@convex-dev/agent 0.2.12 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/client/createTool.d.ts.map +1 -1
  2. package/dist/client/createTool.js +0 -2
  3. package/dist/client/createTool.js.map +1 -1
  4. package/dist/client/definePlaygroundAPI.d.ts +10 -10
  5. package/dist/client/files.d.ts +5 -2
  6. package/dist/client/files.d.ts.map +1 -1
  7. package/dist/client/files.js.map +1 -1
  8. package/dist/client/index.d.ts.map +1 -1
  9. package/dist/client/index.js +1 -8
  10. package/dist/client/index.js.map +1 -1
  11. package/dist/client/messages.d.ts +2 -2
  12. package/dist/client/messages.d.ts.map +1 -1
  13. package/dist/client/messages.js.map +1 -1
  14. package/dist/client/saveInputMessages.d.ts.map +1 -1
  15. package/dist/client/saveInputMessages.js +1 -0
  16. package/dist/client/saveInputMessages.js.map +1 -1
  17. package/dist/client/search.d.ts +1 -1
  18. package/dist/client/search.d.ts.map +1 -1
  19. package/dist/client/start.d.ts.map +1 -1
  20. package/dist/client/start.js.map +1 -1
  21. package/dist/client/streaming.d.ts +3 -3
  22. package/dist/client/streaming.d.ts.map +1 -1
  23. package/dist/client/streaming.js.map +1 -1
  24. package/dist/client/threads.d.ts +6 -6
  25. package/dist/client/threads.d.ts.map +1 -1
  26. package/dist/client/threads.js.map +1 -1
  27. package/dist/client/types.d.ts +6 -25
  28. package/dist/client/types.d.ts.map +1 -1
  29. package/dist/component/_generated/api.d.ts +24 -2563
  30. package/dist/component/_generated/api.d.ts.map +1 -1
  31. package/dist/component/_generated/api.js +10 -1
  32. package/dist/component/_generated/api.js.map +1 -1
  33. package/dist/component/_generated/component.d.ts +2276 -0
  34. package/dist/component/_generated/component.d.ts.map +1 -0
  35. package/dist/component/_generated/component.js +11 -0
  36. package/dist/component/_generated/component.js.map +1 -0
  37. package/dist/component/_generated/dataModel.d.ts +4 -18
  38. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  39. package/dist/component/_generated/dataModel.js +11 -0
  40. package/dist/component/_generated/dataModel.js.map +1 -0
  41. package/dist/component/_generated/server.d.ts +10 -38
  42. package/dist/component/_generated/server.d.ts.map +1 -1
  43. package/dist/component/_generated/server.js +9 -5
  44. package/dist/component/_generated/server.js.map +1 -1
  45. package/dist/component/messages.d.ts +59 -3
  46. package/dist/component/messages.d.ts.map +1 -1
  47. package/dist/component/messages.js +157 -39
  48. package/dist/component/messages.js.map +1 -1
  49. package/dist/component/streams.d.ts +1 -1
  50. package/dist/component/threads.d.ts +4 -4
  51. package/dist/component/users.d.ts +3 -3
  52. package/dist/component/vector/index.d.ts.map +1 -1
  53. package/dist/component/vector/index.js +1 -3
  54. package/dist/component/vector/index.js.map +1 -1
  55. package/dist/deltas.js +1 -1
  56. package/dist/deltas.js.map +1 -1
  57. package/dist/mapping.d.ts.map +1 -1
  58. package/dist/mapping.js +1 -5
  59. package/dist/mapping.js.map +1 -1
  60. package/dist/react/useDeltaStreams.d.ts.map +1 -1
  61. package/dist/react/useDeltaStreams.js.map +1 -1
  62. package/dist/react/useStreamingUIMessages.d.ts.map +1 -1
  63. package/dist/react/useStreamingUIMessages.js +0 -1
  64. package/dist/react/useStreamingUIMessages.js.map +1 -1
  65. package/dist/react/useThreadMessages.d.ts.map +1 -1
  66. package/dist/react/useThreadMessages.js +1 -2
  67. package/dist/react/useThreadMessages.js.map +1 -1
  68. package/dist/react/useUIMessages.d.ts.map +1 -1
  69. package/dist/react/useUIMessages.js +1 -2
  70. package/dist/react/useUIMessages.js.map +1 -1
  71. package/package.json +29 -31
  72. package/src/client/createTool.ts +0 -2
  73. package/src/client/files.ts +3 -2
  74. package/src/client/index.test.ts +0 -1
  75. package/src/client/index.ts +4 -9
  76. package/src/client/messages.ts +2 -2
  77. package/src/client/saveInputMessages.test.ts +0 -1
  78. package/src/client/saveInputMessages.ts +1 -0
  79. package/src/client/search.test.ts +0 -1
  80. package/src/client/search.ts +1 -1
  81. package/src/client/start.ts +3 -8
  82. package/src/client/streaming.ts +2 -2
  83. package/src/client/threads.ts +2 -2
  84. package/src/client/types.ts +13 -61
  85. package/src/component/_generated/api.ts +64 -0
  86. package/src/component/_generated/component.ts +2922 -0
  87. package/src/component/_generated/{server.d.ts → server.ts} +33 -21
  88. package/src/component/messages.ts +209 -52
  89. package/src/component/vector/index.ts +1 -3
  90. package/src/deltas.ts +1 -1
  91. package/src/mapping.ts +1 -4
  92. package/src/react/useDeltaStreams.ts +0 -1
  93. package/src/react/useStreamingUIMessages.ts +0 -2
  94. package/src/react/useThreadMessages.ts +3 -10
  95. package/src/react/useUIMessages.ts +2 -6
  96. package/src/test.ts +2 -1
  97. package/src/validators.test.ts +14 -7
  98. package/src/component/_generated/api.d.ts +0 -2587
  99. package/src/component/_generated/api.js +0 -23
  100. package/src/component/_generated/server.js +0 -90
  101. package/src/vitest.config.ts +0 -7
  102. /package/src/component/_generated/{dataModel.d.ts → dataModel.ts} +0 -0
