@convex-dev/agent 0.0.1-alpha.2 → 0.0.1-alpha.4

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 (60) hide show
  1. package/README.md +91 -95
  2. package/dist/commonjs/client/index.d.ts +60 -60
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +80 -77
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/types.d.ts +1 -1
  7. package/dist/commonjs/client/types.d.ts.map +1 -1
  8. package/dist/commonjs/component/messages.d.ts +56 -56
  9. package/dist/commonjs/component/messages.d.ts.map +1 -1
  10. package/dist/commonjs/component/messages.js +128 -134
  11. package/dist/commonjs/component/messages.js.map +1 -1
  12. package/dist/commonjs/component/schema.d.ts +256 -256
  13. package/dist/commonjs/component/schema.d.ts.map +1 -1
  14. package/dist/commonjs/component/schema.js +18 -18
  15. package/dist/commonjs/component/schema.js.map +1 -1
  16. package/dist/commonjs/component/vector/index.d.ts +4 -4
  17. package/dist/commonjs/component/vector/index.d.ts.map +1 -1
  18. package/dist/commonjs/component/vector/index.js +12 -10
  19. package/dist/commonjs/component/vector/index.js.map +1 -1
  20. package/dist/commonjs/component/vector/tables.d.ts +3 -3
  21. package/dist/commonjs/component/vector/tables.js +6 -6
  22. package/dist/commonjs/component/vector/tables.js.map +1 -1
  23. package/dist/commonjs/validators.d.ts +5 -5
  24. package/dist/commonjs/validators.d.ts.map +1 -1
  25. package/dist/commonjs/validators.js +3 -3
  26. package/dist/commonjs/validators.js.map +1 -1
  27. package/dist/esm/client/index.d.ts +60 -60
  28. package/dist/esm/client/index.d.ts.map +1 -1
  29. package/dist/esm/client/index.js +80 -77
  30. package/dist/esm/client/index.js.map +1 -1
  31. package/dist/esm/client/types.d.ts +1 -1
  32. package/dist/esm/client/types.d.ts.map +1 -1
  33. package/dist/esm/component/messages.d.ts +56 -56
  34. package/dist/esm/component/messages.d.ts.map +1 -1
  35. package/dist/esm/component/messages.js +128 -134
  36. package/dist/esm/component/messages.js.map +1 -1
  37. package/dist/esm/component/schema.d.ts +256 -256
  38. package/dist/esm/component/schema.d.ts.map +1 -1
  39. package/dist/esm/component/schema.js +18 -18
  40. package/dist/esm/component/schema.js.map +1 -1
  41. package/dist/esm/component/vector/index.d.ts +4 -4
  42. package/dist/esm/component/vector/index.d.ts.map +1 -1
  43. package/dist/esm/component/vector/index.js +12 -10
  44. package/dist/esm/component/vector/index.js.map +1 -1
  45. package/dist/esm/component/vector/tables.d.ts +3 -3
  46. package/dist/esm/component/vector/tables.js +6 -6
  47. package/dist/esm/component/vector/tables.js.map +1 -1
  48. package/dist/esm/validators.d.ts +5 -5
  49. package/dist/esm/validators.d.ts.map +1 -1
  50. package/dist/esm/validators.js +3 -3
  51. package/dist/esm/validators.js.map +1 -1
  52. package/package.json +2 -2
  53. package/src/client/index.ts +133 -127
  54. package/src/client/types.ts +1 -1
  55. package/src/component/_generated/api.d.ts +53 -53
  56. package/src/component/messages.ts +139 -145
  57. package/src/component/schema.ts +18 -18
  58. package/src/component/vector/index.ts +13 -11
  59. package/src/component/vector/tables.ts +6 -6
  60. package/src/validators.ts +6 -3
@@ -3,74 +3,74 @@ import { paginator } from "convex-helpers/server/pagination";
3
3
  import { mergedStream, stream } from "convex-helpers/server/stream";
4
4
  import { nullable, partial } from "convex-helpers/validators";
5
5
  import { DEFAULT_MESSAGE_RANGE, extractText, isTool } from "../shared.js";
6
- import { vChatStatus, vMessageStatus, vMessageWithFileAndId, vSearchOptions, vStepWithMessagesWithFileAndId, } from "../validators.js";
6
+ import { vThreadStatus, vMessageStatus, vMessageWithFileAndId, vSearchOptions, vStepWithMessagesWithFileAndId, } from "../validators.js";
7
7
  import { api, internal } from "./_generated/api.js";
