@convex-dev/rag 0.5.4 → 0.6.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 (82) hide show
  1. package/README.md +89 -82
  2. package/dist/client/index.d.ts +30 -26
  3. package/dist/client/index.d.ts.map +1 -1
  4. package/dist/client/index.js +2 -2
  5. package/dist/client/index.js.map +1 -1
  6. package/dist/component/_generated/api.d.ts +25 -482
  7. package/dist/component/_generated/api.d.ts.map +1 -1
  8. package/dist/component/_generated/api.js +10 -1
  9. package/dist/component/_generated/api.js.map +1 -1
  10. package/dist/component/_generated/component.d.ts +380 -0
  11. package/dist/component/_generated/component.d.ts.map +1 -0
  12. package/dist/component/_generated/component.js +11 -0
  13. package/dist/component/_generated/component.js.map +1 -0
  14. package/dist/component/_generated/dataModel.d.ts +4 -18
  15. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  16. package/dist/component/_generated/dataModel.js +11 -0
  17. package/dist/component/_generated/dataModel.js.map +1 -0
  18. package/dist/component/_generated/server.d.ts +10 -38
  19. package/dist/component/_generated/server.d.ts.map +1 -1
  20. package/dist/component/_generated/server.js +9 -5
  21. package/dist/component/_generated/server.js.map +1 -1
  22. package/dist/component/chunks.d.ts +5 -5
  23. package/dist/component/chunks.d.ts.map +1 -1
  24. package/dist/component/chunks.js +21 -51
  25. package/dist/component/chunks.js.map +1 -1
  26. package/dist/component/embeddings/tables.d.ts +4 -5
  27. package/dist/component/embeddings/tables.d.ts.map +1 -1
  28. package/dist/component/embeddings/tables.js.map +1 -1
  29. package/dist/component/entries.d.ts +6 -6
  30. package/dist/component/namespaces.d.ts +8 -8
  31. package/dist/component/namespaces.d.ts.map +1 -1
  32. package/dist/component/namespaces.js +2 -2
  33. package/dist/component/namespaces.js.map +1 -1
  34. package/dist/component/schema.d.ts +185 -224
  35. package/dist/component/schema.d.ts.map +1 -1
  36. package/dist/component/search.d.ts +4 -3
  37. package/dist/component/search.d.ts.map +1 -1
  38. package/dist/component/search.js +1 -1
  39. package/dist/component/search.js.map +1 -1
  40. package/dist/shared.d.ts +9 -4
  41. package/dist/shared.d.ts.map +1 -1
  42. package/dist/shared.js +1 -4
  43. package/dist/shared.js.map +1 -1
  44. package/package.json +72 -44
  45. package/src/client/defaultChunker.test.ts +1 -1
  46. package/src/client/defaultChunker.ts +7 -7
  47. package/src/client/fileUtils.ts +3 -3
  48. package/src/client/hybridRank.ts +1 -1
  49. package/src/client/index.test.ts +18 -18
  50. package/src/client/index.ts +104 -84
  51. package/src/client/setup.test.ts +2 -2
  52. package/src/component/_generated/api.ts +66 -0
  53. package/src/component/_generated/component.ts +442 -0
  54. package/src/component/_generated/{server.d.ts → server.ts} +33 -21
  55. package/src/component/chunks.test.ts +14 -14
  56. package/src/component/chunks.ts +59 -88
  57. package/src/component/embeddings/importance.test.ts +4 -4
  58. package/src/component/embeddings/importance.ts +1 -1
  59. package/src/component/embeddings/index.test.ts +3 -4
  60. package/src/component/embeddings/index.ts +6 -6
  61. package/src/component/embeddings/tables.ts +9 -8
  62. package/src/component/entries.test.ts +10 -10
  63. package/src/component/entries.ts +29 -29
  64. package/src/component/filters.ts +8 -8
  65. package/src/component/namespaces.ts +31 -34
  66. package/src/component/schema.ts +2 -2
  67. package/src/component/search.test.ts +5 -5
  68. package/src/component/search.ts +8 -9
  69. package/src/component/setup.test.ts +2 -8
  70. package/src/shared.ts +47 -45
  71. package/src/test.ts +20 -0
  72. package/dist/client/types.d.ts +0 -29
  73. package/dist/client/types.d.ts.map +0 -1
  74. package/dist/client/types.js +0 -2
  75. package/dist/client/types.js.map +0 -1
  76. package/dist/package.json +0 -3
  77. package/src/client/types.ts +0 -69
  78. package/src/component/_generated/api.d.ts +0 -507
  79. package/src/component/_generated/api.js +0 -23
  80. package/src/component/_generated/server.js +0 -90
  81. package/src/vitest.config.ts +0 -7
  82. /package/src/component/_generated/{dataModel.d.ts → dataModel.ts} +0 -0
