@convex-dev/agent 0.1.16-alpha.0 → 0.1.16-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 (62) hide show
  1. package/README.md +26 -15
  2. package/dist/client/createTool.d.ts +2 -2
  3. package/dist/client/createTool.d.ts.map +1 -1
  4. package/dist/client/createTool.js.map +1 -1
  5. package/dist/client/files.js +2 -2
  6. package/dist/client/files.js.map +1 -1
  7. package/dist/client/index.d.ts +2 -1
  8. package/dist/client/index.d.ts.map +1 -1
  9. package/dist/client/index.js +47 -29
  10. package/dist/client/index.js.map +1 -1
  11. package/dist/client/search.d.ts +2 -3
  12. package/dist/client/search.d.ts.map +1 -1
  13. package/dist/client/search.js +2 -1
  14. package/dist/client/search.js.map +1 -1
  15. package/dist/client/types.d.ts +7 -9
  16. package/dist/client/types.d.ts.map +1 -1
  17. package/dist/component/messages.d.ts +1 -1
  18. package/dist/component/messages.d.ts.map +1 -1
  19. package/dist/component/messages.js +5 -5
  20. package/dist/component/messages.js.map +1 -1
  21. package/dist/component/schema.d.ts.map +1 -1
  22. package/dist/component/schema.js.map +1 -1
  23. package/dist/mapping.d.ts.map +1 -1
  24. package/dist/mapping.js +3 -1
  25. package/dist/mapping.js.map +1 -1
  26. package/dist/react/deltas.d.ts.map +1 -1
  27. package/dist/react/deltas.js +6 -5
  28. package/dist/react/deltas.js.map +1 -1
  29. package/dist/validators.js +1 -2
  30. package/dist/validators.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/client/createTool.ts +9 -6
  33. package/src/client/files.ts +8 -8
  34. package/src/client/index.test.ts +14 -12
  35. package/src/client/index.ts +127 -99
  36. package/src/client/listMessages.ts +1 -1
  37. package/src/client/search.ts +14 -14
  38. package/src/client/streaming.ts +7 -7
  39. package/src/client/types.ts +29 -23
  40. package/src/component/apiKeys.ts +1 -1
  41. package/src/component/files.test.ts +1 -1
  42. package/src/component/files.ts +6 -6
  43. package/src/component/messages.test.ts +6 -6
  44. package/src/component/messages.ts +44 -43
  45. package/src/component/schema.ts +1 -2
  46. package/src/component/streams.ts +27 -27
  47. package/src/component/threads.test.ts +4 -4
  48. package/src/component/threads.ts +4 -4
  49. package/src/component/users.test.ts +2 -2
  50. package/src/component/users.ts +4 -4
  51. package/src/component/vector/index.ts +11 -11
  52. package/src/component/vector/tables.ts +6 -6
  53. package/src/mapping.test.ts +4 -4
  54. package/src/mapping.ts +18 -17
  55. package/src/react/deltas.test.ts +16 -16
  56. package/src/react/deltas.ts +19 -18
  57. package/src/react/index.ts +11 -11
  58. package/src/react/optimisticallySendMessage.ts +2 -2
  59. package/src/react/toUIMessages.test.ts +10 -10
  60. package/src/react/toUIMessages.ts +6 -6
  61. package/src/react/useSmoothText.ts +6 -6
  62. package/src/validators.ts +24 -24