8
8
  import { action, internalMutation, internalQuery, mutation, query, } from "./_generated/server.js";
9
9
  import { schema, v } from "./schema.js";
10
10
  import { getVectorTableName, VectorDimensions, vVectorId, } from "./vector/tables.js";
11
- export const getChat = query({
12
- args: { chatId: v.id("chats") },
11
+ export const getThread = query({
12
+ args: { threadId: v.id("threads") },
13
13
  handler: async (ctx, args) => {
14
- return ctx.db.get(args.chatId);
14
+ return ctx.db.get(args.threadId);
15
15
  },
16
- returns: v.union(v.doc("chats"), v.null()),
16
+ returns: v.union(v.doc("threads"), v.null()),
17
17
  });
18
- export const getChatsByUserId = query({
18
+ export const getThreadsByUserId = query({
19
19
  args: {
20
20
  userId: v.string(),
21
21
  // Note: the other arguments cannot change from when the cursor was created.
22
22
  cursor: v.optional(v.union(v.string(), v.null())),
23
23
  limit: v.optional(v.number()),
24
24
  offset: v.optional(v.number()),
25
- statuses: v.optional(v.array(vChatStatus)),
25
+ statuses: v.optional(v.array(vThreadStatus)),
26
26
  },
27
27
  handler: async (ctx, args) => {
28
28
  const streams = (args.statuses ?? ["active"]).map((status) => stream(ctx.db, schema)
29
- .query("chats")
29
+ .query("threads")
30
30
  .withIndex("status_userId_order", (q) => q
31
31
  .eq("status", status)
32
32
  .eq("userId", args.userId)
33
33
  .gte("order", args.offset ?? 0)));
34
- const chats = await mergedStream(streams, ["order"]).paginate({
34
+ const threads = await mergedStream(streams, ["order"]).paginate({
35
35
  numItems: args.limit ?? 100,
36
36
  cursor: args.cursor ?? null,
37
37
  });
38
38
  return {
39
- chats: chats.page,
40
- continueCursor: chats.continueCursor,
41
- isDone: chats.isDone,
39
+ threads: threads.page,
40
+ continueCursor: threads.continueCursor,
41
+ isDone: threads.isDone,
42
42
  };
43
43
  },
44
44
  returns: v.object({
45
- chats: v.array(v.doc("chats")),
45
+ threads: v.array(v.doc("threads")),
46
46
  continueCursor: v.string(),
47
47
  isDone: v.boolean(),
48
48
  }),
49
49
  });
50
- const vChat = schema.tables.chats.validator;
51
- const statuses = vChat.fields.status.members.map((m) => m.value);
52
- export const createChat = mutation({
53
- args: omit(vChat.fields, ["order", "status"]),
50
+ const vThread = schema.tables.threads.validator;
51
+ const statuses = vThread.fields.status.members.map((m) => m.value);
52
+ export const createThread = mutation({
53
+ args: omit(vThread.fields, ["order", "status"]),
54
54
  handler: async (ctx, args) => {
55
55
  const streams = statuses.map((status) => stream(ctx.db, schema)
56
- .query("chats")
56
+ .query("threads")
57
57
  .withIndex("status_userId_order", (q) => q.eq("status", status).eq("userId", args.userId))
58
58
  .order("desc"));
59
- const latestChat = await mergedStream(streams, ["order"]).first();
60
- const order = (latestChat?.order ?? -1) + 1;
61
- const chatId = await ctx.db.insert("chats", {
59
+ const latestThread = await mergedStream(streams, ["order"]).first();
60
+ const order = (latestThread?.order ?? -1) + 1;
61
+ const threadId = await ctx.db.insert("threads", {
62
62
  ...args,
63
63
  order,
64
64
  status: "active",
65
65
  });
66
- return (await ctx.db.get(chatId));
66
+ return (await ctx.db.get(threadId));
67
67
  },
68
- returns: v.doc("chats"),
68
+ returns: v.doc("threads"),
69
69
  });
70
- export const updateChat = mutation({
70
+ export const updateThread = mutation({
71
71
  args: {
72
- chatId: v.id("chats"),
73
- patch: v.object(partial(pick(vChat.fields, [
72
+ threadId: v.id("threads"),
73
+ patch: v.object(partial(pick(vThread.fields, [
74
74
  "title",
75
75
  "summary",
76
76
  "defaultSystemPrompt",
@@ -78,37 +78,37 @@ export const updateChat = mutation({
78
78
  ]))),
79
79
  },
80
80
  handler: async (ctx, args) => {
81
- const chat = await ctx.db.get(args.chatId);
82
- assert(chat, `Chat ${args.chatId} not found`);
83
- await ctx.db.patch(args.chatId, args.patch);
84
- return (await ctx.db.get(args.chatId));
81
+ const thread = await ctx.db.get(args.threadId);
82
+ assert(thread, `Thread ${args.threadId} not found`);
83
+ await ctx.db.patch(args.threadId, args.patch);
84
+ return (await ctx.db.get(args.threadId));
85
85
  },
86
- returns: v.doc("chats"),
86
+ returns: v.doc("threads"),
87
87
  });
88
- export const archiveChat = mutation({
89
- args: { chatId: v.id("chats") },
88
+ export const archiveThread = mutation({
89
+ args: { threadId: v.id("threads") },
90
90
  handler: async (ctx, args) => {
91
- const chat = await ctx.db.get(args.chatId);
92
- assert(chat, `Chat ${args.chatId} not found`);
93
- await ctx.db.patch(args.chatId, { status: "archived" });
94
- return (await ctx.db.get(args.chatId));
91
+ const thread = await ctx.db.get(args.threadId);
92
+ assert(thread, `Thread ${args.threadId} not found`);
93
+ await ctx.db.patch(args.threadId, { status: "archived" });
94
+ return (await ctx.db.get(args.threadId));
95
95
  },
96
- returns: v.doc("chats"),
96
+ returns: v.doc("threads"),
97
97
  });
98
98
  export const deleteAllForUserId = action({
99
99
  args: { userId: v.string() },
100
100
  handler: async (ctx, args) => {
101
101
  let messagesCursor = null;
102
- let chatsCursor = null;
102
+ let threadsCursor = null;
103
103
  let isDone = false;
104
104
  while (!isDone) {
105
105
  const result = await ctx.runMutation(internal.messages._deletePageForUserId, {
106
106
  userId: args.userId,
107
107
  messagesCursor,
108
- chatsCursor,
108
+ threadsCursor,
109
109
  });
110
110
  messagesCursor = result.messagesCursor;
111
- chatsCursor = result.chatsCursor;
111
+ threadsCursor = result.threadsCursor;
112
112
  isDone = result.isDone;
113
113
  }
114
114
  },
@@ -122,7 +122,7 @@ export const deleteAllForUserIdAsync = mutation({
122
122
  const isDone = await deleteAllFroUserIdAsyncHandler(ctx, {
123
123
  userId: args.userId,
124
124
  messagesCursor: null,
125
- chatsCursor: null,
125
+ threadsCursor: null,
126
126
  });
127
127
  return isDone;
128
128
  },
@@ -131,11 +131,11 @@ export const deleteAllForUserIdAsync = mutation({
131
131
  const deleteAllArgs = {
132
132
  userId: v.string(),
133
133
  messagesCursor: nullable(v.string()),
134
- chatsCursor: nullable(v.string()),
134
+ threadsCursor: nullable(v.string()),
135
135
  };
136
136
  const deleteAllReturns = {
137
137
  messagesCursor: v.string(),
138
- chatsCursor: nullable(v.string()),
138
+ threadsCursor: nullable(v.string()),
139
139
  isDone: v.boolean(),
140
140
  };
141
141
  export const _deleteAllForUserIdAsync = internalMutation({
@@ -149,7 +149,7 @@ async function deleteAllFroUserIdAsyncHandler(ctx, args) {
149
149
  await ctx.scheduler.runAfter(0, internal.messages._deleteAllForUserIdAsync, {
150
150
  userId: args.userId,
151
151
  messagesCursor: result.messagesCursor,
152
- chatsCursor: result.chatsCursor,
152
+ threadsCursor: result.threadsCursor,
153
153
  });
154
154
  }
155
155
  return result.isDone;
@@ -161,34 +161,34 @@ export const _deletePageForUserId = internalMutation({
161
161
  });
162
162
  async function deletePageForUserId(ctx, args) {
163
163
  const streams = statuses.map((status) => stream(ctx.db, schema)
164
- .query("chats")
164
+ .query("threads")
165
165
  .withIndex("status_userId_order", (q) => q.eq("status", status).eq("userId", args.userId))
166
166
  .order("desc"));
167
- const chatStreams = mergedStream(streams, ["order"]);
168
- const messages = await chatStreams
167
+ const threadStreams = mergedStream(streams, ["order"]);
168
+ const messages = await threadStreams
169
169
  .flatMap(async (c) => stream(ctx.db, schema)
170
170
  .query("messages")
171
- .withIndex("chatId_status_tool_order_stepOrder", (q) => q.eq("chatId", c._id).eq("status", "success")), ["tool", "order", "stepOrder"])
171
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => q.eq("threadId", c._id).eq("status", "success")), ["tool", "order", "stepOrder"])
172
172
  .paginate({
173
173
  numItems: 100,
174
174
  cursor: args.messagesCursor ?? null,
175
175
  });
176
176
  await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
177
177
  if (messages.isDone) {
178
- const chats = await chatStreams.paginate({
178
+ const threads = await threadStreams.paginate({
179
179
  numItems: 100,
180
- cursor: args.chatsCursor ?? null,
180
+ cursor: args.threadsCursor ?? null,
181
181
  });
182
- await Promise.all(chats.page.map((c) => ctx.db.delete(c._id)));
182
+ await Promise.all(threads.page.map((c) => ctx.db.delete(c._id)));
183
183
  return {
184
184
  messagesCursor: messages.continueCursor,
185
- chatsCursor: chats.continueCursor,
186
- isDone: chats.isDone,
185
+ threadsCursor: threads.continueCursor,
186
+ isDone: threads.isDone,
187
187
  };
188
188
  }
189
189
  return {
190
190
  messagesCursor: messages.continueCursor,
191
- chatsCursor: null,
191
+ threadsCursor: null,
192
192
  isDone: messages.isDone,
193
193
  };
194
194
  }
@@ -201,52 +201,52 @@ async function deleteMessage(ctx, messageDoc) {
201
201
  }
202
202
  }
203
203
  }
204
- const deleteChatArgs = {
205
- chatId: v.id("chats"),
204
+ const deleteThreadArgs = {
205
+ threadId: v.id("threads"),
206
206
  cursor: v.optional(v.string()),
207
207
  limit: v.optional(v.number()),
208
208
  };
209
- const deleteChatReturns = {
209
+ const deleteThreadReturns = {
210
210
  cursor: v.string(),
211
211
  isDone: v.boolean(),
212
212
  };
213
- export const deleteAllForChatIdSync = action({
214
- args: deleteChatArgs,
213
+ export const deleteAllForThreadIdSync = action({
214
+ args: deleteThreadArgs,
215
215
  handler: async (ctx, args) => {
216
- const result = await ctx.runMutation(internal.messages._deletePageForChatId, { chatId: args.chatId, cursor: args.cursor, limit: args.limit });
216
+ const result = await ctx.runMutation(internal.messages._deletePageForThreadId, { threadId: args.threadId, cursor: args.cursor, limit: args.limit });
217
217
  return result;
218
218
  },
219
- returns: deleteChatReturns,
219
+ returns: deleteThreadReturns,
220
220
  });
221
- export const deleteAllForChatIdAsync = mutation({
222
- args: deleteChatArgs,
221
+ export const deleteAllForThreadIdAsync = mutation({
222
+ args: deleteThreadArgs,
223
223
  handler: async (ctx, args) => {
224
- const result = await deletePageForChatIdHandler(ctx, args);
224
+ const result = await deletePageForThreadIdHandler(ctx, args);
225
225
  if (!result.isDone) {
226
- await ctx.scheduler.runAfter(0, api.messages.deleteAllForChatIdAsync, {
227
- chatId: args.chatId,
226
+ await ctx.scheduler.runAfter(0, api.messages.deleteAllForThreadIdAsync, {
227
+ threadId: args.threadId,
228
228
  cursor: result.cursor,
229
229
  });
230
230
  }
231
231
  return result;
232
232
  },
233
- returns: deleteChatReturns,
233
+ returns: deleteThreadReturns,
234
234
  });
235
- export const _deletePageForChatId = internalMutation({
236
- args: deleteChatArgs,
237
- handler: deletePageForChatIdHandler,
238
- returns: deleteChatReturns,
235
+ export const _deletePageForThreadId = internalMutation({
236
+ args: deleteThreadArgs,
237
+ handler: deletePageForThreadIdHandler,
238
+ returns: deleteThreadReturns,
239
239
  });
240
- async function deletePageForChatIdHandler(ctx, args) {
240
+ async function deletePageForThreadIdHandler(ctx, args) {
241
241
  const messages = await stream(ctx.db, schema)
242
242
  .query("messages")
243
- .withIndex("chatId_status_tool_order_stepOrder", (q) => q.eq("chatId", args.chatId).eq("status", "success"))
243
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => q.eq("threadId", args.threadId).eq("status", "success"))
244
244
  .paginate({
245
245
  numItems: args.limit ?? 100,
246
246
  cursor: args.cursor ?? null,
247
247
  });
248
248
  await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
249
- await ctx.db.delete(args.chatId);
249
+ await ctx.db.delete(args.threadId);
250
250
  return {
251
251
  cursor: messages.continueCursor,
252
252
  isDone: messages.isDone,
@@ -281,7 +281,7 @@ export const vMessageDoc = schema.tables.messages.validator;
281
281
  export const messageStatuses = vMessageDoc.fields.status.members.map((m) => m.value);
282
282
  const addMessagesArgs = {
283
283
  userId: v.optional(v.string()),
284
- chatId: v.optional(v.id("chats")),
284
+ threadId: v.optional(v.id("threads")),
285
285
  stepId: v.optional(v.id("steps")),
286
286
  parentMessageId: v.optional(v.id("messages")),
287
287
  messages: v.array(vMessageWithFileAndId),
@@ -300,29 +300,23 @@ export const addMessages = mutation({
300
300
  });
301
301
  async function addMessagesHandler(ctx, args) {
302
302
  let userId = args.userId;
303
- const chatId = args.chatId;
304
- if (!userId && args.chatId) {
305
- const chat = await ctx.db.get(args.chatId);
306
- assert(chat, `Chat ${args.chatId} not found`);
307
- userId = chat._id;
303
+ const threadId = args.threadId;
304
+ if (!userId && args.threadId) {
305
+ const thread = await ctx.db.get(args.threadId);
306
+ assert(thread, `Thread ${args.threadId} not found`);
307
+ userId = thread._id;
308
308
  }
309
309
  const { failPendingSteps, pending, messages, parentMessageId, ...rest } = args;
310
310
  const parent = parentMessageId && (await ctx.db.get(parentMessageId));
311
311
  if (failPendingSteps && parent?.status !== "pending") {
312
- assert(args.chatId, "chatId is required to fail pending steps");
312
+ assert(args.threadId, "threadId is required to fail pending steps");
313
313
  const pendingMessages = await ctx.db
314
314
  .query("messages")
315
- .withIndex("chatId_status_tool_order_stepOrder", (q) => q.eq("chatId", chatId).eq("status", "pending"))
315
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => q.eq("threadId", threadId).eq("status", "pending"))
316
316
  .collect();
317
317
  await Promise.all(pendingMessages.map((m) => ctx.db.patch(m._id, { status: "failed", text: "Restarting" })));
318
318
  }
319
- let threadId = parentMessageId;
320
- const maxMessage = await getMaxMessage(ctx, chatId, userId);
321
- // If the previous message isn't our parent, we make a new thread.
322
- threadId =
323
- parentMessageId && maxMessage?._id === parentMessageId
324
- ? maxMessage.threadId ?? parentMessageId
325
- : parentMessageId;
319
+ const maxMessage = await getMaxMessage(ctx, threadId, userId);
326
320
  let order = maxMessage?.order ?? -1;
327
321
  const toReturn = [];
328
322
  if (messages.length > 0) {
@@ -334,7 +328,7 @@ async function addMessagesHandler(ctx, args) {
334
328
  const text = extractText(message);
335
329
  const messageId = await ctx.db.insert("messages", {
336
330
  ...rest,
337
- threadId,
331
+ parentMessageId,
338
332
  userId,
339
333
  message,
340
334
  id,
@@ -349,12 +343,12 @@ async function addMessagesHandler(ctx, args) {
349
343
  }
350
344
  return { messages: toReturn };
351
345
  }
352
- async function getMaxMessage(ctx, chatId, userId) {
353
- assert(chatId || userId, "One of chatId or userId is required");
354
- if (chatId) {
346
+ async function getMaxMessage(ctx, threadId, userId) {
347
+ assert(threadId || userId, "One of threadId or userId is required");
348
+ if (threadId) {
355
349
  return mergedStream(["success", "pending"].map((status) => stream(ctx.db, schema)
356
350
  .query("messages")
357
- .withIndex("chatId_status_tool_order_stepOrder", (q) => q.eq("chatId", chatId).eq("status", status).eq("tool", false))
351
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => q.eq("threadId", threadId).eq("status", status).eq("tool", false))
358
352
  .order("desc")), ["order", "stepOrder"]).first();
359
353
  }
360
354
  else {
@@ -365,7 +359,7 @@ async function getMaxMessage(ctx, chatId, userId) {
365
359
  }
366
360
  }
367
361
  const addStepsArgs = {
368
- chatId: v.id("chats"),
362
+ threadId: v.id("threads"),
369
363
  messageId: v.id("messages"),
370
364
  steps: v.array(vStepWithMessagesWithFileAndId),
371
365
  failPendingSteps: v.optional(v.boolean()),
@@ -397,7 +391,7 @@ async function addStepsHandler(ctx, args) {
397
391
  let nextStepOrder = (steps.at(-1)?.stepOrder ?? -1) + 1;
398
392
  for (const { step, messages } of args.steps) {
399
393
  const stepId = await ctx.db.insert("steps", {
400
- chatId: args.chatId,
394
+ threadId: args.threadId,
401
395
  parentMessageId: args.messageId,
402
396
  order,
403
397
  stepOrder: nextStepOrder,
@@ -405,7 +399,7 @@ async function addStepsHandler(ctx, args) {
405
399
  step,
406
400
  });
407
401
  await addMessagesHandler(ctx, {
408
- chatId: args.chatId,
402
+ threadId: args.threadId,
409
403
  parentMessageId: args.messageId,
410
404
  stepId,
411
405
  messages,
@@ -460,8 +454,8 @@ async function commitMessageHandler(ctx, { messageId }) {
460
454
  const order = message.order;
461
455
  const messages = await mergedStream([true, false].map((tool) => stream(ctx.db, schema)
462
456
  .query("messages")
463
- .withIndex("chatId_status_tool_order_stepOrder", (q) => q
464
- .eq("chatId", message.chatId)
457
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => q
458
+ .eq("threadId", message.threadId)
465
459
  .eq("status", "pending")
466
460
  .eq("tool", tool)
467
461
  .eq("order", order))), ["order", "stepOrder"]).collect();
@@ -470,9 +464,9 @@ async function commitMessageHandler(ctx, { messageId }) {
470
464
  // TODO: recursively commit steps & messages that might depend on this one.
471
465
  }
472
466
  }
473
- export const getChatMessages = query({
467
+ export const getThreadMessages = query({
474
468
  args: {
475
- chatId: v.id("chats"),
469
+ threadId: v.id("threads"),
476
470
  isTool: v.optional(v.boolean()),
477
471
  order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
478
472
  limit: v.optional(v.number()),
@@ -488,9 +482,9 @@ export const getChatMessages = query({
488
482
  const order = args.order ?? "desc";
489
483
  const streams = toolOptions.flatMap((tool) => statuses.map((status) => stream(ctx.db, schema)
490
484
  .query("messages")
491
- .withIndex("chatId_status_tool_order_stepOrder", (q) => {
485
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => {
492
486
  const qq = q
493
- .eq("chatId", args.chatId)
487
+ .eq("threadId", args.threadId)
494
488
  .eq("status", status)
495
489
  .eq("tool", tool);
496
490
  if (parent) {
@@ -521,19 +515,19 @@ export const getChatMessages = query({
521
515
  export const searchMessages = action({
522
516
  args: {
523
517
  userId: v.optional(v.string()),
524
- chatId: v.optional(v.id("chats")),
518
+ threadId: v.optional(v.id("threads")),
525
519
  parentMessageId: v.optional(v.id("messages")),
526
520
  ...vSearchOptions.fields,
527
521
  },
528
522
  returns: v.array(v.doc("messages")),
529
523
  handler: async (ctx, args) => {
530
- assert(args.userId || args.chatId, "Specify userId or chatId");
524
+ assert(args.userId || args.threadId, "Specify userId or threadId");
531
525
  const limit = args.limit;
532
526
  let textSearchMessages;
533
527
  if (args.text) {
534
528
  textSearchMessages = await ctx.runQuery(api.messages.textSearch, {
535
529
  userId: args.userId,
536
- chatId: args.chatId,
530
+ threadId: args.threadId,
537
531
  text: args.text,
538
532
  limit,
539
533
  });
@@ -548,8 +542,8 @@ export const searchMessages = action({
548
542
  const vectors = (await ctx.vectorSearch(tableName, "vector", {
549
543
  vector: args.vector,
550
544
  filter: (q) => args.userId
551
- ? q.eq("model_kind_userId", [model, "chat", args.userId])
552
- : q.eq("model_kind_chatId", [model, "chat", args.chatId]),
545
+ ? q.eq("model_kind_userId", [model, "thread", args.userId])
546
+ : q.eq("model_kind_threadId", [model, "thread", args.threadId]),
553
547
  limit,
554
548
  })).filter((v) => v._score > 0.5);
555
549
  // Reciprocal rank fusion
@@ -565,7 +559,7 @@ export const searchMessages = action({
565
559
  const vectorIds = vectorScores.slice(0, limit).map((v) => v.id);
566
560
  const messages = await ctx.runQuery(internal.messages._fetchVectorMessages, {
567
561
  userId: args.userId,
568
- chatId: args.chatId,
562
+ threadId: args.threadId,
569
563
  vectorIds,
570
564
  textSearchMessages: textSearchMessages?.filter((m) => !vectorIds.includes(m.embeddingId)),
571
565
  messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
@@ -580,7 +574,7 @@ export const searchMessages = action({
580
574
  export const _fetchVectorMessages = internalQuery({
581
575
  args: {
582
576
  userId: v.optional(v.string()),
583
- chatId: v.optional(v.id("chats")),
577
+ threadId: v.optional(v.id("threads")),
584
578
  vectorIds: v.array(vVectorId),
585
579
  textSearchMessages: v.optional(v.array(v.doc("messages"))),
586
580
  messageRange: v.object({ before: v.number(), after: v.number() }),
@@ -590,27 +584,27 @@ export const _fetchVectorMessages = internalQuery({
590
584
  returns: v.array(v.doc("messages")),
591
585
  handler: async (ctx, args) => {
592
586
  const parent = args.parentMessageId && (await ctx.db.get(args.parentMessageId));
593
- const { userId, chatId } = args;
594
- assert(userId || chatId, "Specify userId or chatId to search");
587
+ const { userId, threadId } = args;
588
+ assert(userId || threadId, "Specify userId or threadId to search");
595
589
  let messages = (await Promise.all(args.vectorIds.map((embeddingId) => ctx.db
596
590
  .query("messages")
597
591
  .withIndex("embeddingId", (q) => q.eq("embeddingId", embeddingId))
598
592
  .filter((q) => userId
599
593
  ? q.eq("userId", userId)
600
594
  : // eslint-disable-next-line @typescript-eslint/no-explicit-any
601
- q.eq("chatId", chatId))
595
+ q.eq("threadId", threadId))
602
596
  .first()))).filter((m) => m !== undefined && m !== null && (!parent || m.order <= parent.order));
603
597
  messages.push(...(args.textSearchMessages ?? []));
604
598
  // TODO: prioritize more recent messages
605
599
  messages.sort((a, b) => a.order - b.order);
606
600
  messages = messages.slice(0, args.limit);
607
601
  // Fetch the surrounding messages
608
- if (!chatId) {
602
+ if (!threadId) {
609
603
  return messages.sort((a, b) => a.order - b.order);
610
604
  }
611
605
  const included = {};
612
606
  for (const m of messages) {
613
- const searchId = m.chatId ?? m.userId;
607
+ const searchId = m.threadId ?? m.userId;
614
608
  if (!included[searchId]) {
615
609
  included[searchId] = new Set();
616
610
  }
@@ -619,7 +613,7 @@ export const _fetchVectorMessages = internalQuery({
619
613
  const ranges = {};
620
614
  const { before, after } = args.messageRange;
621
615
  for (const m of messages) {
622
- const searchId = m.chatId ?? m.userId;
616
+ const searchId = m.threadId ?? m.userId;
623
617
  const order = m.order;
624
618
  let earliest = order - before;
625
619
  let latest = order + after;
@@ -637,11 +631,11 @@ export const _fetchVectorMessages = internalQuery({
637
631
  included[searchId].add(i);
638
632
  }
639
633
  if (earliest !== latest) {
640
- if (m.chatId) {
634
+ if (m.threadId) {
641
635
  const surrounding = await ctx.db
642
636
  .query("messages")
643
- .withIndex("chatId_status_tool_order_stepOrder", (q) => q
644
- .eq("chatId", m.chatId)
637
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => q
638
+ .eq("threadId", m.threadId)
645
639
  .eq("status", "success")
646
640
  .eq("tool", false)
647
641
  .gt("order", earliest)
@@ -678,18 +672,18 @@ export const _fetchVectorMessages = internalQuery({
678
672
  // excluding duplicates in later ranges.
679
673
  export const textSearch = query({
680
674
  args: {
681
- chatId: v.optional(v.id("chats")),
675
+ threadId: v.optional(v.id("threads")),
682
676
  userId: v.optional(v.string()),
683
677
  text: v.string(),
684
678
  limit: v.number(),
685
679
  },
686
680
  handler: async (ctx, args) => {
687
- assert(args.userId || args.chatId, "Specify userId or chatId");
681
+ assert(args.userId || args.threadId, "Specify userId or threadId");
688
682
  const messages = await ctx.db
689
683
  .query("messages")
690
684
  .withSearchIndex("text_search", (q) => args.userId
691
685
  ? q.search("text", args.text).eq("userId", args.userId)
692
- : q.search("text", args.text).eq("chatId", args.chatId))
686
+ : q.search("text", args.text).eq("threadId", args.threadId))
693
687
  .take(args.limit);
694
688
  return messages;
695
689
  },
@@ -738,9 +732,9 @@ export const textSearch = query({
738
732
  // ),
739
733
  // });
740
734
  // const DEFAULT_MESSAGES_LIMIT = 40; // What pg & upstash do too.
741
- // export const getChatMessagesPage = query({
735
+ // export const getThreadMessagesPage = query({
742
736
  // args: {
743
- // threadId: v.string(),
737
+ // parentMessageId: v.string(),
744
738
  // selectBy: v.optional(vSelectBy),
745
739
  // // Unimplemented and as far I can tell no storage provider has either.
746
740
  // // memoryConfig: v.optional(vMemoryConfig),
@@ -748,7 +742,7 @@ export const textSearch = query({
748
742
  // handler: async (ctx, args): Promise<SerializedMessage[]> => {
749
743
  // const messages = await ctx.db
750
744
  // .query("messages")
751
- // .withIndex("threadId", (q) => q.eq("threadId", args.threadId))
745
+ // .withIndex("parentMessageId", (q) => q.eq("parentMessageId", args.parentMessageId))
752
746
  // .order("desc")
753
747
  // .take(args.selectBy?.last ? args.selectBy.last : DEFAULT_MESSAGES_LIMIT);
754
748
  // const handled: boolean[] = [];
@@ -801,9 +795,9 @@ export const textSearch = query({
801
795
  // ranges.map(async (range) => {
802
796
  // return await ctx.db
803
797
  // .query("messages")
804
- // .withIndex("threadId", (q) =>
798
+ // .withIndex("parentMessageId", (q) =>
805
799
  // q
806
- // .eq("threadId", args.threadId)
800
+ // .eq("parentMessageId", args.parentMessageId)
807
801
  // .gte("threadOrder", range.start)
808
802
  // .lte("threadOrder", range.end)
809
803
  // )
@@ -819,21 +813,21 @@ export const textSearch = query({
819
813
  // export const saveMessages = mutation({
820
814
  // args: { messages: v.array(vSerializedMessage) },
821
815
  // handler: async (ctx, args) => {
822
- // const messagesByThreadId: Record<string, SerializedMessage[]> = {};
816
+ // const messagesByParentMessageId: Record<string, SerializedMessage[]> = {};
823
817
  // for (const message of args.messages) {
824
- // messagesByThreadId[message.threadId] = [
825
- // ...(messagesByThreadId[message.threadId] ?? []),
818
+ // messagesByParentMessageId[message.parentMessageId] = [
819
+ // ...(messagesByParentMessageId[message.parentMessageId] ?? []),
826
820
  // message,
827
821
  // ];
828
822
  // }
829
- // for (const threadId in messagesByThreadId) {
823
+ // for (const parentMessageId in messagesByParentMessageId) {
830
824
  // const lastMessage = await ctx.db
831
825
  // .query("messages")
832
- // .withIndex("threadId", (q) => q.eq("threadId", threadId))
826
+ // .withIndex("parentMessageId", (q) => q.eq("parentMessageId", parentMessageId))
833
827
  // .order("desc")
834
828
  // .first();
835
829
  // let threadOrder = lastMessage?.threadOrder ?? 0;
836
- // for (const message of messagesByThreadId[threadId]) {
830
+ // for (const message of messagesByParentMessageId[parentMessageId]) {
837
831
  // threadOrder++;
838
832
  // await ctx.db.insert("messages", {
839
833
  // ...message,