@convex-dev/agent 0.0.1-alpha.3 → 0.0.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.
- package/README.md +9 -7
- package/dist/commonjs/client/index.d.ts +12 -5
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +127 -44
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/messages.d.ts +114 -103
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +143 -246
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +808 -738
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +12 -3
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/vector/index.d.ts +21 -6
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +33 -21
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +25 -5
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.js +14 -6
- package/dist/commonjs/component/vector/tables.js.map +1 -1
- package/dist/commonjs/validators.d.ts +101 -89
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +8 -1
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/esm/client/index.d.ts +12 -5
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +127 -44
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/messages.d.ts +114 -103
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +143 -246
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +808 -738
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +12 -3
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/vector/index.d.ts +21 -6
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +33 -21
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/component/vector/tables.d.ts +25 -5
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.js +14 -6
- package/dist/esm/component/vector/tables.js.map +1 -1
- package/dist/esm/validators.d.ts +101 -89
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +8 -1
- package/dist/esm/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +149 -50
- package/src/component/_generated/api.d.ts +28 -16
- package/src/component/messages.ts +175 -289
- package/src/component/schema.ts +13 -3
- package/src/component/vector/index.ts +65 -26
- package/src/component/vector/tables.ts +38 -6
- package/src/validators.ts +11 -4
package/src/component/schema.ts
CHANGED
|
@@ -17,12 +17,12 @@ export const schema = defineSchema({
|
|
|
17
17
|
// the parent thread(s). There are multiple if the thread is a merging of
|
|
18
18
|
// multiple threads.
|
|
19
19
|
parentThreadIds: v.optional(v.array(v.id("threads"))),
|
|
20
|
-
}).index("
|
|
20
|
+
}).index("userId_status_order", ["userId", "status", "order"]),
|
|
21
21
|
// TODO: text search on title/ summary
|
|
22
22
|
messages: defineTable({
|
|
23
23
|
id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
|
|
24
24
|
userId: v.optional(v.string()), // useful for future indexes (text search)
|
|
25
|
-
threadId: v.
|
|
25
|
+
threadId: v.id("threads"),
|
|
26
26
|
parentMessageId: v.optional(v.id("messages")),
|
|
27
27
|
stepId: v.optional(v.id("steps")),
|
|
28
28
|
agentName: v.optional(v.string()),
|
|
@@ -35,7 +35,7 @@ export const schema = defineSchema({
|
|
|
35
35
|
// Repeats until a non-tool message.
|
|
36
36
|
// Unset if it's not in a thread.
|
|
37
37
|
order: v.number(),
|
|
38
|
-
stepOrder: v.
|
|
38
|
+
stepOrder: v.number(),
|
|
39
39
|
fileId: v.optional(v.id("files")),
|
|
40
40
|
status: vMessageStatus,
|
|
41
41
|
})
|
|
@@ -92,6 +92,16 @@ export const schema = defineSchema({
|
|
|
92
92
|
"stepOrder",
|
|
93
93
|
]),
|
|
94
94
|
|
|
95
|
+
memories: defineTable({
|
|
96
|
+
threadId: v.optional(v.id("threads")),
|
|
97
|
+
userId: v.optional(v.string()),
|
|
98
|
+
memory: v.string(),
|
|
99
|
+
embeddingId: v.optional(vVectorId),
|
|
100
|
+
})
|
|
101
|
+
.index("threadId", ["threadId"])
|
|
102
|
+
.index("userId", ["userId"])
|
|
103
|
+
.index("embeddingId", ["embeddingId"]),
|
|
104
|
+
|
|
95
105
|
files: defineTable({
|
|
96
106
|
storageId: v.string(),
|
|
97
107
|
hash: v.string(),
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { paginator } from "convex-helpers/server/pagination";
|
|
2
2
|
import { v } from "convex/values";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
ActionCtx,
|
|
5
|
+
mutation,
|
|
6
|
+
MutationCtx,
|
|
7
|
+
query,
|
|
8
|
+
QueryCtx,
|
|
9
|
+
} from "../_generated/server";
|
|
10
|
+
import {
|
|
11
|
+
EmbeddingsWithoutDenormalizedFields,
|
|
12
|
+
getVectorTableName,
|
|
13
|
+
VectorDimension,
|
|
14
|
+
vEmbeddingsWithoutDenormalizedFields,
|
|
15
|
+
vVectorDimension,
|
|
16
|
+
vVectorId,
|
|
17
|
+
} from "./tables";
|
|
5
18
|
import schema from "../schema";
|
|
6
19
|
import { mergedStream } from "convex-helpers/server/stream";
|
|
7
20
|
import { stream } from "convex-helpers/server/stream";
|
|
@@ -10,6 +23,7 @@ export const paginate = query({
|
|
|
10
23
|
args: {
|
|
11
24
|
vectorDimension: vVectorDimension,
|
|
12
25
|
targetModel: v.string(),
|
|
26
|
+
table: v.optional(v.string()),
|
|
13
27
|
cursor: v.optional(v.string()),
|
|
14
28
|
limit: v.number(),
|
|
15
29
|
},
|
|
@@ -23,8 +37,11 @@ export const paginate = query({
|
|
|
23
37
|
const vectors = await paginator(ctx.db, schema)
|
|
24
38
|
.query(tableName)
|
|
25
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
-
.withIndex("
|
|
27
|
-
|
|
40
|
+
.withIndex("model_table_threadId" as any, (q) =>
|
|
41
|
+
args.table
|
|
42
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
+
(q.eq("model", args.targetModel) as any).eq("table", args.table)
|
|
44
|
+
: q.eq("model", args.targetModel)
|
|
28
45
|
)
|
|
29
46
|
.paginate({
|
|
30
47
|
cursor: args.cursor ?? null,
|
|
@@ -82,36 +99,58 @@ export const deleteBatchForThread = mutation({
|
|
|
82
99
|
export const insertBatch = mutation({
|
|
83
100
|
args: {
|
|
84
101
|
vectorDimension: vVectorDimension,
|
|
85
|
-
vectors: v.array(
|
|
86
|
-
v.object({
|
|
87
|
-
model: v.string(),
|
|
88
|
-
kind: v.union(v.literal("thread"), v.literal("memory")),
|
|
89
|
-
userId: v.optional(v.string()),
|
|
90
|
-
threadId: v.optional(v.string()),
|
|
91
|
-
vector: v.array(v.number()),
|
|
92
|
-
})
|
|
93
|
-
),
|
|
102
|
+
vectors: v.array(vEmbeddingsWithoutDenormalizedFields),
|
|
94
103
|
},
|
|
95
104
|
returns: v.null(),
|
|
96
105
|
handler: async (ctx, args) => {
|
|
97
106
|
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
|
-
threadId: v.threadId,
|
|
104
|
-
vector: v.vector,
|
|
105
|
-
model_kind_userId: v.userId ? [v.model, v.kind, v.userId] : undefined,
|
|
106
|
-
model_kind_threadId: v.threadId
|
|
107
|
-
? [v.model, v.kind, v.threadId]
|
|
108
|
-
: undefined,
|
|
109
|
-
})
|
|
110
|
-
)
|
|
107
|
+
args.vectors.map((v) => insertVector(ctx, args.vectorDimension, v))
|
|
111
108
|
);
|
|
112
109
|
},
|
|
113
110
|
});
|
|
114
111
|
|
|
112
|
+
export async function insertVector(
|
|
113
|
+
ctx: MutationCtx,
|
|
114
|
+
dimension: VectorDimension,
|
|
115
|
+
v: EmbeddingsWithoutDenormalizedFields
|
|
116
|
+
) {
|
|
117
|
+
return ctx.db.insert(getVectorTableName(dimension), {
|
|
118
|
+
...v,
|
|
119
|
+
model_table_userId: v.userId ? [v.model, v.table, v.userId] : undefined,
|
|
120
|
+
model_table_threadId: v.threadId
|
|
121
|
+
? [v.model, v.table, v.threadId]
|
|
122
|
+
: undefined,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function searchVectors(
|
|
127
|
+
ctx: ActionCtx,
|
|
128
|
+
vector: number[],
|
|
129
|
+
args: {
|
|
130
|
+
dimension: VectorDimension;
|
|
131
|
+
model: string;
|
|
132
|
+
table: string;
|
|
133
|
+
userId?: string;
|
|
134
|
+
threadId?: string;
|
|
135
|
+
limit?: number;
|
|
136
|
+
}
|
|
137
|
+
) {
|
|
138
|
+
const tableName = getVectorTableName(args.dimension);
|
|
139
|
+
return ctx.vectorSearch(tableName, "vector", {
|
|
140
|
+
vector,
|
|
141
|
+
// TODO: to support more tables, add more "OR" clauses for each.
|
|
142
|
+
filter: (q) =>
|
|
143
|
+
args.userId
|
|
144
|
+
? q.eq("model_table_userId", [args.model, args.table, args.userId])
|
|
145
|
+
: q.eq("model_table_threadId", [
|
|
146
|
+
args.model,
|
|
147
|
+
args.table,
|
|
148
|
+
args.threadId!,
|
|
149
|
+
]),
|
|
150
|
+
limit: args.limit,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
115
154
|
export const updateBatch = mutation({
|
|
116
155
|
args: {
|
|
117
156
|
vectors: v.array(
|
|
@@ -1,37 +1,69 @@
|
|
|
1
|
+
import { omit } from "convex-helpers";
|
|
1
2
|
import { literals } from "convex-helpers/validators";
|
|
2
3
|
import {
|
|
3
4
|
defineTable,
|
|
4
5
|
GenericTableSearchIndexes,
|
|
6
|
+
SchemaDefinition,
|
|
5
7
|
TableDefinition,
|
|
6
8
|
} from "convex/server";
|
|
7
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
GenericId,
|
|
11
|
+
Infer,
|
|
12
|
+
ObjectType,
|
|
13
|
+
v,
|
|
14
|
+
VId,
|
|
15
|
+
VObject,
|
|
16
|
+
VUnion,
|
|
17
|
+
} from "convex/values";
|
|
8
18
|
import { QueryCtx } from "../_generated/server";
|
|
9
19
|
|
|
10
20
|
// We only generate embeddings for non-tool, non-system messages
|
|
11
21
|
const embeddings = {
|
|
12
22
|
model: v.string(),
|
|
13
|
-
|
|
23
|
+
// What table it's stored in. (usually messages or memories)
|
|
24
|
+
table: v.string(),
|
|
14
25
|
userId: v.optional(v.string()),
|
|
15
26
|
threadId: v.optional(v.string()),
|
|
16
27
|
// not set for private threads
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
model_table_userId: v.optional(v.array(v.string())),
|
|
29
|
+
model_table_threadId: v.optional(v.array(v.string())),
|
|
19
30
|
vector: v.array(v.number()),
|
|
20
31
|
};
|
|
21
32
|
|
|
33
|
+
export const vEmbeddingsWithoutDenormalizedFields = v.object(
|
|
34
|
+
omit(embeddings, ["model_table_userId", "model_table_threadId"])
|
|
35
|
+
);
|
|
36
|
+
export type EmbeddingsWithoutDenormalizedFields = Infer<
|
|
37
|
+
typeof vEmbeddingsWithoutDenormalizedFields
|
|
38
|
+
>;
|
|
39
|
+
|
|
22
40
|
function table<D extends number>(dimensions: D): Table<D> {
|
|
23
41
|
return defineTable(embeddings)
|
|
24
42
|
.vectorIndex("vector", {
|
|
25
43
|
vectorField: "vector",
|
|
26
44
|
dimensions,
|
|
27
|
-
filterFields: ["
|
|
45
|
+
filterFields: ["model_table_userId", "model_table_threadId"],
|
|
28
46
|
})
|
|
29
|
-
.index("
|
|
47
|
+
.index("model_table_threadId", ["model", "table", "threadId"]);
|
|
30
48
|
}
|
|
31
49
|
|
|
50
|
+
export type VectorSchema = SchemaDefinition<
|
|
51
|
+
{ [key in VectorTableName]: Table<128> },
|
|
52
|
+
true
|
|
53
|
+
>;
|
|
54
|
+
|
|
32
55
|
export const VectorDimensions = [
|
|
33
56
|
128, 256, 512, 768, 1024, 1536, 2048, 3072, 4096,
|
|
34
57
|
] as const;
|
|
58
|
+
export function validateVectorDimension(
|
|
59
|
+
dimension: number
|
|
60
|
+
): asserts dimension is VectorDimension {
|
|
61
|
+
if (!VectorDimensions.includes(dimension as VectorDimension)) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Unsupported vector dimension${dimension}. Supported: ${VectorDimensions.join(", ")}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
35
67
|
export type VectorDimension = (typeof VectorDimensions)[number];
|
|
36
68
|
export const VectorTableNames = VectorDimensions.map(
|
|
37
69
|
(d) => `embeddings_${d}`
|
package/src/validators.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Infer, v } from "convex/values";
|
|
2
|
+
import { vVectorDimension } from "./component/vector/tables";
|
|
2
3
|
|
|
3
4
|
// const deprecated = v.optional(v.any()) as unknown as VNull<unknown, "optional">;
|
|
4
5
|
|
|
@@ -243,19 +244,18 @@ export const vStep = v.object({
|
|
|
243
244
|
});
|
|
244
245
|
export type Step = Infer<typeof vStep>;
|
|
245
246
|
|
|
246
|
-
export const
|
|
247
|
+
export const vStepWithMessages = v.object({
|
|
247
248
|
step: vStep,
|
|
248
249
|
messages: v.array(vMessageWithFileAndId),
|
|
249
250
|
});
|
|
250
|
-
export type StepWithMessagesWithFileAndId = Infer<
|
|
251
|
-
typeof vStepWithMessagesWithFileAndId
|
|
252
|
-
>;
|
|
251
|
+
export type StepWithMessagesWithFileAndId = Infer<typeof vStepWithMessages>;
|
|
253
252
|
|
|
254
253
|
export const vSearchOptions = v.object({
|
|
255
254
|
vector: v.optional(v.array(v.number())),
|
|
256
255
|
vectorModel: v.optional(v.string()),
|
|
257
256
|
text: v.optional(v.string()),
|
|
258
257
|
limit: v.number(),
|
|
258
|
+
vectorScoreThreshold: v.optional(v.number()),
|
|
259
259
|
messageRange: v.optional(v.object({ before: v.number(), after: v.number() })),
|
|
260
260
|
});
|
|
261
261
|
export type SearchOptions = Infer<typeof vSearchOptions>;
|
|
@@ -291,3 +291,10 @@ export const vObjectArgs = v.object({
|
|
|
291
291
|
prompt: v.optional(v.string()),
|
|
292
292
|
messages: v.optional(v.array(vMessage)),
|
|
293
293
|
});
|
|
294
|
+
|
|
295
|
+
export const vEmbeddingsWithMetadata = v.object({
|
|
296
|
+
vectors: v.array(v.union(v.array(v.number()), v.null())),
|
|
297
|
+
dimension: vVectorDimension,
|
|
298
|
+
model: v.string(),
|
|
299
|
+
});
|
|
300
|
+
export type EmbeddingsWithMetadata = Infer<typeof vEmbeddingsWithMetadata>;
|