@@ -16,9 +16,8 @@ import {
16
16
  const DEFAULT_VECTOR_SCORE_THRESHOLD = 0.0;
17
17
 
18
18
  export type GetEmbedding = (text: string) => Promise<{
19
- vector: number[];
20
- vectorModel: string;
21
- vectorScoreThreshold?: number;
19
+ embedding: number[];
20
+ embeddingModel: string;
22
21
  }>;
23
22
 
24
23
  /**
@@ -44,7 +43,7 @@ export async function fetchContextMessages(
44
43
  upToAndIncludingMessageId?: string;
45
44
  contextOptions: ContextOptions;
46
45
  getEmbedding?: GetEmbedding;
47
- }
46
+ },
48
47
  ): Promise<MessageDoc[]> {
49
48
  assert(args.userId || args.threadId, "Specify userId or threadId");
50
49
  const opts = args.contextOptions;
@@ -67,17 +66,17 @@ export async function fetchContextMessages(
67
66
  upToAndIncludingMessageId: args.upToAndIncludingMessageId,
68
67
  order: "desc",
69
68
  statuses: ["success"],
70
- }
69
+ },
71
70
  );
72
71
  included = new Set(page.map((m) => m._id));
73
72
  contextMessages.push(
74
73
  // Reverse since we fetched in descending order
75
- ...page.reverse()
74
+ ...page.reverse(),
76
75
  );
77
76
  }
78
77
  if (opts.searchOptions?.textSearch || opts.searchOptions?.vectorSearch) {
79
78
  const targetMessage = contextMessages.find(
80
- (m) => m._id === args.upToAndIncludingMessageId
79
+ (m) => m._id === args.upToAndIncludingMessageId,
81
80
  )?.message;
82
81
  const messagesToSearch = targetMessage ? [targetMessage] : args.messages;
83
82
  if (!("runAction" in ctx)) {
@@ -89,11 +88,11 @@ export async function fetchContextMessages(
89
88
  assert(text, `No text to search in message ${JSON.stringify(lastMessage)}`);
90
89
  assert(
91
90
  !args.contextOptions?.searchOptions?.vectorSearch || "runAction" in ctx,
92
- "You must do vector search from an action"
91
+ "You must do vector search from an action",
93
92
  );
94
93
  if (opts.searchOptions?.vectorSearch && !args.getEmbedding) {
95
94
  throw new Error(
96
- "You must provide an embedding and embeddingModel to use vector search"
95
+ "You must provide an embedding and embeddingModel to use vector search",
97
96
  );
98
97
  }
99
98
  const embeddingFields = opts.searchOptions?.vectorSearch
@@ -122,20 +121,21 @@ export async function fetchContextMessages(
122
121
  vectorScoreThreshold:
123
122
  opts.searchOptions?.vectorScoreThreshold ??
124
123
  DEFAULT_VECTOR_SCORE_THRESHOLD,
125
- ...embeddingFields,
126
- }
124
+ embedding: embeddingFields?.embedding,
125
+ embeddingModel: embeddingFields?.embeddingModel,
126
+ },
127
127
  );
128
128
  // TODO: track what messages we used for context
129
129
  contextMessages.unshift(
130
- ...searchMessages.filter((m) => !included?.has(m._id))
130
+ ...searchMessages.filter((m) => !included?.has(m._id)),
131
131
  );
132
132
  }
133
133
  // Ensure we don't include tool messages without a corresponding tool call
134
134
  return filterOutOrphanedToolMessages(
135
135
  contextMessages.sort((a, b) =>
136
136
  // Sort the raw MessageDocs by order and stepOrder
137
- a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order
138
- )
137
+ a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order,
138
+ ),
139
139
  );
140
140
  }
141
141
 
@@ -38,7 +38,7 @@ export async function syncStreams(
38
38
  streamArgs: StreamArgs | undefined;
39
39
  // By default, only streaming messages are included.
40
40
  includeStatuses?: ("streaming" | "finished" | "aborted")[];
41
- }
41
+ },
42
42
  ): Promise<SyncStreamsReturnValue | undefined> {
43
43
  if (!args.streamArgs) return undefined;
44
44
  if (args.streamArgs.kind === "list") {
@@ -66,7 +66,7 @@ export async function abortStream(
66
66
  component: AgentComponent,
67
67
  args: {
68
68
  reason: string;
69
- } & ({ streamId: string } | { threadId: string; order: number })
69
+ } & ({ streamId: string } | { threadId: string; order: number }),
70
70
  ): Promise<boolean> {
71
71
  if ("streamId" in args) {
72
72
  return await ctx.runMutation(component.streams.abort, {
@@ -102,7 +102,7 @@ export async function listStreams(
102
102
  threadId: string;
103
103
  startOrder?: number;
104
104
  includeStatuses?: ("streaming" | "finished" | "aborted")[];
105
- }
105
+ },
106
106
  ): Promise<StreamMessage[]> {
107
107
  return ctx.runQuery(component.streams.list, {
108
108
  threadId,
@@ -137,7 +137,7 @@ export function mergeTransforms<TOOLS extends ToolSet>(
137
137
  existing:
138
138
  | StreamTextTransform<TOOLS>
139
139
  | Array<StreamTextTransform<TOOLS>>
140
- | undefined
140
+ | undefined,
141
141
  ) {
142
142
  if (!options) {
143
143
  return existing;
@@ -180,7 +180,7 @@ export class DeltaStreamer {
180
180
  order: number | undefined;
181
181
  stepOrder: number | undefined;
182
182
  abortSignal: AbortSignal | undefined;
183
- }
183
+ },
184
184
  ) {
185
185
  this.options =
186
186
  typeof options === "boolean"
@@ -216,7 +216,7 @@ export class DeltaStreamer {
216
216
  ...omit(this.metadata, ["abortSignal"]),
217
217
  order: this.#nextOrder,
218
218
  stepOrder: this.#nextStepOrder,
219
- }
219
+ },
220
220
  );
221
221
  }
222
222
  this.#nextParts.push(...parts);
@@ -237,7 +237,7 @@ export class DeltaStreamer {
237
237
  try {
238
238
  const success = await this.ctx.runMutation(
239
239
  this.component.streams.addDelta,
240
- delta
240
+ delta,
241
241
  );
242
242
  if (!success) {
243
243
  this.abortController.abort();
@@ -22,13 +22,14 @@ import type {
22
22
  Auth,
23
23
  Expand,
24
24
  FunctionReference,
25
- GenericActionCtx,
26
- GenericDataModel,
27
- GenericMutationCtx,
28
- GenericQueryCtx,
29
25
  StorageActionWriter,
30
26
  StorageReader,
31
27
  WithoutSystemFields,
28
+ FunctionArgs,
29
+ FunctionReturnType,
30
+ GenericActionCtx,
31
+ GenericDataModel,
32
+ OptionalRestArgs,
32
33
  } from "convex/server";
33
34
  import type { GenericId } from "convex/values";
34
35
  import type { Schema } from "zod";
@@ -127,7 +128,7 @@ export type UsageHandler = (
127
128
  providerMetadata: ProviderMetadata | undefined;
128
129
  model: string;
129
130
  provider: string;
130
- }
131
+ },
131
132
  ) => void | Promise<void>;
132
133
 
133
134
  export type RawRequestResponseHandler = (
@@ -138,7 +139,7 @@ export type RawRequestResponseHandler = (
138
139
  agentName: string | undefined;
139
140
  request: LanguageModelRequestMetadata;
140
141
  response: LanguageModelResponseMetadata;
141
- }
142
+ },
142
143
  ) => void | Promise<void>;
143
144
 
144
145
  export type AgentComponent = UseApi<Mounts>;
@@ -335,7 +336,7 @@ export interface Thread<DefaultTools extends ToolSet> {
335
336
  * Update the metadata for the thread.
336
337
  */
337
338
  updateMetadata: (
338
- patch: Partial<WithoutSystemFields<ThreadDoc>>
339
+ patch: Partial<WithoutSystemFields<ThreadDoc>>,
339
340
  ) => Promise<ThreadDoc>;
340
341
  /**
341
342
  * This behaves like {@link generateText} from the "ai" package except that
@@ -358,7 +359,7 @@ export interface Thread<DefaultTools extends ToolSet> {
358
359
  OUTPUT,
359
360
  OUTPUT_PARTIAL
360
361
  >,
361
- options?: Options
362
+ options?: Options,
362
363
  ): Promise<
363
364
  GenerateTextResult<TOOLS extends undefined ? DefaultTools : TOOLS, OUTPUT> &
364
365
  ThreadOutputMetadata
@@ -397,7 +398,7 @@ export interface Thread<DefaultTools extends ToolSet> {
397
398
  * iterating over the text, streaming it over HTTP, etc.
398
399
  */
399
400
  saveStreamDeltas?: boolean | StreamingOptions;
400
- }
401
+ },
401
402
  ): Promise<