@@ -111,7 +111,7 @@ export const addAsync = mutation({
111
111
  name: workpoolName(namespace.namespace, args.entry.key, entryId),
112
112
  onComplete: internal.entries.addAsyncOnComplete,
113
113
  context: entryId,
114
- }
114
+ },
115
115
  );
116
116
  return { entryId, status: status.kind, created: true };
117
117
  },
@@ -120,7 +120,7 @@ export const addAsync = mutation({
120
120
  function workpoolName(
121
121
  namespace: string,
122
122
  key: string | undefined,
123
- entryId: Id<"entries">
123
+ entryId: Id<"entries">,
124
124
  ) {
125
125
  return `rag-async-${namespace}-${key ? key + "-" + entryId : entryId}`;
126
126
  }
@@ -137,7 +137,7 @@ export const addAsyncOnComplete = internalMutation({
137
137
  const entry = await ctx.db.get(args.context);
138
138
  if (!entry) {
139
139
  console.error(
140
- `Entry ${args.context} not found when trying to complete chunker for async add`
140
+ `Entry ${args.context} not found when trying to complete chunker for async add`,
141
141
  );
142
142
  return;
143
143
  }
@@ -154,7 +154,7 @@ export const addAsyncOnComplete = internalMutation({
154
154
  namespace,
155
155
  entry,
156
156
  null,
157
- args.result.kind === "canceled" ? "Canceled" : args.result.error
157
+ args.result.kind === "canceled" ? "Canceled" : args.result.error,
158
158
  );
159
159
  }
160
160
  }
@@ -169,7 +169,7 @@ type AddEntryArgs = Pick<
169
169
  async function findExistingEntry(
170
170
  ctx: MutationCtx,
171
171
  namespaceId: Id<"namespaces">,
172
- key: string | undefined
172
+ key: string | undefined,
173
173
  ) {
174
174
  if (!key) {
175
175
  return null;
@@ -182,11 +182,11 @@ async function findExistingEntry(
182
182
  q
183
183
  .eq("namespaceId", namespaceId)
184
184
  .eq("status.kind", status)
185
- .eq("key", key)
185
+ .eq("key", key),
186
186
  )
187
- .order("desc")
187
+ .order("desc"),
188
188
  ),
189
- ["version"]
189
+ ["version"],
190
190
  ).first();
191
191
  return existing;
192
192
  }
@@ -256,7 +256,7 @@ async function runOnComplete(
256
256
  namespace: Doc<"namespaces">,
257
257
  entry: Doc<"entries">,
258
258
  replacedEntry: Doc<"entries"> | null,
259
- error?: string
259
+ error?: string,
260
260
  ) {
261
261
  await ctx.runMutation(onComplete as unknown as OnComplete, {
262
262
  namespace: publicNamespace(namespace),
@@ -282,8 +282,8 @@ function entryIsSame(existing: Doc<"entries">, newEntry: AddEntryArgs) {
282
282
  if (
283
283
  !existing.filterValues.every((filter) =>
284
284
  newEntry.filterValues.some(
285
- (f) => f.name === filter.name && f.value === filter.value
286
- )
285
+ (f) => f.name === filter.name && f.value === filter.value,
286
+ ),
287
287
  )
288
288
  ) {
289
289
  return false;
@@ -309,7 +309,7 @@ export const list = query({
309
309
  .withIndex("status_namespaceId", (q) =>
310
310
  namespaceId
311
311
  ? q.eq("status.kind", args.status).eq("namespaceId", namespaceId)
312
- : q.eq("status.kind", args.status)
312
+ : q.eq("status.kind", args.status),
313
313
  )
314
314
  .order(args.order ?? "asc")
315
315
  .paginate(args.paginationOpts);
@@ -359,16 +359,16 @@ export const findByContentHash = query({
359
359
  q
360
360
  .eq("namespaceId", namespace._id)
361
361
  .eq("status.kind", status)
362
- .eq("key", args.key)
362
+ .eq("key", args.key),
363
363
  )
364
- .order("desc")
364
+ .order("desc"),
365
365
  ),
366
- ["version"]
366
+ ["version"],
367
367
  )) {
368
368
  attempts++;
369
369
  if (attempts > 20) {
370
370
  console.debug(
371
- `Giving up after checking ${attempts} entries for ${args.key} content hash ${args.contentHash}, returning null`
371
+ `Giving up after checking ${attempts} entries for ${args.key} content hash ${args.contentHash}, returning null`,
372
372
  );
373
373
  return null;
374
374
  }
@@ -407,7 +407,7 @@ export const promoteToReady = mutation({
407
407
 
408
408
  async function promoteToReadyHandler(
409
409
  ctx: MutationCtx,
410
- args: { entryId: Id<"entries"> }
410
+ args: { entryId: Id<"entries"> },
411
411
  ) {
412
412
  const entry = await ctx.db.get(args.entryId);
413
413
  assert(entry, `Entry ${args.entryId} not found`);
@@ -418,7 +418,7 @@ async function promoteToReadyHandler(
418
418
  return { replacedEntry: null };
419
419
  } else if (entry.status.kind === "replaced") {
420
420
  console.debug(
421
- `Entry ${args.entryId} is already replaced, returning the current version...`
421
+ `Entry ${args.entryId} is already replaced, returning the current version...`,
422
422
  );
423
423
  return { replacedEntry: publicEntry(entry) };
424
424
  }
@@ -441,7 +441,7 @@ async function promoteToReadyHandler(
441
441
  previousStatus.onComplete,
442
442
  namespace,
443
443
  entry,
444
- previousEntry
444
+ previousEntry,
445
445
  );
446
446
  }
447
447
  // Then mark all previous pending entries as replaced,
@@ -454,7 +454,7 @@ async function promoteToReadyHandler(
454
454
  .eq("namespaceId", entry.namespaceId)
455
455
  .eq("status.kind", "pending")
456
456
  .eq("key", entry.key)
457
- .lt("version", entry.version)
457
+ .lt("version", entry.version),
458
458
  )
459
459
  .collect();
460
460
  await Promise.all(
@@ -468,10 +468,10 @@ async function promoteToReadyHandler(
468
468
  previousStatus.onComplete,
469
469
  namespace,
470
470
  entry,
471
- null
471
+ null,
472
472
  );
473
473
  }
474
- })
474
+ }),
475
475
  );
476
476
  }
477
477
  return {
@@ -489,7 +489,7 @@ export async function getPreviousEntry(ctx: QueryCtx, entry: Doc<"entries">) {
489
489
  q
490
490
  .eq("namespaceId", entry.namespaceId)
491
491
  .eq("status.kind", "ready")
492
- .eq("key", entry.key)
492
+ .eq("key", entry.key),
493
493
  )
494
494
  .unique();
495
495
  if (previousEntry?._id === entry._id) return null;
@@ -542,7 +542,7 @@ export const deleteAsync = mutation({
542
542
 
543
543
  async function deleteAsyncHandler(
544
544
  ctx: MutationCtx,
545
- args: { entryId: Id<"entries">; startOrder: number }
545
+ args: { entryId: Id<"entries">; startOrder: number },
546
546
  ) {
547
547
  const { entryId, startOrder } = args;
548
548
  const entry = await ctx.db.get(entryId);
@@ -614,7 +614,7 @@ export const deleteByKeyAsync = mutation({
614
614
 
615
615
  async function getEntriesByKey(
616
616
  ctx: QueryCtx,
617
- args: { namespaceId: Id<"namespaces">; key: string; beforeVersion?: number }
617
+ args: { namespaceId: Id<"namespaces">; key: string; beforeVersion?: number },
618
618
  ): Promise<Doc<"entries">[]> {
619
619
  return mergedStream(
620
620
  statuses.map((status) =>
@@ -625,11 +625,11 @@ async function getEntriesByKey(
625
625
  .eq("namespaceId", args.namespaceId)
626
626
  .eq("status.kind", status)
627
627
  .eq("key", args.key)
628
- .lt("version", args.beforeVersion ?? Infinity)
628
+ .lt("version", args.beforeVersion ?? Infinity),
629
629
  )
630
- .order("desc")
630
+ .order("desc"),
631
631
  ),
632
- ["version"]
632
+ ["version"],
633
633
  ).take(100);
634
634
  }
635
635
 
@@ -653,7 +653,7 @@ export const deleteByKeySync = action({
653
653
  while (true) {
654
654
  const entries: Doc<"entries">[] = await ctx.runQuery(
655
655
  internal.entries.getEntriesForNamespaceByKey,
656
- { namespaceId: args.namespaceId, key: args.key }
656
+ { namespaceId: args.namespaceId, key: args.key },
657
657
  );
658
658
  for await (const entry of entries) {
659
659
  await ctx.runAction(api.entries.deleteSync, {
@@ -55,7 +55,7 @@ export type NamedFilter<K extends string = string, V = Value> = {
55
55
  */
56
56
  export function filterFieldsFromNumbers(
57
57
  namespaceId: GenericId<"namespaces">,
58
- filters: NumberedFilter | undefined
58
+ filters: NumberedFilter | undefined,
59
59
  ): NamedFilterField {
60
60
  const filterFields: NamedFilterField = {};
61
61
  if (!filters) return filterFields;
@@ -63,7 +63,7 @@ export function filterFieldsFromNumbers(
63
63
  const index = Number(i);
64
64
  if (isNaN(index) || index < 0 || index >= filterFieldNames.length) {
65
65
  console.warn(
66
- `Unknown filter index: ${index} for value ${JSON.stringify(filter)}`
66
+ `Unknown filter index: ${index} for value ${JSON.stringify(filter)}`,
67
67
  );
68
68
  break;
69
69
  }
@@ -78,7 +78,7 @@ export function filterFieldsFromNumbers(
78
78
  */
79
79
  export function numberedFilterFromNamedFilters(
80
80
  namedFilters: Array<{ name: string; value: Value }>,
81
- filterNames: string[]
81
+ filterNames: string[],
82
82
  ): NumberedFilter {
83
83
  const numberedFilter: NumberedFilter = {};
84
84
  for (const namedFilter of namedFilters) {
@@ -86,8 +86,8 @@ export function numberedFilterFromNamedFilters(
86
86
  if (index === -1) {
87
87
  throw new Error(
88
88
  `Unknown filter name: ${namedFilter.name} for namespace with names ${filterNames.join(
89
- ", "
90
- )}`
89
+ ", ",
90
+ )}`,
91
91
  );
92
92
  }
93
93
  numberedFilter[index] = namedFilter.value;
@@ -101,7 +101,7 @@ export function numberedFilterFromNamedFilters(
101
101
  */
102
102
  export function numberedFiltersFromNamedFilters(
103
103
  filters: NamedFilter[],
104
- filterNames: string[]
104
+ filterNames: string[],
105
105
  ): Array<NumberedFilter> {
106
106
  const filterFields: Array<NumberedFilter> = [];
107
107
  for (const filter of filters) {
@@ -109,8 +109,8 @@ export function numberedFiltersFromNamedFilters(
109
109
  if (index === -1) {
110
110
  throw new Error(
111
111
  `Unknown filter name: ${filter.name} for namespace with names ${filterNames.join(
112
- ", "
113
- )}`
112
+ ", ",
113
+ )}`,
114
114
  );
115
115
  }
116
116
  filterFields.push({ [index]: filter.value });
@@ -18,11 +18,11 @@ import {
18
18
  vStatus,
19
19
  statuses,
20
20
  filterNamesContain,
21
- Entry,
21
+ vEntry,
22
22
  } from "../shared.js";
23
23
  import { paginationOptsValidator, PaginationResult } from "convex/server";
24
24
  import { paginator } from "convex-helpers/server/pagination";
25
- import type { ObjectType } from "convex/values";
25
+ import type { Infer, ObjectType } from "convex/values";
26
26
  import { mergedStream, stream } from "convex-helpers/server/stream";
27
27
  import { assert } from "convex-helpers";
28
28
  import { api } from "./_generated/api.js";
@@ -33,7 +33,7 @@ function namespaceIsCompatible(
33
33
  modelId: string;
34
34
  dimension: number;
35
35
  filterNames: string[];
36
- }
36
+ },
37
37
  ) {
38
38
  // Check basic compatibility
39
39
  if (
@@ -79,12 +79,12 @@ export const getCompatibleNamespace = internalQuery({
79
79
 
80
80
  export async function getCompatibleNamespaceHandler(
81
81
  ctx: QueryCtx,
82
- args: ObjectType<typeof vNamespaceLookupArgs>
82
+ args: ObjectType<typeof vNamespaceLookupArgs>,
83
83
  ) {
84
84
  const iter = ctx.db
85
85
  .query("namespaces")
86
86
  .withIndex("status_namespace_version", (q) =>
87
- q.eq("status.kind", "ready").eq("namespace", args.namespace)
87
+ q.eq("status.kind", "ready").eq("namespace", args.namespace),
88
88
  )
89
89
  .order("desc");
90
90
  for await (const existing of iter) {
@@ -132,11 +132,11 @@ export const getOrCreate = mutation({
132
132
  stream(ctx.db, schema)
133
133
  .query("namespaces")
134
134
  .withIndex("status_namespace_version", (q) =>
135
- q.eq("status.kind", status).eq("namespace", args.namespace)
135
+ q.eq("status.kind", status).eq("namespace", args.namespace),
136
136
  )
137
- .order("desc")
137
+ .order("desc"),
138
138
  ),
139
- ["version"]
139
+ ["version"],
140
140
  );
141
141
 
142
142
  let version: number = 0;
@@ -172,7 +172,7 @@ async function runOnComplete(
172
172
  ctx: MutationCtx,
173
173
  onComplete: string | undefined,
174
174
  namespace: Doc<"namespaces">,
175
- replacedNamespace: Doc<"namespaces"> | null
175
+ replacedNamespace: Doc<"namespaces"> | null,
176
176
  ) {
177
177
  const onCompleteFn = onComplete as unknown as OnCompleteNamespace;
178
178
  if (!onCompleteFn) {
@@ -198,25 +198,25 @@ export const promoteToReady = mutation({
198
198
 
199
199
  async function promoteToReadyHandler(
200
200
  ctx: MutationCtx,
201
- args: { namespaceId: Id<"namespaces"> }
201
+ args: { namespaceId: Id<"namespaces"> },
202
202
  ) {
203
203
  const namespace = await ctx.db.get(args.namespaceId);
204
204
  assert(namespace, `Namespace ${args.namespaceId} not found`);
205
205
  if (namespace.status.kind === "ready") {
206
206
  console.debug(
207
- `Namespace ${args.namespaceId} is already ready, not promoting`
207
+ `Namespace ${args.namespaceId} is already ready, not promoting`,
208
208
  );
209
209
  return { replacedNamespace: null };
210
210
  } else if (namespace.status.kind === "replaced") {
211
211
  console.debug(
212
- `Namespace ${args.namespaceId} is already replaced, not promoting and returning itself`
212
+ `Namespace ${args.namespaceId} is already replaced, not promoting and returning itself`,
213
213
  );
214
214
  return { replacedNamespace: publicNamespace(namespace) };
215
215
  }
216
216
  const previousNamespace = await ctx.db
217
217
  .query("namespaces")
218
218
  .withIndex("status_namespace_version", (q) =>
219
- q.eq("status.kind", "ready").eq("namespace", namespace.namespace)
219
+ q.eq("status.kind", "ready").eq("namespace", namespace.namespace),
220
220
  )
221
221
  .order("desc")
222
222
  .unique();
@@ -237,7 +237,7 @@ async function promoteToReadyHandler(
237
237
  ctx,
238
238
  previousStatus.onComplete,
239
239
  namespace,
240
- previousNamespace
240
+ previousNamespace,
241
241
  );
242
242
  }
243
243
  const previousPendingNamespaces = await ctx.db
@@ -246,7 +246,7 @@ async function promoteToReadyHandler(
246
246
  q
247
247
  .eq("status.kind", "pending")
248
248
  .eq("namespace", namespace.namespace)
249
- .lt("version", namespace.version)
249
+ .lt("version", namespace.version),
250
250
  )
251
251
  .collect();
252
252
  // Then mark all previous pending namespaces as replaced,
@@ -259,7 +259,7 @@ async function promoteToReadyHandler(
259
259
  if (previousStatus.kind === "pending" && previousStatus.onComplete) {
260
260
  await runOnComplete(ctx, previousStatus.onComplete, namespace, null);
261
261
  }
262
- })
262
+ }),
263
263
  );
264
264
  return {
265
265
  replacedNamespace: previousNamespace
@@ -278,7 +278,7 @@ export const list = query({
278
278
  const namespaces = await paginator(ctx.db, schema)
279
279
  .query("namespaces")
280
280
  .withIndex("status_namespace_version", (q) =>
281
- q.eq("status.kind", args.status ?? "ready")
281
+ q.eq("status.kind", args.status ?? "ready"),
282
282
  )
283
283
  .order("desc")
284
284
  .paginate(args.paginationOpts);
@@ -298,11 +298,11 @@ export const listNamespaceVersions = query({
298
298
  stream(ctx.db, schema)
299
299
  .query("namespaces")
300
300
  .withIndex("status_namespace_version", (q) =>
301
- q.eq("status.kind", status).eq("namespace", args.namespace)
301
+ q.eq("status.kind", status).eq("namespace", args.namespace),
302
302
  )
303
- .order("desc")
303
+ .order("desc"),
304
304
  ),
305
- ["version"]
305
+ ["version"],
306
306
  ).paginate(args.paginationOpts);
307
307
 
308
308
  return {
@@ -332,21 +332,21 @@ export const deleteNamespace = mutation({
332
332
 
333
333
  async function deleteHandler(
334
334
  ctx: MutationCtx,
335
- args: { namespaceId: Id<"namespaces"> }
335
+ args: { namespaceId: Id<"namespaces"> },
336
336
  ) {
337
337
  const namespace = await ctx.db.get(args.namespaceId);
338
338
  assert(namespace, `Namespace ${args.namespaceId} not found`);
339
339
  const anyEntry = await ctx.db
340
340
  .query("entries")
341
341
  .withIndex("namespaceId_status_key_version", (q) =>
342
- q.eq("namespaceId", args.namespaceId)
342
+ q.eq("namespaceId", args.namespaceId),
343
343
  )
344
344
  .first();
345
345
  if (anyEntry) {
346
346
  throw new Error(
347
347
  `Namespace ${args.namespaceId} cannot delete, has entries` +
348
348
  "First delete all entries." +
349
- `Entry: ${anyEntry.key} id ${anyEntry._id} (${anyEntry.status.kind})`
349
+ `Entry: ${anyEntry.key} id ${anyEntry._id} (${anyEntry.status.kind})`,
350
350
  );
351
351
  }
352
352
  await ctx.db.delete(args.namespaceId);
@@ -360,17 +360,14 @@ export const deleteNamespaceSync = action({
360
360
  for (const status of statuses) {
361
361
  let cursor: string | null = null;
362
362
  while (true) {
363
- const entries: PaginationResult<Entry> = await ctx.runQuery(
364
- api.entries.list,
365
- {
366
- namespaceId: args.namespaceId,
367
- status: status,
368
- paginationOpts: {
369
- numItems: 100,
370
- cursor,
371
- },
372
- }
373
- );
363
+ const entries = (await ctx.runQuery(api.entries.list, {
364
+ namespaceId: args.namespaceId,
365
+ status: status,
366
+ paginationOpts: {
367
+ numItems: 100,
368
+ cursor,
369
+ },
370
+ })) as PaginationResult<Infer<typeof vEntry>>;
374
371
  if (entries.isDone) {
375
372
  break;
376
373
  }
@@ -20,7 +20,7 @@ export const vStatusWithOnComplete = v.union(
20
20
  v.object({
21
21
  kind: v.literal("replaced"),
22
22
  replacedAt: v.number(),
23
- })
23
+ }),
24
24
  );
25
25
 
26
26
  export type StatusWithOnComplete = Infer<typeof vStatusWithOnComplete>;
@@ -79,7 +79,7 @@ export const schema = defineSchema({
79
79
  embeddingId: vVectorId,
80
80
  vector: v.array(v.number()),
81
81
  pendingSearchableText: v.optional(v.string()),
82
- })
82
+ }),
83
83
  ),
84
84
  // TODO: should content be inline?
85
85
  contentId: v.id("content"),
@@ -16,7 +16,7 @@ describe("search", () => {
16
16
  t: ConvexTest,
17
17
  namespace = "test-namespace",
18
18
  dimension = 128,
19
- filterNames: string[] = []
19
+ filterNames: string[] = [],
20
20
  ) {
21
21
  return await t.run(async (ctx) => {
22
22
  return ctx.db.insert("namespaces", {
@@ -35,7 +35,7 @@ describe("search", () => {
35
35
  namespaceId: Id<"namespaces">,
36
36
  key = "test-entry",
37
37
  version = 0,
38
- filterValues: Array<{ name: string; value: Value }> = []
38
+ filterValues: Array<{ name: string; value: Value }> = [],
39
39
  ) {
40
40
  return await t.run(async (ctx) => {
41
41
  return ctx.db.insert("entries", {
@@ -207,7 +207,7 @@ describe("search", () => {
207
207
 
208
208
  // With threshold should return fewer results
209
209
  expect(resultWithThreshold.results.length).toBeLessThan(
210
- resultWithoutThreshold.results.length
210
+ resultWithoutThreshold.results.length,
211
211
  );
212
212
  expect(resultWithoutThreshold.results).toHaveLength(2);
213
213
 
@@ -305,7 +305,7 @@ describe("search", () => {
305
305
  t,
306
306
  "multi-filter-namespace",
307
307
  128,
308
- ["category", "priority_category"]
308
+ ["category", "priority_category"],
309
309
  );
310
310
 
311
311
  // Create entries with different filter combinations
@@ -438,7 +438,7 @@ describe("search", () => {
438
438
  // Results should be sorted by score (best first)
439
439
  for (let i = 1; i < result.results.length; i++) {
440
440
  expect(result.results[i - 1].score).toBeGreaterThanOrEqual(
441
- result.results[i].score
441
+ result.results[i].score,
442
442
  );
443
443
  }
444
444
  });
@@ -5,7 +5,6 @@ import { numberedFiltersFromNamedFilters, vNamedFilter } from "./filters.js";
5
5
  import { internal } from "./_generated/api.js";
6
6
  import {
7
7
  vEntry,
8
- type Entry,
9
8
  vSearchResult,
10
9
  type SearchResult,
11
10
  type EntryId,
@@ -22,7 +21,7 @@ export const search = action({
22
21
  limit: v.number(),
23
22
  vectorScoreThreshold: v.optional(v.number()),
24
23
  chunkContext: v.optional(
25
- v.object({ before: v.number(), after: v.number() })
24
+ v.object({ before: v.number(), after: v.number() }),
26
25
  ),
27
26
  },
28
27
  returns: v.object({
@@ -31,10 +30,10 @@ export const search = action({
31
30
  }),
32
31
  handler: async (
33
32
  ctx,
34
- args
33
+ args,
35
34
  ): Promise<{
36
35
  results: SearchResult[];
37
- entries: Entry[];
36
+ entries: Infer<typeof vEntry>[];
38
37
  }> => {
39
38
  const { modelId, embedding, filters, limit } = args;
40
39
  const namespace = await ctx.runQuery(
@@ -44,11 +43,11 @@ export const search = action({
44
43
  modelId,
45
44
  dimension: embedding.length,
46
45
  filterNames: filters.map((f) => f.name),
47
- }
46
+ },
48
47
  );
49
48
  if (!namespace) {
50
49
  console.debug(
51
- `No compatible namespace found for ${args.namespace} with model ${args.modelId} and dimension ${embedding.length} and filters ${filters.map((f) => f.name).join(", ")}.`
50
+ `No compatible namespace found for ${args.namespace} with model ${args.modelId} and dimension ${embedding.length} and filters ${filters.map((f) => f.name).join(", ")}.`,
52
51
  );
53
52
  return {
54
53
  results: [],
@@ -71,20 +70,20 @@ export const search = action({
71
70
  {
72
71
  embeddingIds: aboveThreshold.map((r) => r._id),
73
72
  chunkContext,
74
- }
73
+ },
75
74
  );
76
75
  return {
77
76
  results: ranges
78
77
  .map((r, i) => publicSearchResult(r, aboveThreshold[i]._score))
79
78
  .filter((r) => r !== null),
80
- entries,
79
+ entries: entries as Infer<typeof vEntry>[],
81
80
  };
82
81
  },
83
82
  });
84
83
 
85
84
  function publicSearchResult(
86
85
  r: Infer<typeof vRangeResult> | null,
87
- score: number
86
+ score: number,
88
87
  ): SearchResult | null {
89
88
  if (r === null) {
90
89
  return null;
@@ -3,17 +3,11 @@ import { test } from "vitest";
3
3
  import { convexTest } from "convex-test";
4
4
  import schema from "./schema.js";
5
5
  export const modules = import.meta.glob("./**/*.*s");
6
-
7
- // Sorry about everything
8
- import componentSchema from "../../node_modules/@convex-dev/workpool/src/component/schema.js";
9
- export { componentSchema };
10
- export const componentModules = import.meta.glob(
11
- "../../node_modules/@convex-dev/workpool/src/component/**/*.ts"
12
- );
6
+ import workpool from "@convex-dev/workpool/test";
13
7
 
14
8
  export function initConvexTest() {
15
9
  const t = convexTest(schema, modules);
16
- t.registerComponent("workpool", componentSchema, componentModules);
10
+ t.registerComponent("workpool", workpool.schema, workpool.modules);
17
11
  return t;
18
12
  }
19
13