@convex-dev/agent 0.0.1-alpha.0 → 0.0.1-alpha.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 (45) hide show
  1. package/dist/commonjs/client/index.d.ts +76 -41
  2. package/dist/commonjs/client/index.d.ts.map +1 -1
  3. package/dist/commonjs/client/index.js +104 -68
  4. package/dist/commonjs/client/index.js.map +1 -1
  5. package/dist/commonjs/component/messages.d.ts +12 -8
  6. package/dist/commonjs/component/messages.d.ts.map +1 -1
  7. package/dist/commonjs/component/messages.js +23 -6
  8. package/dist/commonjs/component/messages.js.map +1 -1
  9. package/dist/commonjs/component/schema.d.ts +6 -6
  10. package/dist/commonjs/component/schema.d.ts.map +1 -1
  11. package/dist/commonjs/component/schema.js +1 -1
  12. package/dist/commonjs/component/schema.js.map +1 -1
  13. package/dist/commonjs/component/vector/index.d.ts +41 -0
  14. package/dist/commonjs/component/vector/index.d.ts.map +1 -0
  15. package/dist/commonjs/component/vector/index.js +120 -0
  16. package/dist/commonjs/component/vector/index.js.map +1 -0
  17. package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
  18. package/dist/commonjs/component/vector/tables.js +4 -2
  19. package/dist/commonjs/component/vector/tables.js.map +1 -1
  20. package/dist/esm/client/index.d.ts +76 -41
  21. package/dist/esm/client/index.d.ts.map +1 -1
  22. package/dist/esm/client/index.js +104 -68
  23. package/dist/esm/client/index.js.map +1 -1
  24. package/dist/esm/component/messages.d.ts +12 -8
  25. package/dist/esm/component/messages.d.ts.map +1 -1
  26. package/dist/esm/component/messages.js +23 -6
  27. package/dist/esm/component/messages.js.map +1 -1
  28. package/dist/esm/component/schema.d.ts +6 -6
  29. package/dist/esm/component/schema.d.ts.map +1 -1
  30. package/dist/esm/component/schema.js +1 -1
  31. package/dist/esm/component/schema.js.map +1 -1
  32. package/dist/esm/component/vector/index.d.ts +41 -0
  33. package/dist/esm/component/vector/index.d.ts.map +1 -0
  34. package/dist/esm/component/vector/index.js +120 -0
  35. package/dist/esm/component/vector/index.js.map +1 -0
  36. package/dist/esm/component/vector/tables.d.ts.map +1 -1
  37. package/dist/esm/component/vector/tables.js +4 -2
  38. package/dist/esm/component/vector/tables.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/client/index.ts +248 -154
  41. package/src/component/_generated/api.d.ts +131 -5
  42. package/src/component/messages.ts +30 -8
  43. package/src/component/schema.ts +1 -1
  44. package/src/component/vector/index.ts +144 -0
  45. package/src/component/vector/tables.ts +7 -5
@@ -10,6 +10,7 @@
10
10
 
11
11
  import type * as lib from "../lib.js";
12
12
  import type * as messages from "../messages.js";
13
+ import type * as vector_index from "../vector/index.js";
13
14
  import type * as vector_tables from "../vector/tables.js";
14
15
 
