@convex-dev/rag 0.1.7
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/LICENSE +201 -0
- package/README.md +371 -0
- package/dist/client/_generated/_ignore.d.ts +1 -0
- package/dist/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/client/_generated/_ignore.js +3 -0
- package/dist/client/_generated/_ignore.js.map +1 -0
- package/dist/client/defaultChunker.d.ts +15 -0
- package/dist/client/defaultChunker.d.ts.map +1 -0
- package/dist/client/defaultChunker.js +148 -0
- package/dist/client/defaultChunker.js.map +1 -0
- package/dist/client/fileUtils.d.ts +24 -0
- package/dist/client/fileUtils.d.ts.map +1 -0
- package/dist/client/fileUtils.js +179 -0
- package/dist/client/fileUtils.js.map +1 -0
- package/dist/client/index.d.ts +442 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +597 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +29 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/component/_generated/api.d.ts +439 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +22 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +60 -0
- package/dist/component/_generated/server.d.ts +149 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +74 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/chunks.d.ts +139 -0
- package/dist/component/chunks.d.ts.map +1 -0
- package/dist/component/chunks.js +413 -0
- package/dist/component/chunks.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +6 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/embeddings/importance.d.ts +21 -0
- package/dist/component/embeddings/importance.d.ts.map +1 -0
- package/dist/component/embeddings/importance.js +67 -0
- package/dist/component/embeddings/importance.js.map +1 -0
- package/dist/component/embeddings/index.d.ts +23 -0
- package/dist/component/embeddings/index.d.ts.map +1 -0
- package/dist/component/embeddings/index.js +54 -0
- package/dist/component/embeddings/index.js.map +1 -0
- package/dist/component/embeddings/tables.d.ts +39 -0
- package/dist/component/embeddings/tables.d.ts.map +1 -0
- package/dist/component/embeddings/tables.js +53 -0
- package/dist/component/embeddings/tables.js.map +1 -0
- package/dist/component/entries.d.ts +167 -0
- package/dist/component/entries.d.ts.map +1 -0
- package/dist/component/entries.js +409 -0
- package/dist/component/entries.js.map +1 -0
- package/dist/component/filters.d.ts +46 -0
- package/dist/component/filters.d.ts.map +1 -0
- package/dist/component/filters.js +72 -0
- package/dist/component/filters.js.map +1 -0
- package/dist/component/namespaces.d.ts +131 -0
- package/dist/component/namespaces.d.ts.map +1 -0
- package/dist/component/namespaces.js +222 -0
- package/dist/component/namespaces.js.map +1 -0
- package/dist/component/schema.d.ts +1697 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +88 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/search.d.ts +20 -0
- package/dist/component/search.d.ts.map +1 -0
- package/dist/component/search.js +69 -0
- package/dist/component/search.js.map +1 -0
- package/dist/package.json +3 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -0
- package/dist/shared.d.ts +479 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +98 -0
- package/dist/shared.js.map +1 -0
- package/package.json +97 -0
- package/src/client/_generated/_ignore.ts +1 -0
- package/src/client/defaultChunker.test.ts +243 -0
- package/src/client/defaultChunker.ts +183 -0
- package/src/client/fileUtils.ts +179 -0
- package/src/client/index.test.ts +475 -0
- package/src/client/index.ts +1125 -0
- package/src/client/setup.test.ts +28 -0
- package/src/client/types.ts +69 -0
- package/src/component/_generated/api.d.ts +439 -0
- package/src/component/_generated/api.js +23 -0
- package/src/component/_generated/dataModel.d.ts +60 -0
- package/src/component/_generated/server.d.ts +149 -0
- package/src/component/_generated/server.js +90 -0
- package/src/component/chunks.test.ts +915 -0
- package/src/component/chunks.ts +555 -0
- package/src/component/convex.config.ts +7 -0
- package/src/component/embeddings/importance.test.ts +249 -0
- package/src/component/embeddings/importance.ts +75 -0
- package/src/component/embeddings/index.test.ts +482 -0
- package/src/component/embeddings/index.ts +99 -0
- package/src/component/embeddings/tables.ts +114 -0
- package/src/component/entries.test.ts +341 -0
- package/src/component/entries.ts +546 -0
- package/src/component/filters.ts +119 -0
- package/src/component/namespaces.ts +299 -0
- package/src/component/schema.ts +106 -0
- package/src/component/search.test.ts +445 -0
- package/src/component/search.ts +97 -0
- package/src/component/setup.test.ts +5 -0
- package/src/react/index.ts +7 -0
- package/src/shared.ts +247 -0
- package/src/vitest.config.ts +7 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import type { Doc, Id } from "./_generated/dataModel.js";
|
|
2
|
+
import {
|
|
3
|
+
internalQuery,
|
|
4
|
+
mutation,
|
|
5
|
+
query,
|
|
6
|
+
type MutationCtx,
|
|
7
|
+
type QueryCtx,
|
|
8
|
+
} from "./_generated/server.js";
|
|
9
|
+
import { schema, v } from "./schema.js";
|
|
10
|
+
import {
|
|
11
|
+
vNamespace,
|
|
12
|
+
vPaginationResult,
|
|
13
|
+
vActiveStatus,
|
|
14
|
+
type Namespace,
|
|
15
|
+
type NamespaceId,
|
|
16
|
+
type OnCompleteNamespace,
|
|
17
|
+
vStatus,
|
|
18
|
+
statuses,
|
|
19
|
+
filterNamesContain,
|
|
20
|
+
} from "../shared.js";
|
|
21
|
+
import { paginationOptsValidator } from "convex/server";
|
|
22
|
+
import { paginator } from "convex-helpers/server/pagination";
|
|
23
|
+
import type { ObjectType } from "convex/values";
|
|
24
|
+
import { mergedStream, stream } from "convex-helpers/server/stream";
|
|
25
|
+
import { assert } from "convex-helpers";
|
|
26
|
+
|
|
27
|
+
function namespaceIsCompatible(
|
|
28
|
+
existing: Doc<"namespaces">,
|
|
29
|
+
args: {
|
|
30
|
+
modelId: string;
|
|
31
|
+
dimension: number;
|
|
32
|
+
filterNames: string[];
|
|
33
|
+
}
|
|
34
|
+
) {
|
|
35
|
+
// Check basic compatibility
|
|
36
|
+
if (
|
|
37
|
+
existing.modelId !== args.modelId ||
|
|
38
|
+
existing.dimension !== args.dimension
|
|
39
|
+
) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// For filter names, the namespace must support all requested filters
|
|
44
|
+
// but can support additional filters (superset is OK)
|
|
45
|
+
if (!filterNamesContain(existing.filterNames, args.filterNames)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const vNamespaceLookupArgs = {
|
|
53
|
+
namespace: v.string(),
|
|
54
|
+
modelId: v.string(),
|
|
55
|
+
dimension: v.number(),
|
|
56
|
+
filterNames: v.array(v.string()),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const get = query({
|
|
60
|
+
args: vNamespaceLookupArgs,
|
|
61
|
+
returns: v.union(v.null(), vNamespace),
|
|
62
|
+
handler: async (ctx, args) => {
|
|
63
|
+
const namespace = await getCompatibleNamespaceHandler(ctx, args);
|
|
64
|
+
if (!namespace) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return publicNamespace(namespace);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export const getCompatibleNamespace = internalQuery({
|
|
72
|
+
args: vNamespaceLookupArgs,
|
|
73
|
+
returns: v.union(v.null(), v.doc("namespaces")),
|
|
74
|
+
handler: getCompatibleNamespaceHandler,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export async function getCompatibleNamespaceHandler(
|
|
78
|
+
ctx: QueryCtx,
|
|
79
|
+
args: ObjectType<typeof vNamespaceLookupArgs>
|
|
80
|
+
) {
|
|
81
|
+
const iter = ctx.db
|
|
82
|
+
.query("namespaces")
|
|
83
|
+
.withIndex("status_namespace_version", (q) =>
|
|
84
|
+
q.eq("status.kind", "ready").eq("namespace", args.namespace)
|
|
85
|
+
)
|
|
86
|
+
.order("desc");
|
|
87
|
+
for await (const existing of iter) {
|
|
88
|
+
if (namespaceIsCompatible(existing, args)) {
|
|
89
|
+
return existing;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const lookup = query({
|
|
96
|
+
args: {
|
|
97
|
+
namespace: v.string(),
|
|
98
|
+
modelId: v.string(),
|
|
99
|
+
dimension: v.number(),
|
|
100
|
+
filterNames: v.array(v.string()),
|
|
101
|
+
},
|
|
102
|
+
returns: v.union(v.null(), v.id("namespaces")),
|
|
103
|
+
handler: async (ctx, args) => {
|
|
104
|
+
const namespace = await getCompatibleNamespaceHandler(ctx, args);
|
|
105
|
+
if (!namespace) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return namespace._id;
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export const getOrCreate = mutation({
|
|
113
|
+
args: {
|
|
114
|
+
namespace: v.string(),
|
|
115
|
+
status: vActiveStatus,
|
|
116
|
+
onComplete: v.optional(v.string()),
|
|
117
|
+
modelId: v.string(),
|
|
118
|
+
dimension: v.number(),
|
|
119
|
+
filterNames: v.array(v.string()),
|
|
120
|
+
},
|
|
121
|
+
returns: v.object({
|
|
122
|
+
namespaceId: v.id("namespaces"),
|
|
123
|
+
status: vActiveStatus,
|
|
124
|
+
}),
|
|
125
|
+
handler: async (ctx, args) => {
|
|
126
|
+
const { status, onComplete, ...rest } = args;
|
|
127
|
+
const iter = mergedStream(
|
|
128
|
+
statuses.map((status) =>
|
|
129
|
+
stream(ctx.db, schema)
|
|
130
|
+
.query("namespaces")
|
|
131
|
+
.withIndex("status_namespace_version", (q) =>
|
|
132
|
+
q.eq("status.kind", status).eq("namespace", args.namespace)
|
|
133
|
+
)
|
|
134
|
+
.order("desc")
|
|
135
|
+
),
|
|
136
|
+
["version"]
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
let version: number = 0;
|
|
140
|
+
for await (const existing of iter) {
|
|
141
|
+
if (!version) version = existing.version + 1;
|
|
142
|
+
if (existing.status.kind !== args.status) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// see if it's compatible
|
|
146
|
+
if (namespaceIsCompatible(existing, args)) {
|
|
147
|
+
return {
|
|
148
|
+
namespaceId: existing._id,
|
|
149
|
+
status: existing.status.kind,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const namespaceId = await ctx.db.insert("namespaces", {
|
|
154
|
+
status: { kind: "pending", onComplete },
|
|
155
|
+
version,
|
|
156
|
+
...rest,
|
|
157
|
+
});
|
|
158
|
+
if (status === "ready") {
|
|
159
|
+
await promoteToReadyHandler(ctx, { namespaceId });
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
namespaceId,
|
|
163
|
+
status,
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
async function runOnComplete(
|
|
169
|
+
ctx: MutationCtx,
|
|
170
|
+
onComplete: string | undefined,
|
|
171
|
+
namespace: Doc<"namespaces">,
|
|
172
|
+
replacedNamespace: Doc<"namespaces"> | null
|
|
173
|
+
) {
|
|
174
|
+
const onCompleteFn = onComplete as unknown as OnCompleteNamespace;
|
|
175
|
+
if (!onCompleteFn) {
|
|
176
|
+
throw new Error(`On complete function ${onComplete} not found`);
|
|
177
|
+
}
|
|
178
|
+
await ctx.runMutation(onCompleteFn, {
|
|
179
|
+
namespace: publicNamespace(namespace),
|
|
180
|
+
replacedNamespace: replacedNamespace
|
|
181
|
+
? publicNamespace(replacedNamespace)
|
|
182
|
+
: null,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export const promoteToReady = mutation({
|
|
187
|
+
args: {
|
|
188
|
+
namespaceId: v.id("namespaces"),
|
|
189
|
+
},
|
|
190
|
+
returns: v.object({
|
|
191
|
+
replacedVersion: v.union(v.null(), vNamespace),
|
|
192
|
+
}),
|
|
193
|
+
handler: promoteToReadyHandler,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
async function promoteToReadyHandler(
|
|
197
|
+
ctx: MutationCtx,
|
|
198
|
+
args: { namespaceId: Id<"namespaces"> }
|
|
199
|
+
) {
|
|
200
|
+
const namespace = await ctx.db.get(args.namespaceId);
|
|
201
|
+
assert(namespace, `Namespace ${args.namespaceId} not found`);
|
|
202
|
+
if (namespace.status.kind === "ready") {
|
|
203
|
+
console.debug(
|
|
204
|
+
`Namespace ${args.namespaceId} is already ready, not promoting`
|
|
205
|
+
);
|
|
206
|
+
return { replacedVersion: null };
|
|
207
|
+
} else if (namespace.status.kind === "replaced") {
|
|
208
|
+
console.debug(
|
|
209
|
+
`Namespace ${args.namespaceId} is already replaced, not promoting and returning itself`
|
|
210
|
+
);
|
|
211
|
+
return { replacedVersion: publicNamespace(namespace) };
|
|
212
|
+
}
|
|
213
|
+
const previousNamespace = await ctx.db
|
|
214
|
+
.query("namespaces")
|
|
215
|
+
.withIndex("status_namespace_version", (q) =>
|
|
216
|
+
q.eq("status.kind", "ready").eq("namespace", namespace.namespace)
|
|
217
|
+
)
|
|
218
|
+
.order("desc")
|
|
219
|
+
.unique();
|
|
220
|
+
if (previousNamespace) {
|
|
221
|
+
// First mark the previous namespace as replaced,
|
|
222
|
+
// so there are never two "ready" namespaces.
|
|
223
|
+
previousNamespace.status = { kind: "replaced", replacedAt: Date.now() };
|
|
224
|
+
await ctx.db.replace(previousNamespace._id, previousNamespace);
|
|
225
|
+
}
|
|
226
|
+
// Only then mark the current namespace as ready,
|
|
227
|
+
// so there are never two "ready" namespaces.
|
|
228
|
+
const previousStatus = namespace.status;
|
|
229
|
+
namespace.status = { kind: "ready" };
|
|
230
|
+
await ctx.db.replace(args.namespaceId, namespace);
|
|
231
|
+
// Then run the onComplete function where it can observe itself as "ready".
|
|
232
|
+
if (previousStatus.kind === "pending" && previousStatus.onComplete) {
|
|
233
|
+
await runOnComplete(
|
|
234
|
+
ctx,
|
|
235
|
+
previousStatus.onComplete,
|
|
236
|
+
namespace,
|
|
237
|
+
previousNamespace
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
const previousPendingNamespaces = await ctx.db
|
|
241
|
+
.query("namespaces")
|
|
242
|
+
.withIndex("status_namespace_version", (q) =>
|
|
243
|
+
q
|
|
244
|
+
.eq("status.kind", "pending")
|
|
245
|
+
.eq("namespace", namespace.namespace)
|
|
246
|
+
.lt("version", namespace.version)
|
|
247
|
+
)
|
|
248
|
+
.collect();
|
|
249
|
+
// Then mark all previous pending namespaces as replaced,
|
|
250
|
+
// so they can observe the new namespace and onComplete side-effects.
|
|
251
|
+
await Promise.all(
|
|
252
|
+
previousPendingNamespaces.map(async (namespace) => {
|
|
253
|
+
const previousStatus = namespace.status;
|
|
254
|
+
namespace.status = { kind: "replaced", replacedAt: Date.now() };
|
|
255
|
+
await ctx.db.replace(namespace._id, namespace);
|
|
256
|
+
if (previousStatus.kind === "pending" && previousStatus.onComplete) {
|
|
257
|
+
await runOnComplete(ctx, previousStatus.onComplete, namespace, null);
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
);
|
|
261
|
+
return {
|
|
262
|
+
replacedVersion: previousNamespace
|
|
263
|
+
? publicNamespace(previousNamespace)
|
|
264
|
+
: null,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export const list = query({
|
|
269
|
+
args: v.object({
|
|
270
|
+
paginationOpts: paginationOptsValidator,
|
|
271
|
+
status: vStatus,
|
|
272
|
+
}),
|
|
273
|
+
returns: vPaginationResult(vNamespace),
|
|
274
|
+
handler: async (ctx, args) => {
|
|
275
|
+
const namespaces = await paginator(ctx.db, schema)
|
|
276
|
+
.query("namespaces")
|
|
277
|
+
.withIndex("status_namespace_version", (q) =>
|
|
278
|
+
q.eq("status.kind", args.status ?? "ready")
|
|
279
|
+
)
|
|
280
|
+
.order("desc")
|
|
281
|
+
.paginate(args.paginationOpts);
|
|
282
|
+
return {
|
|
283
|
+
...namespaces,
|
|
284
|
+
page: namespaces.page.map(publicNamespace),
|
|
285
|
+
};
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
export function publicNamespace(namespace: Doc<"namespaces">): Namespace {
|
|
290
|
+
const { _id, _creationTime, status, ...rest } = namespace;
|
|
291
|
+
return {
|
|
292
|
+
namespaceId: _id as unknown as NamespaceId,
|
|
293
|
+
createdAt: _creationTime,
|
|
294
|
+
...rest,
|
|
295
|
+
status: status.kind,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// TODO: deletion
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { defineSchema, defineTable } from "convex/server";
|
|
2
|
+
import { v, type Infer } from "convex/values";
|
|
3
|
+
import embeddingsTables, { vVectorId } from "./embeddings/tables.js";
|
|
4
|
+
import { typedV } from "convex-helpers/validators";
|
|
5
|
+
import {
|
|
6
|
+
allFilterFieldNames,
|
|
7
|
+
vAllFilterFields,
|
|
8
|
+
vNamedFilter,
|
|
9
|
+
} from "./filters.js";
|
|
10
|
+
|
|
11
|
+
export const vStatusWithOnComplete = v.union(
|
|
12
|
+
v.object({
|
|
13
|
+
kind: v.literal("pending"),
|
|
14
|
+
// Callback function handle for when the namespace/entry is ready/failed.
|
|
15
|
+
onComplete: v.optional(v.string()),
|
|
16
|
+
}),
|
|
17
|
+
v.object({
|
|
18
|
+
kind: v.literal("ready"),
|
|
19
|
+
}),
|
|
20
|
+
v.object({
|
|
21
|
+
kind: v.literal("replaced"),
|
|
22
|
+
replacedAt: v.number(),
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export type StatusWithOnComplete = Infer<typeof vStatusWithOnComplete>;
|
|
27
|
+
|
|
28
|
+
export const schema = defineSchema({
|
|
29
|
+
namespaces: defineTable({
|
|
30
|
+
// user-specified id, eg. userId or "documentation"
|
|
31
|
+
namespace: v.string(),
|
|
32
|
+
version: v.number(),
|
|
33
|
+
modelId: v.string(),
|
|
34
|
+
dimension: v.number(),
|
|
35
|
+
filterNames: v.array(v.string()),
|
|
36
|
+
status: vStatusWithOnComplete,
|
|
37
|
+
}).index("status_namespace_version", ["status.kind", "namespace", "version"]),
|
|
38
|
+
entries: defineTable({
|
|
39
|
+
key: v.optional(v.string()),
|
|
40
|
+
namespaceId: v.id("namespaces"),
|
|
41
|
+
version: v.number(),
|
|
42
|
+
importance: v.number(),
|
|
43
|
+
filterValues: v.array(vNamedFilter),
|
|
44
|
+
// To avoid re-creating/ updating the same entry
|
|
45
|
+
// This is a hash that ideally encompasses the content AND chunking strategy
|
|
46
|
+
// e.g. a hash of the list of chunk content hashes.
|
|
47
|
+
contentHash: v.optional(v.string()),
|
|
48
|
+
// conveneient metadata
|
|
49
|
+
title: v.optional(v.string()),
|
|
50
|
+
metadata: v.optional(v.record(v.string(), v.any())),
|
|
51
|
+
status: vStatusWithOnComplete,
|
|
52
|
+
})
|
|
53
|
+
.index("namespaceId_status_key_version", [
|
|
54
|
+
"namespaceId",
|
|
55
|
+
"status.kind",
|
|
56
|
+
"key",
|
|
57
|
+
"version",
|
|
58
|
+
])
|
|
59
|
+
// To look up most recently changed entries
|
|
60
|
+
.index("status_namespaceId", ["status.kind", "namespaceId"]),
|
|
61
|
+
chunks: defineTable({
|
|
62
|
+
entryId: v.id("entries"),
|
|
63
|
+
order: v.number(),
|
|
64
|
+
state: v.union(
|
|
65
|
+
v.object({
|
|
66
|
+
kind: v.literal("pending"),
|
|
67
|
+
embedding: v.array(v.number()),
|
|
68
|
+
importance: v.number(),
|
|
69
|
+
pendingSearchableText: v.optional(v.string()),
|
|
70
|
+
}),
|
|
71
|
+
v.object({
|
|
72
|
+
kind: v.literal("ready"),
|
|
73
|
+
embeddingId: vVectorId,
|
|
74
|
+
// TODO: text search
|
|
75
|
+
searchableText: v.optional(v.string()),
|
|
76
|
+
}),
|
|
77
|
+
v.object({
|
|
78
|
+
kind: v.literal("replaced"),
|
|
79
|
+
embeddingId: vVectorId,
|
|
80
|
+
vector: v.array(v.number()),
|
|
81
|
+
pendingSearchableText: v.optional(v.string()),
|
|
82
|
+
})
|
|
83
|
+
),
|
|
84
|
+
// TODO: should content be inline?
|
|
85
|
+
contentId: v.id("content"),
|
|
86
|
+
...vAllFilterFields,
|
|
87
|
+
})
|
|
88
|
+
.index("entryId_order", ["entryId", "order"])
|
|
89
|
+
.index("embeddingId", ["state.embeddingId"])
|
|
90
|
+
.searchIndex("searchableText", {
|
|
91
|
+
searchField: "state.searchableText",
|
|
92
|
+
filterFields: allFilterFieldNames,
|
|
93
|
+
}),
|
|
94
|
+
content: defineTable({
|
|
95
|
+
text: v.string(),
|
|
96
|
+
// convenient metadata
|
|
97
|
+
metadata: v.optional(v.record(v.string(), v.any())),
|
|
98
|
+
}),
|
|
99
|
+
|
|
100
|
+
...embeddingsTables,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export const vv = typedV(schema);
|
|
104
|
+
export { vv as v };
|
|
105
|
+
|
|
106
|
+
export default schema;
|