@mastra/libsql 0.10.4-alpha.0 → 0.10.4-alpha.2

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.
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
+ import type { LibSQLVectorFilter } from './filter';
3
4
  import { LibSQLFilterTranslator } from './filter';
4
5
 
5
6
  describe('LibSQLFilterTranslator', () => {
@@ -17,14 +18,8 @@ describe('LibSQLFilterTranslator', () => {
17
18
  });
18
19
  });
19
20
 
20
- it('translates array to $in', () => {
21
- expect(translator.translate({ field: ['a', 'b'] })).toEqual({
22
- field: { $in: ['a', 'b'] },
23
- });
24
- });
25
-
26
21
  it('preserves comparison operators', () => {
27
- const filter = {
22
+ const filter: LibSQLVectorFilter = {
28
23
  field1: { $eq: 'value' },
29
24
  field2: { $ne: 'value' },
30
25
  field3: { $gt: 5 },
@@ -55,7 +50,7 @@ describe('LibSQLFilterTranslator', () => {
55
50
  nested: {
56
51
  field: 'value',
57
52
  },
58
- }),
53
+ } as any),
59
54
  ).toEqual({
60
55
  'nested.field': { $eq: 'value' },
61
56
  });
@@ -65,7 +60,8 @@ describe('LibSQLFilterTranslator', () => {
65
60
  // Array Operations
66
61
  describe('array operations', () => {
67
62
  it('translates array to $in', () => {
68
- expect(translator.translate({ field: ['a', 'b'] })).toEqual({
63
+ const filter: LibSQLVectorFilter = { field: ['a', 'b'] };
64
+ expect(translator.translate(filter)).toEqual({
69
65
  field: { $in: ['a', 'b'] },
70
66
  });
71
67
  });
@@ -82,7 +78,7 @@ describe('LibSQLFilterTranslator', () => {
82
78
  it('handles empty arrays', () => {
83
79
  expect(
84
80
  translator.translate({
85
- field: [],
81
+ field: [] as any,
86
82
  }),
87
83
  ).toEqual({
88
84
  field: { $in: [] },
@@ -128,7 +124,7 @@ describe('LibSQLFilterTranslator', () => {
128
124
  });
129
125
 
130
126
  // Array Operator Normalization
131
- describe('array operator normalization', () => {
127
+ describe('Array operator normalization', () => {
132
128
  it('normalizes single values for $all', () => {
133
129
  expect(
134
130
  translator.translate({
@@ -173,7 +169,7 @@ describe('LibSQLFilterTranslator', () => {
173
169
  // Logical Operators
174
170
  describe('Logical Operators', () => {
175
171
  it('handles logical operators', () => {
176
- const filter = {
172
+ const filter: LibSQLVectorFilter = {
177
173
  $and: [{ field1: { $eq: 'value1' } }, { field2: { $eq: 'value2' } }],
178
174
  $or: [{ field3: { $eq: 'value3' } }, { field4: { $eq: 'value4' } }],
179
175
  };
@@ -457,16 +453,6 @@ describe('LibSQLFilterTranslator', () => {
457
453
  field: { $eq: '' },
458
454
  });
459
455
  });
460
-
461
- it('handles empty arrays', () => {
462
- expect(
463
- translator.translate({
464
- field: [],
465
- }),
466
- ).toEqual({
467
- field: { $in: [] },
468
- });
469
- });
470
456
  });
471
457
 
472
458
  // Complex Filter Structures
@@ -540,53 +526,10 @@ describe('LibSQLFilterTranslator', () => {
540
526
  });
541
527
  });
542
528
 
543
- // Array Operator Normalization
544
- describe('Array Operator Normalization', () => {
545
- it('normalizes single values for $all', () => {
546
- expect(
547
- translator.translate({
548
- field: { $all: 'value' },
549
- }),
550
- ).toEqual({
551
- field: { $all: ['value'] },
552
- });
553
- });
554
-
555
- it('normalizes single values for $in', () => {
556
- expect(
557
- translator.translate({
558
- field: { $in: 'value' },
559
- }),
560
- ).toEqual({
561
- field: { $in: ['value'] },
562
- });
563
- });
564
-
565
- it('normalizes single values for $nin', () => {
566
- expect(
567
- translator.translate({
568
- field: { $nin: 'value' },
569
- }),
570
- ).toEqual({
571
- field: { $nin: ['value'] },
572
- });
573
- });
574
-
575
- it('preserves arrays for array operators', () => {
576
- expect(
577
- translator.translate({
578
- field: { $all: ['value1', 'value2'] },
579
- }),
580
- ).toEqual({
581
- field: { $all: ['value1', 'value2'] },
582
- });
583
- });
584
- });
585
-
586
529
  // Operator Support Validation
587
530
  describe('Operator Support Validation', () => {
588
531
  it('ensure all operator filters are supported', () => {
589
- const supportedFilters = [
532
+ const supportedFilters: LibSQLVectorFilter[] = [
590
533
  // Basic comparison operators
591
534
  { field: { $eq: 'value' } },
592
535
  { field: { $ne: 'value' } },
@@ -612,12 +555,7 @@ describe('LibSQLFilterTranslator', () => {
612
555
  { $or: [{ field1: 'value1' }, { field2: 'value2' }] },
613
556
  { $nor: [{ field1: 'value1' }, { field2: 'value2' }] },
614
557
 
615
- { $and: { field: 'value' } },
616
- { $or: { field: 'value' } },
617
- { $nor: { field: 'value' } },
618
- { $not: { field: 'value' } },
619
-
620
- { $or: [{ $and: { field1: 'value1' } }, { $not: { field2: 'value2' } }] },
558
+ { $or: [{ $and: [{ field1: 'value1' }] }, { $not: { field2: 'value2' } }] },
621
559
 
622
560
  { field: { $not: { $eq: 'value' } } },
623
561
  { field: { $not: { $in: ['value1', 'value2'] } } },
@@ -634,7 +572,7 @@ describe('LibSQLFilterTranslator', () => {
634
572
 
635
573
  it('throws error for $not if not an object', () => {
636
574
  expect(() => translator.translate({ $not: 'value' })).toThrow();
637
- expect(() => translator.translate({ $not: [{ field: 'value' }] })).toThrow();
575
+ expect(() => translator.translate({ $not: [{ field: 'value' }] } as any)).toThrow();
638
576
  });
639
577
  it('throws error for $not if empty', () => {
640
578
  expect(() => translator.translate({ $not: {} })).toThrow();
@@ -646,21 +584,21 @@ describe('LibSQLFilterTranslator', () => {
646
584
  expect(() =>
647
585
  translator.translate({
648
586
  field: { $and: [{ $eq: 'value1' }, { $eq: 'value2' }] },
649
- }),
587
+ } as any),
650
588
  ).toThrow();
651
589
 
652
590
  // $or cannot be used in field conditions
653
591
  expect(() =>
654
592
  translator.translate({
655
593
  field: { $or: [{ $eq: 'value1' }, { $eq: 'value2' }] },
656
- }),
594
+ } as any),
657
595
  ).toThrow();
658
596
 
659
597
  // $nor cannot be used in field conditions
660
598
  expect(() =>
661
599
  translator.translate({
662
600
  field: { $nor: [{ $eq: 'value1' }, { $eq: 'value2' }] },
663
- }),
601
+ } as any),
664
602
  ).toThrow();
665
603
  });
666
604
 
@@ -709,7 +647,7 @@ describe('LibSQLFilterTranslator', () => {
709
647
  field: {
710
648
  $gt: {
711
649
  $or: [{ subfield: 'value1' }, { subfield: 'value2' }],
712
- },
650
+ } as any,
713
651
  },
714
652
  }),
715
653
  ).toThrow();
@@ -723,17 +661,17 @@ describe('LibSQLFilterTranslator', () => {
723
661
  $and: [{ subfield: 'value1' }, { subfield: 'value2' }],
724
662
  },
725
663
  ],
726
- },
664
+ } as any,
727
665
  }),
728
666
  ).toThrow();
729
667
  });
730
668
 
731
669
  it('validates $not operator structure', () => {
732
670
  // $not must be an object
733
- expect(() => translator.translate({ field: { $not: 'value' } })).toThrow();
671
+ expect(() => translator.translate({ field: { $not: 'value' } } as any)).toThrow();
734
672
  expect(() => translator.translate({ field: { $not: ['value'] } })).toThrow();
735
673
  expect(() => translator.translate({ $not: 'value' })).toThrow();
736
- expect(() => translator.translate({ $not: ['value'] })).toThrow();
674
+ expect(() => translator.translate({ $not: ['value'] } as any)).toThrow();
737
675
  });
738
676
 
739
677
  it('validates $not operator nesting', () => {
@@ -793,7 +731,7 @@ describe('LibSQLFilterTranslator', () => {
793
731
  const invalidFilters = [{ $gt: 100 }, { $in: ['value1', 'value2'] }, { $eq: true }];
794
732
 
795
733
  invalidFilters.forEach(filter => {
796
- expect(() => translator.translate(filter)).toThrow(/Invalid top-level operator/);
734
+ expect(() => translator.translate(filter as any)).toThrow(/Invalid top-level operator/);
797
735
  });
798
736
  });
799
737
  it('allows logical operators at top level', () => {
@@ -815,13 +753,13 @@ describe('LibSQLFilterTranslator', () => {
815
753
  // Should throw for non-object values
816
754
  expect(() =>
817
755
  translator.translate({
818
- field: { $elemMatch: 'value' },
756
+ field: { $elemMatch: 'value' } as any,
819
757
  }),
820
758
  ).toThrow('$elemMatch requires an object with conditions');
821
759
 
822
760
  expect(() =>
823
761
  translator.translate({
824
- field: { $elemMatch: ['value'] },
762
+ field: { $elemMatch: ['value'] } as any,
825
763
  }),
826
764
  ).toThrow('$elemMatch requires an object with conditions');
827
765
  });
@@ -962,7 +900,7 @@ describe('LibSQLFilterTranslator', () => {
962
900
  // Unsupported Operations
963
901
  describe('unsupported operators', () => {
964
902
  it('throws on unsupported operators', () => {
965
- expect(() => translator.translate({ field: { $regex: 'value' } })).toThrow();
903
+ expect(() => translator.translate({ field: { $regex: 'value' } } as any)).toThrow();
966
904
  });
967
905
  });
968
906
  });
@@ -1,5 +1,19 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
2
- import type { FieldCondition, VectorFilter, OperatorSupport } from '@mastra/core/vector/filter';
2
+ import type { VectorFilter, OperatorSupport, OperatorValueMap, VectorFieldValue } from '@mastra/core/vector/filter';
3
+
4
+ type LibSQLOperatorValueMap = Omit<
5
+ OperatorValueMap,
6
+ '$regex' | '$options' | '$in' | '$all' | '$nin' | '$eq' | '$ne'
7
+ > & {
8
+ $size: number;
9
+ $contains: VectorFieldValue | Record<string, unknown>;
10
+ $all: VectorFieldValue;
11
+ $in: VectorFieldValue;
12
+ $nin: VectorFieldValue;
13
+ $eq: VectorFieldValue;
14
+ $ne: VectorFieldValue;
15
+ };
16
+ export type LibSQLVectorFilter = VectorFilter<keyof LibSQLOperatorValueMap, LibSQLOperatorValueMap>;
3
17
 
4
18
  /**
5
19
  * Translates MongoDB-style filters to LibSQL compatible filters.
@@ -11,7 +25,7 @@ import type { FieldCondition, VectorFilter, OperatorSupport } from '@mastra/core
11
25
  * - Can take either a single condition or an array of conditions
12
26
  *
13
27
  */
14
- export class LibSQLFilterTranslator extends BaseFilterTranslator {
28
+ export class LibSQLFilterTranslator extends BaseFilterTranslator<LibSQLVectorFilter> {
15
29
  protected override getSupportedOperators(): OperatorSupport {
16
30
  return {
17
31
  ...BaseFilterTranslator.DEFAULT_OPERATORS,
@@ -20,7 +34,7 @@ export class LibSQLFilterTranslator extends BaseFilterTranslator {
20
34
  };
21
35
  }
22
36
 
23
- translate(filter?: VectorFilter): VectorFilter {
37
+ translate(filter?: LibSQLVectorFilter): LibSQLVectorFilter {
24
38
  if (this.isEmpty(filter)) {
25
39
  return filter;
26
40
  }
@@ -28,7 +42,7 @@ export class LibSQLFilterTranslator extends BaseFilterTranslator {
28
42
  return this.translateNode(filter);
29
43
  }
30
44
 
31
- private translateNode(node: VectorFilter | FieldCondition, currentPath: string = ''): any {
45
+ private translateNode(node: LibSQLVectorFilter, currentPath: string = ''): any {
32
46
  if (this.isRegex(node)) {
33
47
  throw new Error('Direct regex pattern format is not supported in LibSQL');
34
48
  }
@@ -74,7 +88,7 @@ export class LibSQLFilterTranslator extends BaseFilterTranslator {
74
88
 
75
89
  if (this.isLogicalOperator(key)) {
76
90
  result[key] = Array.isArray(value)
77
- ? value.map((filter: VectorFilter) => this.translateNode(filter))
91
+ ? value.map((filter: LibSQLVectorFilter) => this.translateNode(filter))
78
92
  : this.translateNode(value);
79
93
  } else if (this.isOperator(key)) {
80
94
  if (this.isArrayOperator(key) && !Array.isArray(value) && key !== '$elemMatch') {
@@ -1130,7 +1130,7 @@ describe('LibSQLVector', () => {
1130
1130
  vectorDB.query({
1131
1131
  indexName,
1132
1132
  queryVector: [1, 0, 0],
1133
- filter: { price: { $invalid: 100 } },
1133
+ filter: { price: { $invalid: 100 } } as any,
1134
1134
  }),
1135
1135
  ).rejects.toThrow('Unsupported operator: $invalid');
1136
1136
  });
@@ -1360,16 +1360,6 @@ describe('LibSQLVector', () => {
1360
1360
  });
1361
1361
  });
1362
1362
 
1363
- it('should throw error for invalid operator', async () => {
1364
- await expect(
1365
- vectorDB.query({
1366
- indexName,
1367
- queryVector: [1, 0, 0],
1368
- filter: { price: { $invalid: 100 } },
1369
- }),
1370
- ).rejects.toThrow('Unsupported operator: $invalid');
1371
- });
1372
-
1373
1363
  it('should handle multiple logical operators at root level', async () => {
1374
1364
  const results = await vectorDB.query({
1375
1365
  indexName,
@@ -1,6 +1,7 @@
1
1
  import { createClient } from '@libsql/client';
2
2
  import type { Client as TursoClient, InValue } from '@libsql/client';
3
3
 
4
+ import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
4
5
  import { parseSqlIdentifier } from '@mastra/core/utils';
5
6
  import { MastraVector } from '@mastra/core/vector';
6
7
  import type {
@@ -14,11 +15,11 @@ import type {
14
15
  DeleteVectorParams,
15
16
  UpdateVectorParams,
16
17
  } from '@mastra/core/vector';
17
- import type { VectorFilter } from '@mastra/core/vector/filter';
18
+ import type { LibSQLVectorFilter } from './filter';
18
19
  import { LibSQLFilterTranslator } from './filter';
19
20
  import { buildFilterQuery } from './sql-builder';
20
21
 
21
- interface LibSQLQueryVectorParams extends QueryVectorParams {
22
+ interface LibSQLQueryVectorParams extends QueryVectorParams<LibSQLVectorFilter> {
22
23
  minScore?: number;
23
24
  }
24
25
 
@@ -40,7 +41,7 @@ export interface LibSQLVectorConfig {
40
41
  initialBackoffMs?: number;
41
42
  }
42
43
 
43
- export class LibSQLVector extends MastraVector {
44
+ export class LibSQLVector extends MastraVector<LibSQLVectorFilter> {
44
45
  private turso: TursoClient;
45
46
  private readonly maxRetries: number;
46
47
  private readonly initialBackoffMs: number;
@@ -108,7 +109,7 @@ export class LibSQLVector extends MastraVector {
108
109
  throw new Error('LibSQLVector: Max retries reached, but no error was re-thrown from the loop.');
109
110
  }
110
111
 
111
- transformFilter(filter?: VectorFilter) {
112
+ transformFilter(filter?: LibSQLVectorFilter) {
112
113
  const translator = new LibSQLFilterTranslator();
113
114
  return translator.translate(filter);
114
115
  }
@@ -128,7 +129,18 @@ export class LibSQLVector extends MastraVector {
128
129
  if (!Array.isArray(queryVector) || !queryVector.every(x => typeof x === 'number' && Number.isFinite(x))) {
129
130
  throw new Error('queryVector must be an array of finite numbers');
130
131
  }
132
+ } catch (error) {
133
+ throw new MastraError(
134
+ {
135
+ id: 'LIBSQL_VECTOR_QUERY_INVALID_ARGS',
136
+ domain: ErrorDomain.STORAGE,
137
+ category: ErrorCategory.USER,
138
+ },
139
+ error,
140
+ );
141
+ }
131
142
 
143
+ try {
132
144
  const parsedIndexName = parseSqlIdentifier(indexName, 'index name');
133
145
 
134
146
  const vectorStr = `[${queryVector.join(',')}]`;
@@ -165,13 +177,31 @@ export class LibSQLVector extends MastraVector {
165
177
  metadata: JSON.parse((metadata as string) ?? '{}'),
166
178
  ...(includeVector && embedding && { vector: JSON.parse(embedding as string) }),
167
179
  }));
168
- } finally {
169
- // client.release()
180
+ } catch (error) {
181
+ throw new MastraError(
182
+ {
183
+ id: 'LIBSQL_VECTOR_QUERY_FAILED',
184
+ domain: ErrorDomain.STORAGE,
185
+ category: ErrorCategory.THIRD_PARTY,
186
+ },
187
+ error,
188
+ );
170
189
  }
171
190
  }
172
191
 
173
192
  public upsert(args: UpsertVectorParams): Promise<string[]> {
174
- return this.executeWriteOperationWithRetry(() => this.doUpsert(args), true);
193
+ try {
194
+ return this.executeWriteOperationWithRetry(() => this.doUpsert(args), true);
195
+ } catch (error) {
196
+ throw new MastraError(
197
+ {
198
+ id: 'LIBSQL_VECTOR_UPSERT_FAILED',
199
+ domain: ErrorDomain.STORAGE,
200
+ category: ErrorCategory.THIRD_PARTY,
201
+ },
202
+ error,
203
+ );
204
+ }
175
205
  }
176
206
 
177
207
  private async doUpsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]> {
@@ -218,7 +248,19 @@ export class LibSQLVector extends MastraVector {
218
248
  }
219
249
 
220
250
  public createIndex(args: CreateIndexParams): Promise<void> {
221
- return this.executeWriteOperationWithRetry(() => this.doCreateIndex(args));
251
+ try {
252
+ return this.executeWriteOperationWithRetry(() => this.doCreateIndex(args));
253
+ } catch (error) {
254
+ throw new MastraError(
255
+ {
256
+ id: 'LIBSQL_VECTOR_CREATE_INDEX_FAILED',
257
+ domain: ErrorDomain.STORAGE,
258
+ category: ErrorCategory.THIRD_PARTY,
259
+ details: { indexName: args.indexName, dimension: args.dimension },
260
+ },
261
+ error,
262
+ );
263
+ }
222
264
  }
223
265
 
224
266
  private async doCreateIndex({ indexName, dimension }: CreateIndexParams): Promise<void> {
@@ -247,7 +289,19 @@ export class LibSQLVector extends MastraVector {
247
289
  }
248
290
 
249
291
  public deleteIndex(args: DeleteIndexParams): Promise<void> {
250
- return this.executeWriteOperationWithRetry(() => this.doDeleteIndex(args));
292
+ try {
293
+ return this.executeWriteOperationWithRetry(() => this.doDeleteIndex(args));
294
+ } catch (error) {
295
+ throw new MastraError(
296
+ {
297
+ id: 'LIBSQL_VECTOR_DELETE_INDEX_FAILED',
298
+ domain: ErrorDomain.STORAGE,
299
+ category: ErrorCategory.THIRD_PARTY,
300
+ details: { indexName: args.indexName },
301
+ },
302
+ error,
303
+ );
304
+ }
251
305
  }
252
306
 
253
307
  private async doDeleteIndex({ indexName }: DeleteIndexParams): Promise<void> {
@@ -271,7 +325,14 @@ export class LibSQLVector extends MastraVector {
271
325
  });
272
326
  return result.rows.map(row => row.name as string);
273
327
  } catch (error: any) {
274
- throw new Error(`Failed to list vector tables: ${error.message}`);
328
+ throw new MastraError(
329
+ {
330
+ id: 'LIBSQL_VECTOR_LIST_INDEXES_FAILED',
331
+ domain: ErrorDomain.STORAGE,
332
+ category: ErrorCategory.THIRD_PARTY,
333
+ },
334
+ error,
335
+ );
275
336
  }
276
337
  }
277
338
 
@@ -322,7 +383,15 @@ export class LibSQLVector extends MastraVector {
322
383
  metric,
323
384
  };
324
385
  } catch (e: any) {
325
- throw new Error(`Failed to describe vector table: ${e.message}`);
386
+ throw new MastraError(
387
+ {
388
+ id: 'LIBSQL_VECTOR_DESCRIBE_INDEX_FAILED',
389
+ domain: ErrorDomain.STORAGE,
390
+ category: ErrorCategory.THIRD_PARTY,
391
+ details: { indexName },
392
+ },
393
+ e,
394
+ );
326
395
  }
327
396
  }
328
397
 
@@ -357,7 +426,13 @@ export class LibSQLVector extends MastraVector {
357
426
  }
358
427
 
359
428
  if (updates.length === 0) {
360
- throw new Error('No updates provided');
429
+ throw new MastraError({
430
+ id: 'LIBSQL_VECTOR_UPDATE_VECTOR_INVALID_ARGS',
431
+ domain: ErrorDomain.STORAGE,
432
+ category: ErrorCategory.USER,
433
+ details: { indexName, id },
434
+ text: 'No updates provided',
435
+ });
361
436
  }
362
437
  args.push(id);
363
438
  const query = `
@@ -365,10 +440,23 @@ export class LibSQLVector extends MastraVector {
365
440
  SET ${updates.join(', ')}
366
441
  WHERE vector_id = ?;
367
442
  `;
368
- await this.turso.execute({
369
- sql: query,
370
- args,
371
- });
443
+
444
+ try {
445
+ await this.turso.execute({
446
+ sql: query,
447
+ args,
448
+ });
449
+ } catch (error) {
450
+ throw new MastraError(
451
+ {
452
+ id: 'LIBSQL_VECTOR_UPDATE_VECTOR_FAILED',
453
+ domain: ErrorDomain.STORAGE,
454
+ category: ErrorCategory.THIRD_PARTY,
455
+ details: { indexName, id },
456
+ },
457
+ error,
458
+ );
459
+ }
372
460
  }
373
461
 
374
462
  /**
@@ -379,7 +467,19 @@ export class LibSQLVector extends MastraVector {
379
467
  * @throws Will throw an error if the deletion operation fails.
380
468
  */
381
469
  public deleteVector(args: DeleteVectorParams): Promise<void> {
382
- return this.executeWriteOperationWithRetry(() => this.doDeleteVector(args));
470
+ try {
471
+ return this.executeWriteOperationWithRetry(() => this.doDeleteVector(args));
472
+ } catch (error) {
473
+ throw new MastraError(
474
+ {
475
+ id: 'LIBSQL_VECTOR_DELETE_VECTOR_FAILED',
476
+ domain: ErrorDomain.STORAGE,
477
+ category: ErrorCategory.THIRD_PARTY,
478
+ details: { indexName: args.indexName, id: args.id },
479
+ },
480
+ error,
481
+ );
482
+ }
383
483
  }
384
484
 
385
485
  private async doDeleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {
@@ -391,7 +491,19 @@ export class LibSQLVector extends MastraVector {
391
491
  }
392
492
 
393
493
  public truncateIndex(args: DeleteIndexParams): Promise<void> {
394
- return this.executeWriteOperationWithRetry(() => this._doTruncateIndex(args));
494
+ try {
495
+ return this.executeWriteOperationWithRetry(() => this._doTruncateIndex(args));
496
+ } catch (error) {
497
+ throw new MastraError(
498
+ {
499
+ id: 'LIBSQL_VECTOR_TRUNCATE_INDEX_FAILED',
500
+ domain: ErrorDomain.STORAGE,
501
+ category: ErrorCategory.THIRD_PARTY,
502
+ details: { indexName: args.indexName },
503
+ },
504
+ error,
505
+ );
506
+ }
395
507
  }
396
508
 
397
509
  private async _doTruncateIndex({ indexName }: DeleteIndexParams): Promise<void> {
@@ -6,8 +6,8 @@ import type {
6
6
  ArrayOperator,
7
7
  ElementOperator,
8
8
  LogicalOperator,
9
- VectorFilter,
10
9
  } from '@mastra/core/vector/filter';
10
+ import type { LibSQLVectorFilter } from './filter';
11
11
 
12
12
  type OperatorType =
13
13
  | BasicOperator
@@ -372,7 +372,7 @@ function escapeLikePattern(str: string): string {
372
372
  return str.replace(/([%_\\])/g, '\\$1');
373
373
  }
374
374
 
375
- export function buildFilterQuery(filter: VectorFilter): FilterResult {
375
+ export function buildFilterQuery(filter: LibSQLVectorFilter): FilterResult {
376
376
  if (!filter) {
377
377
  return { sql: '', values: [] };
378
378
  }
@@ -428,11 +428,11 @@ function buildCondition(key: string, value: any, parentPath: string): FilterResu
428
428
 
429
429
  function handleLogicalOperator(
430
430
  key: '$and' | '$or' | '$not' | '$nor',
431
- value: VectorFilter[] | VectorFilter,
431
+ value: LibSQLVectorFilter[] | LibSQLVectorFilter,
432
432
  parentPath: string,
433
433
  ): FilterResult {
434
434
  // Handle empty conditions
435
- if (!value || value.length === 0) {
435
+ if (!value || (Array.isArray(value) && value.length === 0)) {
436
436
  switch (key) {
437
437
  case '$and':
438
438
  case '$nor':
@@ -460,7 +460,7 @@ function handleLogicalOperator(
460
460
  const joinOperator = key === '$or' || key === '$nor' ? 'OR' : 'AND';
461
461
  const conditions = Array.isArray(value)
462
462
  ? value.map(f => {
463
- const entries = Object.entries(f);
463
+ const entries = !!f ? Object.entries(f) : [];
464
464
  return entries.map(([k, v]) => buildCondition(k, v, key));
465
465
  })
466
466
  : [buildCondition(key, value, parentPath)];