@@ -8,9 +8,8 @@
8
8
  * @module
9
9
  */
10
10
 
11
- import {
11
+ import type {
12
12
  ActionBuilder,
13
- AnyComponents,
14
13
  HttpActionBuilder,
15
14
  MutationBuilder,
16
15
  QueryBuilder,
@@ -19,15 +18,18 @@ import {
19
18
  GenericQueryCtx,
20
19
  GenericDatabaseReader,
21
20
  GenericDatabaseWriter,
22
- FunctionReference,
21
+ } from "convex/server";
22
+ import {
23
+ actionGeneric,
24
+ httpActionGeneric,
25
+ queryGeneric,
26
+ mutationGeneric,
27
+ internalActionGeneric,
28
+ internalMutationGeneric,
29
+ internalQueryGeneric,
23
30
  } from "convex/server";
24
31
  import type { DataModel } from "./dataModel.js";
25
32
 
26
- type GenericCtx =
27
- | GenericActionCtx<DataModel>
28
- | GenericMutationCtx<DataModel>
29
- | GenericQueryCtx<DataModel>;
30
-
31
33
  /**
32
34
  * Define a query in this Convex app's public API.
33
35
  *
@@ -36,7 +38,7 @@ type GenericCtx =
36
38
  * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
37
39
  * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
38
40
  */
39
- export declare const query: QueryBuilder<DataModel, "public">;
41
+ export const query: QueryBuilder<DataModel, "public"> = queryGeneric;
40
42
 
41
43
  /**
42
44
  * Define a query that is only accessible from other Convex functions (but not from the client).
@@ -46,7 +48,8 @@ export declare const query: QueryBuilder<DataModel, "public">;
46
48
  * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
47
49
  * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
48
50
  */
49
- export declare const internalQuery: QueryBuilder<DataModel, "internal">;
51
+ export const internalQuery: QueryBuilder<DataModel, "internal"> =
52
+ internalQueryGeneric;
50
53
 
51
54
  /**
52
55
  * Define a mutation in this Convex app's public API.
@@ -56,7 +59,7 @@ export declare const internalQuery: QueryBuilder<DataModel, "internal">;
56
59
  * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
57
60
  * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
58
61
  */
59
- export declare const mutation: MutationBuilder<DataModel, "public">;
62
+ export const mutation: MutationBuilder<DataModel, "public"> = mutationGeneric;
60
63
 
61
64
  /**
62
65
  * Define a mutation that is only accessible from other Convex functions (but not from the client).
@@ -66,7 +69,8 @@ export declare const mutation: MutationBuilder<DataModel, "public">;
66
69
  * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
67
70
  * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
68
71
  */
69
- export declare const internalMutation: MutationBuilder<DataModel, "internal">;
72
+ export const internalMutation: MutationBuilder<DataModel, "internal"> =
73
+ internalMutationGeneric;
70
74
 
71
75
  /**
72
76
  * Define an action in this Convex app's public API.
@@ -79,7 +83,7 @@ export declare const internalMutation: MutationBuilder<DataModel, "internal">;
79
83
  * @param func - The action. It receives an {@link ActionCtx} as its first argument.
80
84
  * @returns The wrapped action. Include this as an `export` to name it and make it accessible.
81
85
  */
82
- export declare const action: ActionBuilder<DataModel, "public">;
86
+ export const action: ActionBuilder<DataModel, "public"> = actionGeneric;
83
87
 
84
88
  /**
85
89
  * Define an action that is only accessible from other Convex functions (but not from the client).
@@ -87,19 +91,26 @@ export declare const action: ActionBuilder<DataModel, "public">;
87
91
  * @param func - The function. It receives an {@link ActionCtx} as its first argument.
88
92
  * @returns The wrapped function. Include this as an `export` to name it and make it accessible.
89
93
  */
90
- export declare const internalAction: ActionBuilder<DataModel, "internal">;
94
+ export const internalAction: ActionBuilder<DataModel, "internal"> =
95
+ internalActionGeneric;
91
96
 
92
97
  /**
93
98
  * Define an HTTP action.
94
99
  *
95
- * This function will be used to respond to HTTP requests received by a Convex
96
- * deployment if the requests matches the path and method where this action
97
- * is routed. Be sure to route your action in `convex/http.js`.
100
+ * The wrapped function will be used to respond to HTTP requests received
101
+ * by a Convex deployment if the requests matches the path and method where
102
+ * this action is routed. Be sure to route your httpAction in `convex/http.js`.
98
103
  *
99
- * @param func - The function. It receives an {@link ActionCtx} as its first argument.
104
+ * @param func - The function. It receives an {@link ActionCtx} as its first argument
105
+ * and a Fetch API `Request` object as its second.
100
106
  * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
101
107
  */
102
- export declare const httpAction: HttpActionBuilder;
108
+ export const httpAction: HttpActionBuilder = httpActionGeneric;
109
+
110
+ type GenericCtx =
111
+ | GenericActionCtx<DataModel>
112
+ | GenericMutationCtx<DataModel>
113
+ | GenericQueryCtx<DataModel>;
103
114
 
104
115
  /**
105
116
  * A set of services for use within Convex query functions.
@@ -107,8 +118,7 @@ export declare const httpAction: HttpActionBuilder;
107
118
  * The query context is passed as the first argument to any Convex query
108
119
  * function run on the server.
109
120
  *
110
- * This differs from the {@link MutationCtx} because all of the services are
111
- * read-only.
121
+ * If you're using code generation, use the `QueryCtx` type in `convex/_generated/server.d.ts` instead.
112
122
  */
113
123
  export type QueryCtx = GenericQueryCtx<DataModel>;
114
124
 
@@ -117,6 +127,8 @@ export type QueryCtx = GenericQueryCtx<DataModel>;
117
127
  *
118
128
  * The mutation context is passed as the first argument to any Convex mutation
119
129
  * function run on the server.
130
+ *
131
+ * If you're using code generation, use the `MutationCtx` type in `convex/_generated/server.d.ts` instead.
120
132
  */
121
133
  export type MutationCtx = GenericMutationCtx<DataModel>;
122
134
 
@@ -24,6 +24,7 @@ import { api, internal } from "./_generated/api.js";
24
24
  import type { Doc, Id } from "./_generated/dataModel.js";
25
25
  import {
26
26
  action,
27
+ internalMutation,
27
28
  internalQuery,
28
29
  mutation,
29
30
  type MutationCtx,
@@ -137,6 +138,9 @@ const addMessagesArgs = {
137
138
  failPendingSteps: v.optional(v.boolean()),
138
139
  // A pending message to update. If the pending message failed, abort.
139
140
  pendingMessageId: v.optional(v.id("messages")),
141
+ // if set to true, these messages will not show up in text or vector search
142
+ // results for the userId
143
+ hideFromUserIdSearch: v.optional(v.boolean()),
140
144
  };
141
145
  export const addMessages = mutation({
142
146
  args: addMessagesArgs,
@@ -160,6 +164,7 @@ async function addMessagesHandler(
160
164
  messages,
161
165
  promptMessageId,
162
166
  pendingMessageId,
167
+ hideFromUserIdSearch,
163
168
  ...rest
164
169
  } = args;
165
170
  const promptMessage = promptMessageId && (await ctx.db.get(promptMessageId));
@@ -226,7 +231,7 @@ async function addMessagesHandler(
226
231
  vector: embeddings.vectors[i]!,
227
232
  model: embeddings.model,
228
233
  table: "messages",
229
- userId,
234
+ userId: hideFromUserIdSearch ? undefined : userId,
230
235
  threadId,
231
236
  });
232
237
  }
@@ -237,7 +242,7 @@ async function addMessagesHandler(
237
242
  parentMessageId: promptMessageId,
238
243
  userId,
239
244
  tool: isTool(message.message),
240
- text: extractText(message.message),
245
+ text: hideFromUserIdSearch ? undefined : extractText(message.message),
241
246
  status: fail ? "failed" : (message.status ?? "success"),
242
247
  error: fail ? error : message.error,
243
248
  } satisfies Omit<
@@ -439,64 +444,216 @@ export const updateMessage = mutation({
439
444
  },
440
445
  });
441
446
 
442
- export const listMessagesByThreadId = query({
447
+ const cloneMessageArgs = {
448
+ sourceThreadId: v.id("threads"),
449
+ targetThreadId: v.id("threads"),
450
+ // defaults to false, so searching for a message by userId will not find
451
+ // these copies
452
+ copyUserIdForVectorSearch: v.optional(v.boolean()),
453
+ // defaults to false, so tool calls & responses will be copied
454
+ excludeToolMessages: v.optional(v.boolean()),
455
+ // defaults to copying all messages, but you could just copy success messages.
456
+ statuses: v.optional(v.array(vMessageStatus)),
457
+ // stop at this message id
458
+ upToAndIncludingMessageId: v.optional(v.id("messages")),
459
+ // defaults to 0. the messages will be inserted starting at this order.
460
+ insertAtOrder: v.optional(v.number()),
461
+ };
462
+ export const cloneMessageBatch = internalMutation({
443
463
  args: {
444
- threadId: v.id("threads"),
445
- excludeToolMessages: v.optional(v.boolean()),
446
- /** What order to sort the messages in. To get the latest, use "desc". */
447
- order: v.union(v.literal("asc"), v.literal("desc")),
448
- paginationOpts: v.optional(paginationOptsValidator),
449
- statuses: v.optional(v.array(vMessageStatus)),
450
- upToAndIncludingMessageId: v.optional(v.id("messages")),
464
+ ...cloneMessageArgs,
465
+ paginationOpts: paginationOptsValidator,
451
466
  },
452
- handler: async (ctx, args) => {
453
- const statuses =
454
- args.statuses ?? vMessageStatus.members.map((m) => m.value);
455
- const last =
456
- args.upToAndIncludingMessageId &&
457
- (await ctx.db.get(args.upToAndIncludingMessageId));
458
- assert(
459
- !last || last.threadId === args.threadId,
460
- "upToAndIncludingMessageId must be a message in the thread",
461
- );
462
- const toolOptions = args.excludeToolMessages ? [false] : [true, false];
463
- const order = args.order ?? "desc";
464
- const streams = toolOptions.flatMap((tool) =>
465
- statuses.map((status) =>
466
- stream(ctx.db, schema)
467
- .query("messages")
468
- .withIndex("threadId_status_tool_order_stepOrder", (q) => {
469
- const qq = q
470
- .eq("threadId", args.threadId)
471
- .eq("status", status)
472
- .eq("tool", tool);
473
- if (last) {
474
- return qq.lte("order", last.order);
475
- }
476
- return qq;
477
- })
478
- .order(order)
479
- .filterWith(
480
- // We allow all messages on the same order.
481
- async (m) =>
482
- !last || m.order < last.order || m.order === last.order,
483
- ),
484
- ),
485
- );
486
- const messages = await mergedStream(streams, [
487
- "order",
488
- "stepOrder",
489
- ]).paginate(
490
- args.paginationOpts ?? {
491
- numItems: DEFAULT_RECENT_MESSAGES,
492
- cursor: null,
493
- },
467
+ handler: async (
468
+ ctx,
469
+ args,
470
+ ): Promise<{
471
+ numCopied: number;
472
+ continueCursor: string;
473
+ isDone: boolean;
474
+ }> => {
475
+ const orderOffset = args.insertAtOrder ?? 0;
476
+ const result = await listMessagesByThreadIdHandler(ctx, {
477
+ threadId: args.sourceThreadId,
478
+ excludeToolMessages: args.excludeToolMessages,
479
+ order: "desc",
480
+ paginationOpts: args.paginationOpts,
481
+ statuses: args.statuses,
482
+ upToAndIncludingMessageId: args.upToAndIncludingMessageId,
483
+ });
484
+
485
+ const existing =
486
+ result.page.length === 0
487
+ ? []
488
+ : await mergedStream(
489
+ [true, false].flatMap((tool) =>
490
+ messageStatuses.map((status) =>
491
+ stream(ctx.db, schema)
492
+ .query("messages")
493
+ .withIndex("threadId_status_tool_order_stepOrder", (q) =>
494
+ q
495
+ .eq("threadId", args.targetThreadId)
496
+ .eq("status", status)
497
+ .eq("tool", tool)
498
+ .gte("order", result.page[0].order)
499
+ .lte("order", result.page[result.page.length - 1].order),
500
+ ),
501
+ ),
502
+ ),
503
+ ["order", "stepOrder"],
504
+ ).collect();
505
+
506
+ await Promise.all(
507
+ result.page
508
+ .filter(
509
+ (m) =>
510
+ !existing.some(
511
+ (e) => e.order === m.order && e.stepOrder === m.stepOrder,
512
+ ),
513
+ )
514
+ .map(async (m) => {
515
+ // update file refs
516
+ if (m.fileIds) {
517
+ await changeRefcount(ctx, [], m.fileIds);
518
+ }
519
+ let embeddingId: VectorTableId | undefined = undefined;
520
+ if (m.embeddingId) {
521
+ const vector = await ctx.db.get(m.embeddingId);
522
+ assert(vector, `Vector ${m.embeddingId} not found`);
523
+ const dimension = vector.vector.length;
524
+ validateVectorDimension(dimension);
525
+ embeddingId = await insertVector(ctx, dimension, {
526
+ ...pick(vector, ["model", "table", "vector"]),
527
+ userId: args.copyUserIdForVectorSearch
528
+ ? vector.userId
529
+ : undefined,
530
+ threadId: args.targetThreadId,
531
+ });
532
+ }
533
+ await ctx.db.insert("messages", {
534
+ ...omit(m, [
535
+ "_id",
536
+ "_creationTime",
537
+ "threadId",
538
+ "order",
539
+ "embeddingId",
540
+ ]),
541
+ embeddingId,
542
+ threadId: args.targetThreadId,
543
+ order: orderOffset + m.order,
544
+ });
545
+ }),
494
546
  );
547
+ return {
548
+ numCopied: result.page.length,
549
+ continueCursor: result.continueCursor,
550
+ isDone: result.isDone,
551
+ };
552
+ },
553
+ });
554
+
555
+ export const cloneThread = action({
556
+ args: {
557
+ ...cloneMessageArgs,
558
+ batchSize: v.optional(v.number()),
559
+ // how many messages to copy
560
+ limit: v.optional(v.number()),
561
+ },
562
+ returns: v.number(),
563
+ handler: async (ctx, args) => {
564
+ let cursor: string | null = null;
565
+ let copiedSoFar = 0;
566
+ while (copiedSoFar < (args.limit ?? Infinity)) {
567
+ const numToCopy = Math.min(
568
+ args.batchSize ?? DEFAULT_RECENT_MESSAGES,
569
+ args.limit ?? Infinity - copiedSoFar,
570
+ );
571
+ const result: {
572
+ numCopied: number;
573
+ continueCursor: string;
574
+ isDone: boolean;
575
+ } = await ctx.runMutation(internal.messages.cloneMessageBatch, {
576
+ ...args,
577
+ paginationOpts: {
578
+ cursor,
579
+ numItems: numToCopy,
580
+ },
581
+ });
582
+ copiedSoFar += result.numCopied;
583
+ cursor = result.continueCursor;
584
+ if (result.isDone) {
585
+ break;
586
+ }
587
+ }
588
+ return copiedSoFar;
589
+ },
590
+ });
591
+
592
+ export const listMessagesByThreadIdArgs = {
593
+ threadId: v.id("threads"),
594
+ excludeToolMessages: v.optional(v.boolean()),
595
+ /** What order to sort the messages in. To get the latest, use "desc". */
596
+ order: v.union(v.literal("asc"), v.literal("desc")),
597
+ paginationOpts: v.optional(paginationOptsValidator),
598
+ statuses: v.optional(v.array(vMessageStatus)),
599
+ upToAndIncludingMessageId: v.optional(v.id("messages")),
600
+ };
601
+ export const listMessagesByThreadId = query({
602
+ args: listMessagesByThreadIdArgs,
603
+ handler: async (ctx, args) => {
604
+ const messages = await listMessagesByThreadIdHandler(ctx, args);
495
605
  return { ...messages, page: messages.page.map(publicMessage) };
496
606
  },
497
607
  returns: vPaginationResult(vMessageDoc),
498
608
  });
499
609
 
610
+ async function listMessagesByThreadIdHandler(
611
+ ctx: QueryCtx,
612
+ args: ObjectType<typeof listMessagesByThreadIdArgs>,
613
+ ) {
614
+ const statuses = args.statuses ?? vMessageStatus.members.map((m) => m.value);
615
+ const last =
616
+ args.upToAndIncludingMessageId &&
617
+ (await ctx.db.get(args.upToAndIncludingMessageId));
618
+ assert(
619
+ !last || last.threadId === args.threadId,
620
+ "upToAndIncludingMessageId must be a message in the thread",
621
+ );
622
+ const toolOptions = args.excludeToolMessages ? [false] : [true, false];
623
+ const order = args.order ?? "desc";
624
+ const streams = toolOptions.flatMap((tool) =>
625
+ statuses.map((status) =>
626
+ stream(ctx.db, schema)
627
+ .query("messages")
628
+ .withIndex("threadId_status_tool_order_stepOrder", (q) => {
629
+ const qq = q
630
+ .eq("threadId", args.threadId)
631
+ .eq("status", status)
632
+ .eq("tool", tool);
633
+ if (last) {
634
+ return qq.lte("order", last.order);
635
+ }
636
+ return qq;
637
+ })
638
+ .order(order)
639
+ .filterWith(
640
+ // We allow all messages on the same order.
641
+ async (m) => !last || m.order <= last.order,
642
+ ),
643
+ ),
644
+ );
645
+ const messages = await mergedStream(streams, ["order", "stepOrder"]).paginate(
646
+ args.paginationOpts ?? {
647
+ numItems: DEFAULT_RECENT_MESSAGES,
648
+ cursor: null,
649
+ },
650
+ );
651
+ if (messages.page.length === 0) {
652
+ messages.isDone = true;
653
+ }
654
+ return messages;
655
+ }
656
+
500
657
  export const getMessagesByIds = query({
501
658
  args: { messageIds: v.array(v.id("messages")) },
502
659
  handler: async (ctx, args) => {
@@ -35,11 +35,9 @@ export const paginate = query({
35
35
  const tableName = getVectorTableName(args.vectorDimension);
36
36
  const vectors = await paginator(ctx.db, schema)
37
37
  .query(tableName)
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
38
  .withIndex("model_table_threadId" as any, (q) =>
40
39
  args.table
41
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- (q.eq("model", args.targetModel) as any).eq("table", args.table)
40
+ ? (q.eq("model", args.targetModel) as any).eq("table", args.table)
43
41
  : q.eq("model", args.targetModel),
44
42
  )
45
43
  .paginate({
package/src/deltas.ts CHANGED
@@ -79,7 +79,7 @@ export async function updateFromUIMessageChunks(
79
79
  for await (const messagePart of messageStream) {
80
80
  assert(
81
81
  messagePart.id === message.id,
82
- `Expecting to only make one UIMessage in a stream, but have ${JSON.stringify(message)} and created ${JSON.stringify(messagePart)}`,
82
+ `Expecting to only make one UIMessage in a stream`,
83
83
  );
84
84
  message = messagePart;
85
85
  }
package/src/mapping.ts CHANGED
@@ -60,8 +60,7 @@ export type SerializeUrlsAndUint8Arrays<T> = T extends URL
60
60
  ? ArrayBuffer
61
61
  : T extends Array<infer Inner>
62
62
  ? Array<SerializeUrlsAndUint8Arrays<Inner>>
63
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
- T extends Record<string, any>
63
+ : T extends Record<string, any>
65
64
  ? { [K in keyof T]: SerializeUrlsAndUint8Arrays<T[K]> }
66
65
  : T;
67
66
 
@@ -109,9 +108,7 @@ export async function serializeOrThrow(
109
108
  message: ModelMessage | Message,
110
109
  ): Promise<SerializedMessage> {
111
110
  const { content } = await serializeContent(
112
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
111
  {} as any,
114
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
112
  {} as any,
116
113
  message.content,
117
114
  );
@@ -10,7 +10,6 @@ import { useState } from "react";
10
10
  import { assert } from "convex-helpers";
11
11
 
12
12
  export function useDeltaStreams<
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
13
  Query extends StreamQuery<any> = StreamQuery<object>,
15
14
  >(
16
15
  query: Query,
@@ -13,7 +13,6 @@ import { useDeltaStreams } from "./useDeltaStreams.js";
13
13
 
14
14
  // Polyfill structuredClone to support readUIMessageStream on ReactNative
15
15
  if (!("structuredClone" in globalThis)) {
16
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
16
  void import("@ungap/structured-clone" as any).then(
18
17
  ({ default: structuredClone }) =>
19
18
  (globalThis.structuredClone = structuredClone),
@@ -38,7 +37,6 @@ export function useStreamingUIMessages<
38
37
  METADATA = unknown,
39
38
  DATA_PARTS extends UIDataTypes = UIDataTypes,
40
39
  TOOLS extends UITools = UITools,
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
40
  Query extends StreamQuery<any> = StreamQuery<object>,
43
41
  >(
44
42
  query: Query,
@@ -116,10 +116,7 @@ export type ThreadMessagesResult<
116
116
  * @returns The messages. If stream is true, it will return a list of messages
117
117
  * that includes both full messages and streaming messages.
118
118
  */
119
- export function useThreadMessages<
120
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
- Query extends ThreadMessagesQuery<any, any>,
122
- >(
119
+ export function useThreadMessages<Query extends ThreadMessagesQuery<any, any>>(
123
120
  query: Query,
124
121
  args: ThreadMessagesArgs<Query> | "skip",
125
122
  options: {
@@ -154,8 +151,7 @@ export function useThreadMessages<
154
151
  args === "skip" ||
155
152
  paginated.status === "LoadingFirstPage"
156
153
  ? "skip"
157
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
- ({ ...args, paginationOpts: { cursor: null, numItems: 0 } } as any),
154
+ : ({ ...args, paginationOpts: { cursor: null, numItems: 0 } } as any),
159
155
  { startOrder },
160
156
  );
161
157
 
@@ -222,10 +218,7 @@ export function useThreadMessages<
222
218
  * you want to pass to the query.
223
219
  * @returns The streaming messages.
224
220
  */
225
- export function useStreamingThreadMessages<
226
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
227
- Query extends StreamQuery<any>,
228
- >(
221
+ export function useStreamingThreadMessages<Query extends StreamQuery<any>>(
229
222
  query: Query,
230
223
  args:
231
224
  | (StreamQueryArgs<Query> & {
@@ -122,10 +122,7 @@ export type UIMessagesQueryResult<
122
122
  * The streaming messages are materialized as UIMessages. The rest are passed
123
123
  * through from the query.
124
124
  */
125
- export function useUIMessages<
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
- Query extends UIMessagesQuery<any, any>,
128
- >(
125
+ export function useUIMessages<Query extends UIMessagesQuery<any, any>>(
129
126
  query: Query,
130
127
  args: UIMessagesQueryArgs<Query> | "skip",
131
128
  options: {
@@ -153,8 +150,7 @@ export function useUIMessages<
153
150
  args === "skip" ||
154
151
  paginated.status === "LoadingFirstPage"
155
152
  ? "skip"
156
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
157
- ({ ...args, paginationOpts: { cursor: null, numItems: 0 } } as any),
153
+ : ({ ...args, paginationOpts: { cursor: null, numItems: 0 } } as any),
158
154
  { startOrder, skipStreamIds: options.skipStreamIds },
159
155
  );
160
156
 
package/src/test.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference types="vite/client" />
1
2
  import type { TestConvex } from "convex-test";
2
3
  import type { GenericSchema, SchemaDefinition } from "convex/server";
3
4
  import schema from "./component/schema.js";
@@ -8,7 +9,7 @@ const modules = import.meta.glob("./component/**/*.ts");
8
9
  * @param t - The test convex instance, e.g. from calling `convexTest`.
9
10
  * @param name - The name of the component, as registered in convex.config.ts.
10
11
  */
11
- function register(
12
+ export function register(
12
13
  t: TestConvex<SchemaDefinition<GenericSchema, boolean>>,
13
14
  name: string = "agent",
14
15
  ) {
@@ -1,10 +1,6 @@
1
- import type { Infer } from "convex/values";
1
+ import type { GenericId, Infer } from "convex/values";
2
2
  import { expectTypeOf, test } from "vitest";
3
- import type {
4
- ContextOptions,
5
- OpaqueIds,
6
- StorageOptions,
7
- } from "./client/types.js";
3
+ import type { ContextOptions, StorageOptions } from "./client/types.js";
8
4
  import { vContextOptions, vMessageDoc, vStorageOptions } from "./validators.js";
9
5
  import type { Doc } from "./component/_generated/dataModel.js";
10
6
 
@@ -14,10 +10,21 @@ expectTypeOf<ContextOptions>().toExtend<Infer<typeof vContextOptions>>();
14
10
  expectTypeOf<Infer<typeof vStorageOptions>>().toExtend<StorageOptions>();
15
11
  expectTypeOf<StorageOptions>().toExtend<Infer<typeof vStorageOptions>>();
16
12
 
17
- type MessageBasedOnSchema = OpaqueIds<
13
+ type MessageBasedOnSchema = IdsToStrings<
18
14
  Omit<Doc<"messages">, "files" | "stepId" | "parentMessageId">
19
15
  >;
20
16
  expectTypeOf<Infer<typeof vMessageDoc>>().toEqualTypeOf<MessageBasedOnSchema>();
21
17
  expectTypeOf<MessageBasedOnSchema>().toEqualTypeOf<Infer<typeof vMessageDoc>>();
22
18
 
23
19
  test("noop", () => {});
20
+
21
+ type IdsToStrings<T> =
22
+ T extends GenericId<string>
23
+ ? string
24
+ : T extends (infer U)[]
25
+ ? IdsToStrings<U>[]
26
+ : T extends ArrayBuffer
27
+ ? ArrayBuffer
28
+ : T extends object
29
+ ? { [K in keyof T]: IdsToStrings<T[K]> }
30
+ : T;