402
403
  StreamTextResult<
403
404
  TOOLS extends undefined ? DefaultTools : TOOLS,
@@ -417,7 +418,7 @@ export interface Thread<DefaultTools extends ToolSet> {
417
418
  */
418
419
  generateObject<T>(
419
420
  args: OurObjectArgs<T>,
420
- options?: Options
421
+ options?: Options,
421
422
  ): Promise<GenerateObjectResult<T> & ThreadOutputMetadata>;
422
423
  /**
423
424
  * This behaves like {@link generateObject} from the "ai" package except that
@@ -431,7 +432,7 @@ export interface Thread<DefaultTools extends ToolSet> {
431
432
  */
432
433
  generateObject(
433
434
  args: GenerateObjectNoSchemaOptions,
434
- options?: Options
435
+ options?: Options,
435
436
  ): Promise<GenerateObjectResult<JSONValue> & ThreadOutputMetadata>;
436
437
  /**
437
438
  * This behaves like {@link streamObject} from the "ai" package except that
@@ -445,7 +446,7 @@ export interface Thread<DefaultTools extends ToolSet> {
445
446
  */
446
447
  streamObject<T>(
447
448
  args: OurStreamObjectArgs<T>,
448
- options?: Options
449
+ options?: Options,
449
450
  ): Promise<
450
451
  StreamObjectResult<DeepPartial<T>, T, never> & ThreadOutputMetadata
451
452
  >;
@@ -469,17 +470,24 @@ export type SyncStreamsReturnValue =
469
470
 
470
471
  /* Type utils follow */
471
472
  export type RunQueryCtx = {
472
- runQuery: GenericQueryCtx<GenericDataModel>["runQuery"];
473
+ runQuery: <Query extends FunctionReference<"query", "internal">>(
474
+ query: Query,
475
+ args: FunctionArgs<Query>,
476
+ ) => Promise<FunctionReturnType<Query>>;
473
477
  };
474
- export type RunMutationCtx = {
475
- runQuery: GenericMutationCtx<GenericDataModel>["runQuery"];
476
- runMutation: GenericMutationCtx<GenericDataModel>["runMutation"];
478
+ export type RunMutationCtx = RunQueryCtx & {
479
+ runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(
480
+ mutation: Mutation,
481
+ args: FunctionArgs<Mutation>,
482
+ ) => Promise<FunctionReturnType<Mutation>>;
477
483
  };
478
- export type RunActionCtx = {
479
- runQuery: GenericActionCtx<GenericDataModel>["runQuery"];
480
- runMutation: GenericActionCtx<GenericDataModel>["runMutation"];
481
- runAction: GenericActionCtx<GenericDataModel>["runAction"];
484
+ export type RunActionCtx = RunMutationCtx & {
485
+ runAction<Action extends FunctionReference<"action", "internal">>(
486
+ action: Action,
487
+ args: FunctionArgs<Action>,
488
+ ): Promise<FunctionReturnType<Action>>;
482
489
  };
490
+ export type UserActionCtx = GenericActionCtx<GenericDataModel>;
483
491
  export type ActionCtx = RunActionCtx & {
484
492
  auth: Auth;
485
493
  storage: StorageActionWriter;
@@ -496,9 +504,7 @@ export type OpaqueIds<T> =
496
504
  : T extends ArrayBuffer
497
505
  ? ArrayBuffer
498
506
  : T extends object
499
- ? {
500
- [K in keyof T]: OpaqueIds<T[K]>;
501
- }
507
+ ? { [K in keyof T]: OpaqueIds<T[K]> }
502
508
  : T;
503
509
 
504
510
  export type UseApi<API> = Expand<{
@@ -69,6 +69,6 @@ export const destroy = mutation({
69
69
  v.literal("missing"),
70
70
  v.literal("deleted"),
71
71
  v.literal("name mismatch"),
72
- v.literal("must provide either apiKey or name")
72
+ v.literal("must provide either apiKey or name"),
73
73
  ),
74
74
  });
@@ -22,7 +22,7 @@ describe("files", () => {
22
22
  hash,
23
23
  filename,
24
24
  mimeType: "text/plain",
25
- }
25
+ },
26
26
  );
27
27
  expect(fileId).toBeTruthy();
28
28
  expect(returnedStorageId).toBe(storageId);
@@ -23,7 +23,7 @@ export const addFile = mutation({
23
23
 
24
24
  export async function addFileHandler(
25
25
  ctx: MutationCtx,
26
- args: Infer<typeof addFileArgs>
26
+ args: Infer<typeof addFileArgs>,
27
27
  ) {
28
28
  const existingFile = await ctx.db
29
29
  .query("files")
@@ -93,14 +93,14 @@ export const useExistingFile = mutation({
93
93
  v.object({
94
94
  fileId: v.id("files"),
95
95
  storageId: v.string(),
96
- })
96
+ }),
97
97
  ),
98
98
  });
99
99
 
100
100
  export async function changeRefcount(
101
101
  ctx: MutationCtx,
102
102
  prev: Id<"files">[],
103
- next: Id<"files">[]
103
+ next: Id<"files">[],
104
104
  ) {
105
105
  const prevSet = new Set(prev);
106
106
  const nextSet = new Set(next);
@@ -140,7 +140,7 @@ export const copyFile = mutation({
140
140
 
141
141
  export async function copyFileHandler(
142
142
  ctx: MutationCtx,
143
- args: { fileId: Id<"files"> }
143
+ args: { fileId: Id<"files"> },
144
144
  ) {
145
145
  const file = await ctx.db.get(args.fileId);
146
146
  if (!file) {
@@ -194,14 +194,14 @@ export const deleteFiles = mutation({
194
194
  if (file.refcount && file.refcount > 0) {
195
195
  if (!args.force) {
196
196
  console.error(
197
- `File ${fileId} has refcount ${file.refcount} > 0, skipping...`
197
+ `File ${fileId} has refcount ${file.refcount} > 0, skipping...`,
198
198
  );
199
199
  return null;
200
200
  }
201
201
  }
202
202
  await ctx.db.delete(fileId);
203
203
  return fileId;
204
- })
204
+ }),
205
205
  );
206
206
  return deletedFileIds.filter((fileId) => fileId !== null);
207
207
  },
@@ -280,7 +280,7 @@ describe("agent", () => {
280
280
  patch: {
281
281
  message: { role: "user", content: "test" },
282
282
  },
283
- })
283
+ }),
284
284
  ).rejects.toThrow();
285
285
  });