15
16
  import type {
@@ -29,6 +30,7 @@ import type {
29
30
  declare const fullApi: ApiFromModules<{
30
31
  lib: typeof lib;
31
32
  messages: typeof messages;
33
+ "vector/index": typeof vector_index;
32
34
  "vector/tables": typeof vector_tables;
33
35
  }>;
34
36
  export type Mounts = {
@@ -262,7 +264,7 @@ export type Mounts = {
262
264
  role: "system";
263
265
  };
264
266
  model?: string;
265
- order?: number;
267
+ order: number;
266
268
  status: "pending" | "success" | "failed";
267
269
  stepId?: string;
268
270
  stepOrder?: number;
@@ -386,7 +388,7 @@ export type Mounts = {
386
388
  role: "system";
387
389
  };
388
390
  model?: string;
389
- order?: number;
391
+ order: number;
390
392
  status: "pending" | "success" | "failed";
391
393
  stepId?: string;
392
394
  stepOrder?: number;
@@ -1009,6 +1011,7 @@ export type Mounts = {
1009
1011
  isTool?: boolean;
1010
1012
  limit?: number;
1011
1013
  order?: "asc" | "desc";
1014
+ parentMessageId?: string;
1012
1015
  statuses?: Array<"pending" | "success" | "failed">;
1013
1016
  },
1014
1017
  {
@@ -1129,7 +1132,7 @@ export type Mounts = {
1129
1132
  role: "system";
1130
1133
  };
1131
1134
  model?: string;
1132
- order?: number;
1135
+ order: number;
1133
1136
  status: "pending" | "success" | "failed";
1134
1137
  stepId?: string;
1135
1138
  stepOrder?: number;
@@ -1195,6 +1198,7 @@ export type Mounts = {
1195
1198
  chatId?: string;
1196
1199
  limit: number;
1197
1200
  messageRange?: { after: number; before: number };
1201
+ parentMessageId?: string;
1198
1202
  text?: string;
1199
1203
  userId?: string;
1200
1204
  vector?: Array<number>;
@@ -1315,7 +1319,7 @@ export type Mounts = {
1315
1319
  role: "system";
1316
1320
  };
1317
1321
  model?: string;
1318
- order?: number;
1322
+ order: number;
1319
1323
  status: "pending" | "success" | "failed";
1320
1324
  stepId?: string;
1321
1325
  stepOrder?: number;
@@ -1444,7 +1448,7 @@ export type Mounts = {
1444
1448
  role: "system";
1445
1449
  };
1446
1450
  model?: string;
1447
- order?: number;
1451
+ order: number;
1448
1452
  status: "pending" | "success" | "failed";
1449
1453
  stepId?: string;
1450
1454
  stepOrder?: number;
@@ -1479,6 +1483,128 @@ export type Mounts = {
1479
1483
  }
1480
1484
  >;
1481
1485
  };
1486
+ vector: {
1487
+ index: {
1488
+ deleteBatch: FunctionReference<
1489
+ "mutation",
1490
+ "public",
1491
+ {
1492
+ ids: Array<
1493
+ | string
1494
+ | string
1495
+ | string
1496
+ | string
1497
+ | string
1498
+ | string
1499
+ | string
1500
+ | string
1501
+ | string
1502
+ >;
1503
+ },
1504
+ null
1505
+ >;
1506
+ deleteBatchForChat: FunctionReference<
1507
+ "mutation",
1508
+ "public",
1509
+ {
1510
+ chatId: string;
1511
+ cursor?: string;
1512
+ limit: number;
1513
+ model: string;
1514
+ vectorDimension:
1515
+ | 128
1516
+ | 256
1517
+ | 512
1518
+ | 768
1519
+ | 1024
1520
+ | 1536
1521
+ | 2048
1522
+ | 3072
1523
+ | 4096;
1524
+ },
1525
+ { continueCursor: string; isDone: boolean }
1526
+ >;
1527
+ insertBatch: FunctionReference<
1528
+ "mutation",
1529
+ "public",
1530
+ {
1531
+ vectorDimension:
1532
+ | 128
1533
+ | 256
1534
+ | 512
1535
+ | 768
1536
+ | 1024
1537
+ | 1536
1538
+ | 2048
1539
+ | 3072
1540
+ | 4096;
1541
+ vectors: Array<{
1542
+ chatId?: string;
1543
+ kind: "chat" | "memory";
1544
+ model: string;
1545
+ userId?: string;
1546
+ vector: Array<number>;
1547
+ }>;
1548
+ },
1549
+ null
1550
+ >;
1551
+ paginate: FunctionReference<
1552
+ "query",
1553
+ "public",
1554
+ {
1555
+ cursor?: string;
1556
+ limit: number;
1557
+ targetModel: string;
1558
+ vectorDimension:
1559
+ | 128
1560
+ | 256
1561
+ | 512
1562
+ | 768
1563
+ | 1024
1564
+ | 1536
1565
+ | 2048
1566
+ | 3072
1567
+ | 4096;
1568
+ },
1569
+ {
1570
+ continueCursor: string;
1571
+ ids: Array<
1572
+ | string
1573
+ | string
1574
+ | string
1575
+ | string
1576
+ | string
1577
+ | string
1578
+ | string
1579
+ | string
1580
+ | string
1581
+ >;
1582
+ isDone: boolean;
1583
+ }
1584
+ >;
1585
+ updateBatch: FunctionReference<
1586
+ "mutation",
1587
+ "public",
1588
+ {
1589
+ vectors: Array<{
1590
+ id:
1591
+ | string
1592
+ | string
1593
+ | string
1594
+ | string
1595
+ | string
1596
+ | string
1597
+ | string
1598
+ | string
1599
+ | string;
1600
+ model: string;
1601
+ vector: Array<number>;
1602
+ }>;
1603
+ },
1604
+ null
1605
+ >;
1606
+ };
1607
+ };
1482
1608
  };
1483
1609
  // For now fullApiWithMounts is only fullApi which provides
1484
1610
  // jump-to-definition in component client code.
@@ -597,9 +597,12 @@ export const getChatMessages = query({
597
597
  // Note: the other arguments cannot change from when the cursor was created.
598
598
  cursor: v.optional(v.string()),
599
599
  statuses: v.optional(v.array(vMessageStatus)),
600
+ parentMessageId: v.optional(v.id("messages")),
600
601
  },
601
602
  handler: async (ctx, args) => {
602
603
  const statuses = args.statuses ?? ["success"];
604
+ const parent =
605
+ args.parentMessageId && (await ctx.db.get(args.parentMessageId));
603
606
  const toolOptions =
604
607
  args.isTool === undefined ? [true, false] : [args.isTool];
605
608
  const order = args.order ?? "desc";
@@ -607,9 +610,16 @@ export const getChatMessages = query({
607
610
  statuses.map((status) =>
608
611
  stream(ctx.db, schema)
609
612
  .query("messages")
610
- .withIndex("chatId_status_tool_order_stepOrder", (q) =>
611
- q.eq("chatId", args.chatId).eq("status", status).eq("tool", tool)
612
- )
613
+ .withIndex("chatId_status_tool_order_stepOrder", (q) => {
614
+ const qq = q
615
+ .eq("chatId", args.chatId)
616
+ .eq("status", status)
617
+ .eq("tool", tool);
618
+ if (parent) {
619
+ return qq.lte("order", parent.order);
620
+ }
621
+ return qq;
622
+ })
613
623
  .order(order)
614
624
  )
615
625
  );
@@ -637,6 +647,7 @@ export const searchMessages = action({
637
647
  args: {
638
648
  userId: v.optional(v.string()),
639
649
  chatId: v.optional(v.id("chats")),
650
+ parentMessageId: v.optional(v.id("messages")),
640
651
  ...vSearchOptions.fields,
641
652
  },
642
653
  returns: v.array(v.doc("messages")),
@@ -688,10 +699,12 @@ export const searchMessages = action({
688
699
  userId: args.userId,
689
700
  chatId: args.chatId,
690
701
  vectorIds,
691
- textSearchMessages: textSearchMessages
692
- ?.filter((m) => !vectorIds.includes(m.embeddingId!))
693
- .slice(0, limit - vectorIds.length),
702
+ textSearchMessages: textSearchMessages?.filter(
703
+ (m) => !vectorIds.includes(m.embeddingId!)
704
+ ),
694
705
  messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
706
+ parentMessageId: args.parentMessageId,
707
+ limit,
695
708
  }
696
709
  );
697
710
  return messages;
@@ -707,10 +720,14 @@ export const _fetchVectorMessages = internalQuery({
707
720
  vectorIds: v.array(vVectorId),
708
721
  textSearchMessages: v.optional(v.array(v.doc("messages"))),
709
722
  messageRange: v.object({ before: v.number(), after: v.number() }),
723
+ parentMessageId: v.optional(v.id("messages")),
724
+ limit: v.number(),
710
725
  },
711
726
  returns: v.array(v.doc("messages")),
712
727
  handler: async (ctx, args): Promise<Doc<"messages">[]> => {
713
- const messages = (
728
+ const parent =
729
+ args.parentMessageId && (await ctx.db.get(args.parentMessageId));
730
+ let messages = (
714
731
  await Promise.all(
715
732
  args.vectorIds.map((embeddingId) =>
716
733
  ctx.db
@@ -726,9 +743,14 @@ export const _fetchVectorMessages = internalQuery({
726
743
  .first()
727
744
  )
728
745
  )
729
- ).filter((m): m is Doc<"messages"> => m !== undefined);
746
+ ).filter(
747
+ (m): m is Doc<"messages"> =>
748
+ m !== undefined && m !== null && (!parent || m.order <= parent.order)
749
+ );
730
750
  messages.push(...(args.textSearchMessages ?? []));
751
+ // TODO: prioritize more recent messages
731
752
  messages.sort((a, b) => a.order! - b.order!);
753
+ messages = messages.slice(0, args.limit);
732
754
  // Fetch the surrounding messages
733
755
  const included: Record<Id<"chats">, Set<number>> = {};
734
756
  for (const m of messages) {
@@ -34,7 +34,7 @@ export const schema = defineSchema({
34
34
  tool: v.boolean(),
35
35
  // Repeats until a non-tool message.
36
36
  // Set when the message is finished
37
- order: v.optional(v.number()),
37
+ order: v.number(),
38
38
  stepOrder: v.optional(v.number()),
39
39
  fileId: v.optional(v.id("files")),
40
40
  status: vMessageStatus,
@@ -0,0 +1,144 @@
1
+ import { paginator } from "convex-helpers/server/pagination";
2
+ import { v } from "convex/values";
3
+ import { mutation, query } from "../_generated/server";
4
+ import { getVectorTableName, vVectorDimension, vVectorId } from "./tables";
5
+ import schema from "../schema";
6
+ import { mergedStream } from "convex-helpers/server/stream";
7
+ import { stream } from "convex-helpers/server/stream";
8
+
9
+ export const paginate = query({
10
+ args: {
11
+ vectorDimension: vVectorDimension,
12
+ targetModel: v.string(),
13
+ cursor: v.optional(v.string()),
14
+ limit: v.number(),
15
+ },
16
+ returns: v.object({
17
+ ids: v.array(vVectorId),
18
+ isDone: v.boolean(),
19
+ continueCursor: v.string(),
20
+ }),
21
+ handler: async (ctx, args) => {
22
+ const tableName = getVectorTableName(args.vectorDimension);
23
+ const vectors = await paginator(ctx.db, schema)
24
+ .query(tableName)
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ .withIndex("model_kind_chatId" as any, (q) =>
27
+ q.eq("model", args.targetModel)
28
+ )
29
+ .paginate({
30
+ cursor: args.cursor ?? null,
31
+ numItems: args.limit,
32
+ maximumRowsRead: 300,
33
+ });
34
+ return {
35
+ ids: vectors.page.map((v) => v._id),
36
+ isDone: vectors.isDone,
37
+ continueCursor: vectors.continueCursor,
38
+ };
39
+ },
40
+ });
41
+
42
+ export const deleteBatchForChat = mutation({
43
+ args: {
44
+ vectorDimension: vVectorDimension,
45
+ model: v.string(),
46
+ chatId: v.string(),
47
+ cursor: v.optional(v.string()),
48
+ limit: v.number(),
49
+ },
50
+ returns: v.object({
51
+ isDone: v.boolean(),
52
+ continueCursor: v.string(),
53
+ }),
54
+ handler: async (ctx, args) => {
55
+ const tableName = getVectorTableName(args.vectorDimension);
56
+ const vectors = await mergedStream(
57
+ ["chat", "memory"].map((kind) =>
58
+ stream(ctx.db, schema)
59
+ .query(tableName)
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ .withIndex("model_kind_chatId" as any, (q) =>
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ (q.eq("model", args.model) as any)
64
+ .eq("kind", kind)
65
+ .eq("chatId", args.chatId)
66
+ )
67
+ ),
68
+ ["chatId"]
69
+ ).paginate({
70
+ cursor: args.cursor ?? null,
71
+ numItems: args.limit,
72
+ maximumRowsRead: 300,
73
+ });
74
+ await Promise.all(vectors.page.map((v) => ctx.db.delete(v._id)));
75
+ return {
76
+ isDone: vectors.isDone,
77
+ continueCursor: vectors.continueCursor,
78
+ };
79
+ },
80
+ });
81
+
82
+ export const insertBatch = mutation({
83
+ args: {
84
+ vectorDimension: vVectorDimension,
85
+ vectors: v.array(
86
+ v.object({
87
+ model: v.string(),
88
+ kind: v.union(v.literal("chat"), v.literal("memory")),
89
+ userId: v.optional(v.string()),
90
+ chatId: v.optional(v.string()),
91
+ vector: v.array(v.number()),
92
+ })
93
+ ),
94
+ },
95
+ returns: v.null(),
96
+ handler: async (ctx, args) => {
97
+ await Promise.all(
98
+ args.vectors.map((v) =>
99
+ ctx.db.insert(getVectorTableName(args.vectorDimension), {
100
+ model: v.model,
101
+ kind: v.kind,
102
+ userId: v.userId,
103
+ chatId: v.chatId,
104
+ vector: v.vector,
105
+ model_kind_userId: v.userId ? [v.model, v.kind, v.userId] : undefined,
106
+ model_kind_chatId: v.chatId ? [v.model, v.kind, v.chatId] : undefined,
107
+ })
108
+ )
109
+ );
110
+ },
111
+ });
112
+
113
+ export const updateBatch = mutation({
114
+ args: {
115
+ vectors: v.array(
116
+ v.object({
117
+ model: v.string(),
118
+ id: vVectorId,
119
+ vector: v.array(v.number()),
120
+ })
121
+ ),
122
+ },
123
+ returns: v.null(),
124
+ handler: async (ctx, args) => {
125
+ await Promise.all(
126
+ args.vectors.map((v) =>
127
+ ctx.db.patch(v.id, {
128
+ model: v.model,
129
+ vector: v.vector,
130
+ })
131
+ )
132
+ );
133
+ },
134
+ });
135
+
136
+ export const deleteBatch = mutation({
137
+ args: {
138
+ ids: v.array(vVectorId),
139
+ },
140
+ returns: v.null(),
141
+ handler: async (ctx, args) => {
142
+ await Promise.all(args.ids.map((id) => ctx.db.delete(id)));
143
+ },
144
+ });
@@ -20,11 +20,13 @@ const embeddings = {
20
20
  };
21
21
 
22
22
  function table<D extends number>(dimensions: D): Table<D> {
23
- return defineTable(embeddings).vectorIndex("vector", {
24
- vectorField: "vector",
25
- dimensions,
26
- filterFields: ["model_kind_userId", "model_kind_chatId"],
27
- });
23
+ return defineTable(embeddings)
24
+ .vectorIndex("vector", {
25
+ vectorField: "vector",
26
+ dimensions,
27
+ filterFields: ["model_kind_userId", "model_kind_chatId"],
28
+ })
29
+ .index("model_kind_chatId", ["model", "kind", "chatId"]);
28
30
  }
29
31
 
30
32
  export const VectorDimensions = [