286
286
 
@@ -311,7 +311,7 @@ describe("agent", () => {
311
311
  {
312
312
  threadId: thread._id as Id<"threads">,
313
313
  order: "asc",
314
- }
314
+ },
315
315
  );
316
316
  expect(remainingMessages.page).toHaveLength(1);
317
317
  expect(remainingMessages.page[0]._id).toBe(messageIds[1]);
@@ -346,7 +346,7 @@ describe("agent", () => {
346
346
  {
347
347
  threadId: thread._id as Id<"threads">,
348
348
  order: "asc",
349
- }
349
+ },
350
350
  );
351
351
  expect(remainingMessages.page).toHaveLength(0);
352
352
  });
@@ -398,7 +398,7 @@ describe("agent", () => {
398
398
  {
399
399
  threadId: thread._id as Id<"threads">,
400
400
  order: "asc",
401
- }
401
+ },
402
402
  );
403
403
 
404
404
  expect(remainingMessages.page).toHaveLength(3); // Should have messages from order 1 and 2
@@ -441,7 +441,7 @@ describe("agent", () => {
441
441
  {
442
442
  threadId: thread._id as Id<"threads">,
443
443
  order: "asc",
444
- }
444
+ },
445
445
  );
446
446
 
447
447
  expect(remainingMessages.page).toHaveLength(2);
@@ -504,7 +504,7 @@ describe("agent", () => {
504
504
  {
505
505
  threadId: thread._id as Id<"threads">,
506
506
  order: "asc",
507
- }
507
+ },
508
508
  );
509
509
  expect(remainingMessages.page).toHaveLength(1);
510
510
  });
@@ -46,7 +46,7 @@ function publicMessage(message: Doc<"messages">): MessageDoc {
46
46
 
47
47
  export async function deleteMessage(
48
48
  ctx: MutationCtx,
49
- messageDoc: Doc<"messages">
49
+ messageDoc: Doc<"messages">,
50
50
  ) {
51
51
  await ctx.db.delete(messageDoc._id);
52
52
  if (messageDoc.embeddingId) {
@@ -71,14 +71,14 @@ export const deleteByIds = mutation({
71
71
  return id;
72
72
  }
73
73
  return null;
74
- })
74
+ }),
75
75
  );
76
76
  return deletedMessageIds.filter((id) => id !== null);
77
77
  },
78
78
  });
79
79
 
80
80
  export const messageStatuses = vMessageDoc.fields.status.members.map(
81
- (m) => m.value
81
+ (m) => m.value,
82
82
  );
83
83
 
84
84
  export const deleteByOrder = mutation({
@@ -99,7 +99,7 @@ export const deleteByOrder = mutation({
99
99
  ctx,
100
100
  args.threadId,
101
101
  "asc",
102
- args.startOrder
102
+ args.startOrder,
103
103
  )
104
104
  .narrow({
105
105
  lowerBound: args.startStepOrder
@@ -140,7 +140,7 @@ export const addMessages = mutation({
140
140
  });
141
141
  async function addMessagesHandler(
142
142
  ctx: MutationCtx,
143
- args: ObjectType<typeof addMessagesArgs>
143
+ args: ObjectType<typeof addMessagesArgs>,
144
144
  ) {
145
145
  let userId = args.userId;
146
146
  const threadId = args.threadId;
@@ -163,15 +163,15 @@ async function addMessagesHandler(
163
163
  const pendingMessages = await ctx.db
164
164
  .query("messages")
165
165
  .withIndex("threadId_status_tool_order_stepOrder", (q) =>
166
- q.eq("threadId", threadId).eq("status", "pending")
166
+ q.eq("threadId", threadId).eq("status", "pending"),
167
167
  )
168
168
  .collect();
169
169
  await Promise.all(
170
170
  pendingMessages
171
171
  .filter((m) => !parentMessage || m.order === parentMessage.order)
172
172
  .map((m) =>
173
- ctx.db.patch(m._id, { status: "failed", error: "Restarting" })
174
- )
173
+ ctx.db.patch(m._id, { status: "failed", error: "Restarting" }),
174
+ ),
175
175
  );
176
176
  }
177
177
  let order, stepOrder;
@@ -194,7 +194,7 @@ async function addMessagesHandler(
194
194
  if (embeddings) {
195
195
  assert(
196
196
  embeddings.vectors.length === messages.length,
197
- "embeddings.vectors.length must match messages.length"
197
+ "embeddings.vectors.length must match messages.length",
198
198
  );
199
199
  }
200
200
  for (let i = 0; i < messages.length; i++) {
@@ -242,7 +242,7 @@ async function addMessagesHandler(
242
242
  export async function getMaxMessage(
243
243
  ctx: QueryCtx,
244
244
  threadId: Id<"threads">,
245
- order?: number
245
+ order?: number,
246
246
  ) {
247
247
  return orderedMessagesStream(ctx, threadId, "desc", order).first();
248
248
  }
@@ -251,7 +251,7 @@ function orderedMessagesStream(
251
251
  ctx: QueryCtx,
252
252
  threadId: Id<"threads">,
253
253
  sortOrder: "asc" | "desc",
254
- order?: number
254
+ order?: number,
255
255
  ) {
256
256
  return mergedStream(
257
257
  [true, false].flatMap((tool) =>
@@ -268,10 +268,10 @@ function orderedMessagesStream(
268
268
  }
269
269
  return qq;
270
270
  })
271
- .order(sortOrder)
272
- )
271
+ .order(sortOrder),
272
+ ),
273
273
  ),
274
- ["order", "stepOrder"]
274
+ ["order", "stepOrder"],
275
275
  );
276
276
  }
277
277
 
@@ -288,7 +288,7 @@ export const rollbackMessage = mutation({
288
288
  ctx,
289
289
  message.threadId,
290
290
  "asc",
291
- message.order
291
+ message.order,
292
292
  ).collect();
293
293
  for (const m of messages) {
294
294
  if (m.status === "pending") {
@@ -347,7 +347,7 @@ export const updateMessage = mutation({
347
347
 
348
348
  async function commitMessageHandler(
349
349
  ctx: MutationCtx,
350
- { messageId }: { messageId: Id<"messages"> }
350
+ { messageId }: { messageId: Id<"messages"> },
351
351
  ) {
352
352
  const message = await ctx.db.get(messageId);
353
353
  assert(message, `Message ${messageId} not found`);
@@ -362,10 +362,10 @@ async function commitMessageHandler(
362
362
  .eq("threadId", message.threadId)
363
363
  .eq("status", "pending")
364
364
  .eq("tool", tool)
365
- .eq("order", order)
366
- )
365
+ .eq("order", order),
366
+ ),
367
367
  ),
368
- ["order", "stepOrder"]
368
+ ["order", "stepOrder"],
369
369
  ).collect();
370
370
  for (const message of messages) {
371
371
  await ctx.db.patch(message._id, { status: "success" });
@@ -390,7 +390,7 @@ export const listMessagesByThreadId = query({
390
390
  (await ctx.db.get(args.upToAndIncludingMessageId));
391
391
  assert(
392
392
  !last || last.threadId === args.threadId,
393
- "upToAndIncludingMessageId must be a message in the thread"
393
+ "upToAndIncludingMessageId must be a message in the thread",
394
394
  );
395
395
  const toolOptions = args.excludeToolMessages ? [false] : [true, false];
396
396
  const order = args.order ?? "desc";
@@ -411,9 +411,10 @@ export const listMessagesByThreadId = query({
411
411
  .order(order)
412
412
  .filterWith(
413
413
  // We allow all messages on the same order.
414
- async (m) => !last || m.order < last.order || m.order === last.order
415
- )
416
- )
414
+ async (m) =>
415
+ !last || m.order < last.order || m.order === last.order,
416
+ ),
417
+ ),
417
418
  );
418
419
  const messages = await mergedStream(streams, [
419
420
  "order",
@@ -422,7 +423,7 @@ export const listMessagesByThreadId = query({
422
423
  args.paginationOpts ?? {
423
424
  numItems: DEFAULT_RECENT_MESSAGES,
424
425
  cursor: null,
425
- }
426
+ },
426
427
  );
427
428
  return { ...messages, page: messages.page.map(publicMessage) };
428
429
  },
@@ -450,14 +451,14 @@ export const searchMessages = action({
450
451
  limit: v.number(),
451
452
  vectorScoreThreshold: v.optional(v.number()),
452
453
  messageRange: v.optional(
453
- v.object({ before: v.number(), after: v.number() })
454
+ v.object({ before: v.number(), after: v.number() }),
454
455
  ),
455
456
  },
456
457
  returns: v.array(vMessageDoc),
457
458
  handler: async (ctx, args): Promise<MessageDoc[]> => {
458
459
  assert(
459
460
  args.searchAllMessagesForUserId || args.threadId,
460
- "Specify userId or threadId"
461
+ "Specify userId or threadId",
461
462
  );
462
463
  const limit = args.limit;
463
464
  let textSearchMessages: MessageDoc[] | undefined;
@@ -496,20 +497,20 @@ export const searchMessages = action({
496
497
  1 / ((textEmbeddingIds?.indexOf(v._id) ?? Infinity) + k),
497
498
  }))
498
499
  .sort((a, b) => b.score - a.score);
499
- const vectorIds = vectorScores.slice(0, limit).map((v) => v.id);
500
+ const embeddingIds = vectorScores.slice(0, limit).map((v) => v.id);
500
501
  const messages: MessageDoc[] = await ctx.runQuery(
501
502
  internal.messages._fetchSearchMessages,
502
503
  {
503
504
  searchAllMessagesForUserId: args.searchAllMessagesForUserId,
504
505
  threadId: args.threadId,
505
- vectorIds,
506
+ embeddingIds,
506
507
  textSearchMessages: textSearchMessages?.filter(
507
- (m) => !vectorIds.includes(m.embeddingId! as VectorTableId)
508
+ (m) => !embeddingIds.includes(m.embeddingId! as VectorTableId),
508
509
  ),
509
510
  messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
510
511
  beforeMessageId: args.beforeMessageId,
511
512
  limit,
512
- }
513
+ },
513
514
  );
514
515
  return messages;
515
516
  }
@@ -520,7 +521,7 @@ export const searchMessages = action({
520
521
  export const _fetchSearchMessages = internalQuery({
521
522
  args: {
522
523
  threadId: v.optional(v.id("threads")),
523
- vectorIds: v.array(vVectorId),
524
+ embeddingIds: v.array(vVectorId),
524
525
  searchAllMessagesForUserId: v.optional(v.string()),
525
526
  textSearchMessages: v.optional(v.array(vMessageDoc)),
526
527
  messageRange: v.object({ before: v.number(), after: v.number() }),
@@ -534,28 +535,28 @@ export const _fetchSearchMessages = internalQuery({
534
535
  const { searchAllMessagesForUserId, threadId } = args;
535
536
  assert(
536
537
  searchAllMessagesForUserId || threadId,
537
- "Specify searchAllMessagesForUserId or threadId to search"
538
+ "Specify searchAllMessagesForUserId or threadId to search",
538
539
  );
539
540
  let messages: MessageDoc[] = (
540
541
  await Promise.all(
541
- args.vectorIds.map((embeddingId) =>
542
+ args.embeddingIds.map((embeddingId) =>
542
543
  ctx.db
543
544
  .query("messages")
544
545
  .withIndex("embeddingId_threadId", (q) =>
545
546
  searchAllMessagesForUserId
546
547
  ? q.eq("embeddingId", embeddingId)
547
- : q.eq("embeddingId", embeddingId).eq("threadId", threadId!)
548
+ : q.eq("embeddingId", embeddingId).eq("threadId", threadId!),
548
549
  )
549
550
  .filter((q) =>
550
551
  q.and(
551
552
  q.eq(q.field("status"), "success"),
552
553
  searchAllMessagesForUserId
553
554
  ? q.eq(q.field("userId"), searchAllMessagesForUserId)
554
- : q.eq(q.field("threadId"), threadId)
555
- )
555
+ : q.eq(q.field("threadId"), threadId),
556
+ ),
556
557
  )
557
- .first()
558
- )
558
+ .first(),
559
+ ),
559
560
  )
560
561
  )
561
562
  .filter(
@@ -566,7 +567,7 @@ export const _fetchSearchMessages = internalQuery({
566
567
  (!beforeMessage ||
567
568
  m.order < beforeMessage.order ||
568
569
  (m.order === beforeMessage.order &&
569
- m.stepOrder < beforeMessage.stepOrder))
570
+ m.stepOrder < beforeMessage.stepOrder)),
570
571
  )
571
572
  .map(publicMessage);
572
573
  messages.push(...(args.textSearchMessages ?? []));
@@ -614,7 +615,7 @@ export const _fetchSearchMessages = internalQuery({
614
615
  .eq("status", "success")
615
616
  .eq("tool", false)
616
617
  .gte("order", earliest)
617
- .lte("order", latest)
618
+ .lte("order", latest),
618
619
  )
619
620
  .collect();
620
621
  if (!ranges[searchId]) {
@@ -645,7 +646,7 @@ export const textSearch = query({
645
646
  handler: async (ctx, args) => {
646
647
  assert(
647
648
  args.searchAllMessagesForUserId || args.threadId,
648
- "Specify userId or threadId"
649
+ "Specify userId or threadId",
649
650
  );
650
651
  const beforeMessage =
651
652
  args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
@@ -657,7 +658,7 @@ export const textSearch = query({
657
658
  ? q
658
659
  .search("text", args.text)
659
660
  .eq("userId", args.searchAllMessagesForUserId)
660
- : q.search("text", args.text).eq("threadId", args.threadId!)
661
+ : q.search("text", args.text).eq("threadId", args.threadId!),
661
662
  )
662
663
  // Just in case tool messages slip through
663
664
  .filter((q) => {
@@ -674,7 +675,7 @@ export const textSearch = query({
674
675
  !beforeMessage ||
675
676
  m.order < beforeMessage.order ||
676
677
  (m.order === beforeMessage.order &&
677
- m.stepOrder < beforeMessage.stepOrder)
678
+ m.stepOrder < beforeMessage.stepOrder),
678
679
  )
679
680
  .map(publicMessage);
680
681
  },