@mastra/opensearch 0.10.4-alpha.0 → 0.10.4-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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/opensearch@0.10.4-alpha.0 build /home/runner/work/mastra/mastra/stores/opensearch
2
+ > @mastra/opensearch@0.10.4-alpha.1 build /home/runner/work/mastra/mastra/stores/opensearch
3
3
  > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 9284ms
9
+ TSC ⚡️ Build success in 11957ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/stores/opensearch/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/stores/opensearch/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 10960ms
16
+ DTS ⚡️ Build success in 11764ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 23.60 KB
21
- ESM ⚡️ Build success in 784ms
22
- CJS dist/index.cjs 23.81 KB
23
- CJS ⚡️ Build success in 784ms
20
+ CJS dist/index.cjs 23.79 KB
21
+ CJS ⚡️ Build success in 807ms
22
+ ESM dist/index.js 23.58 KB
23
+ ESM ⚡️ Build success in 814ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @mastra/opensearch
2
2
 
3
+ ## 0.10.4-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 144eb0b: [MASTRA-3669] Metadata Filter Types
8
+ - Updated dependencies [15e9d26]
9
+ - Updated dependencies [07d6d88]
10
+ - Updated dependencies [5d74aab]
11
+ - Updated dependencies [144eb0b]
12
+ - @mastra/core@0.10.7-alpha.2
13
+
3
14
  ## 0.10.4-alpha.0
4
15
 
5
16
  ### Patch Changes
@@ -1,11 +1,14 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
2
+ import type { BlacklistedRootOperators } from '@mastra/core/vector/filter';
2
3
  import type { CreateIndexParams } from '@mastra/core';
3
4
  import type { DeleteIndexParams } from '@mastra/core';
4
5
  import type { DeleteVectorParams } from '@mastra/core';
5
6
  import type { DescribeIndexParams } from '@mastra/core';
6
7
  import type { IndexStats } from '@mastra/core';
8
+ import type { LogicalOperatorValueMap } from '@mastra/core/vector/filter';
7
9
  import { MastraVector } from '@mastra/core/vector';
8
10
  import type { OperatorSupport } from '@mastra/core/vector/filter';
11
+ import type { OperatorValueMap } from '@mastra/core/vector/filter';
9
12
  import type { QueryResult } from '@mastra/core';
10
13
  import type { QueryVectorParams } from '@mastra/core';
11
14
  import type { UpdateVectorParams } from '@mastra/core';
@@ -18,14 +21,16 @@ import type { VectorFilter } from '@mastra/core/vector/filter';
18
21
  */
19
22
  export declare const OPENSEARCH_PROMPT = "When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.\nImportant: Do not explain how to construct the filter\u2014use the specified operators and fields to search the content and return relevant results.\nIf a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.\n\nBasic Comparison Operators:\n- $eq: Exact match (default for field: value)\n Example: { \"category\": \"electronics\" }\n- $ne: Not equal\n Example: { \"category\": { \"$ne\": \"electronics\" } }\n- $gt: Greater than\n Example: { \"price\": { \"$gt\": 100 } }\n- $gte: Greater than or equal\n Example: { \"price\": { \"$gte\": 100 } }\n- $lt: Less than\n Example: { \"price\": { \"$lt\": 100 } }\n- $lte: Less than or equal\n Example: { \"price\": { \"$lte\": 100 } }\n\nArray Operators:\n- $in: Match any value in array\n Example: { \"category\": { \"$in\": [\"electronics\", \"books\"] } }\n- $nin: Does not match any value in array\n Example: { \"category\": { \"$nin\": [\"electronics\", \"books\"] } }\n- $all: Match all values in array\n Example: { \"tags\": { \"$all\": [\"premium\", \"sale\"] } }\n\nLogical Operators:\n- $and: Logical AND (implicit when using multiple conditions)\n Example: { \"$and\": [{ \"price\": { \"$gt\": 100 } }, { \"category\": \"electronics\" }] }\n- $or: Logical OR\n Example: { \"$or\": [{ \"price\": { \"$lt\": 50 } }, { \"category\": \"books\" }] }\n- $not: Logical NOT\n Example: { \"$not\": { \"category\": \"electronics\" } }\n\nElement Operators:\n- $exists: Check if field exists\n Example: { \"rating\": { \"$exists\": true } }\n\nRegex Operator:\n- $regex: Match using a regular expression (ECMAScript syntax)\n Example: { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.\n\nRestrictions:\n- Nested fields are supported using dot notation (e.g., \"address.city\").\n- Multiple conditions on the same field are supported (e.g., { \"price\": { \"$gte\": 100, \"$lte\": 1000 } }).\n- Only logical operators ($and, $or, $not) can be used at the top level.\n- All other operators must be used within a field condition.\n Valid: { \"field\": { \"$gt\": 100 } }\n Valid: { \"$and\": [...] }\n Invalid: { \"$gt\": 100 }\n- Logical operators must contain field conditions, not direct operators.\n Valid: { \"$and\": [{ \"field\": { \"$gt\": 100 } }] }\n Invalid: { \"$and\": [{ \"$gt\": 100 }] }\n- $not operator:\n - Must be an object\n - Cannot be empty\n - Can be used at field level or top level\n - Valid: { \"$not\": { \"field\": \"value\" } }\n - Valid: { \"field\": { \"$not\": { \"$eq\": \"value\" } } }\n- Array operators work on array fields only.\n- Empty arrays in conditions are handled gracefully.\n- Regex queries are case-sensitive by default; use patterns accordingly.\n\nExample Complex Query:\n{\n \"$and\": [\n { \"category\": { \"$in\": [\"electronics\", \"computers\"] } },\n { \"price\": { \"$gte\": 100, \"$lte\": 1000 } },\n { \"tags\": { \"$all\": [\"premium\"] } },\n { \"rating\": { \"$exists\": true, \"$gt\": 4 } },\n { \"$or\": [\n { \"stock\": { \"$gt\": 0 } },\n { \"preorder\": true }\n ]},\n { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n ]\n}";
20
23
 
24
+ declare type OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';
25
+
21
26
  /**
22
27
  * Translator for OpenSearch filter queries.
23
28
  * Maintains OpenSearch-compatible syntax while ensuring proper validation
24
29
  * and normalization of values.
25
30
  */
26
- export declare class OpenSearchFilterTranslator extends BaseFilterTranslator {
31
+ export declare class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {
27
32
  protected getSupportedOperators(): OperatorSupport;
28
- translate(filter?: VectorFilter): VectorFilter;
33
+ translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter;
29
34
  private translateNode;
30
35
  /**
31
36
  * Handles translation of nested objects with dot notation fields
@@ -58,7 +63,11 @@ export declare class OpenSearchFilterTranslator extends BaseFilterTranslator {
58
63
  private createRangeQuery;
59
64
  }
60
65
 
61
- declare class OpenSearchVector extends MastraVector {
66
+ declare type OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
67
+
68
+ declare type OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;
69
+
70
+ declare class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {
62
71
  private client;
63
72
  /**
64
73
  * Creates a new OpenSearchVector client.
@@ -117,7 +126,7 @@ declare class OpenSearchVector extends MastraVector {
117
126
  * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.
118
127
  * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.
119
128
  */
120
- query({ indexName, queryVector, filter, topK, includeVector, }: QueryVectorParams): Promise<QueryResult[]>;
129
+ query({ indexName, queryVector, filter, topK, includeVector, }: OpenSearchVectorParams): Promise<QueryResult[]>;
121
130
  /**
122
131
  * Validates the dimensions of the vectors.
123
132
  *
@@ -129,7 +138,7 @@ declare class OpenSearchVector extends MastraVector {
129
138
  /**
130
139
  * Transforms the filter to the OpenSearch DSL.
131
140
  *
132
- * @param {VectorFilter} filter - The filter to transform.
141
+ * @param {OpenSearchVectorFilter} filter - The filter to transform.
133
142
  * @returns {Record<string, any>} The transformed filter.
134
143
  */
135
144
  private transformFilter;
@@ -156,4 +165,8 @@ declare class OpenSearchVector extends MastraVector {
156
165
  export { OpenSearchVector }
157
166
  export { OpenSearchVector as OpenSearchVector_alias_1 }
158
167
 
168
+ export declare type OpenSearchVectorFilter = VectorFilter<keyof OpenSearchOperatorValueMap, OpenSearchOperatorValueMap, OpenSearchLogicalOperatorValueMap, OpenSearchBlacklisted>;
169
+
170
+ declare type OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;
171
+
159
172
  export { }
@@ -1,11 +1,14 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
2
+ import type { BlacklistedRootOperators } from '@mastra/core/vector/filter';
2
3
  import type { CreateIndexParams } from '@mastra/core';
3
4
  import type { DeleteIndexParams } from '@mastra/core';
4
5
  import type { DeleteVectorParams } from '@mastra/core';
5
6
  import type { DescribeIndexParams } from '@mastra/core';
6
7
  import type { IndexStats } from '@mastra/core';
8
+ import type { LogicalOperatorValueMap } from '@mastra/core/vector/filter';
7
9
  import { MastraVector } from '@mastra/core/vector';
8
10
  import type { OperatorSupport } from '@mastra/core/vector/filter';
11
+ import type { OperatorValueMap } from '@mastra/core/vector/filter';
9
12
  import type { QueryResult } from '@mastra/core';
10
13
  import type { QueryVectorParams } from '@mastra/core';
11
14
  import type { UpdateVectorParams } from '@mastra/core';
@@ -18,14 +21,16 @@ import type { VectorFilter } from '@mastra/core/vector/filter';
18
21
  */
19
22
  export declare const OPENSEARCH_PROMPT = "When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.\nImportant: Do not explain how to construct the filter\u2014use the specified operators and fields to search the content and return relevant results.\nIf a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.\n\nBasic Comparison Operators:\n- $eq: Exact match (default for field: value)\n Example: { \"category\": \"electronics\" }\n- $ne: Not equal\n Example: { \"category\": { \"$ne\": \"electronics\" } }\n- $gt: Greater than\n Example: { \"price\": { \"$gt\": 100 } }\n- $gte: Greater than or equal\n Example: { \"price\": { \"$gte\": 100 } }\n- $lt: Less than\n Example: { \"price\": { \"$lt\": 100 } }\n- $lte: Less than or equal\n Example: { \"price\": { \"$lte\": 100 } }\n\nArray Operators:\n- $in: Match any value in array\n Example: { \"category\": { \"$in\": [\"electronics\", \"books\"] } }\n- $nin: Does not match any value in array\n Example: { \"category\": { \"$nin\": [\"electronics\", \"books\"] } }\n- $all: Match all values in array\n Example: { \"tags\": { \"$all\": [\"premium\", \"sale\"] } }\n\nLogical Operators:\n- $and: Logical AND (implicit when using multiple conditions)\n Example: { \"$and\": [{ \"price\": { \"$gt\": 100 } }, { \"category\": \"electronics\" }] }\n- $or: Logical OR\n Example: { \"$or\": [{ \"price\": { \"$lt\": 50 } }, { \"category\": \"books\" }] }\n- $not: Logical NOT\n Example: { \"$not\": { \"category\": \"electronics\" } }\n\nElement Operators:\n- $exists: Check if field exists\n Example: { \"rating\": { \"$exists\": true } }\n\nRegex Operator:\n- $regex: Match using a regular expression (ECMAScript syntax)\n Example: { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.\n\nRestrictions:\n- Nested fields are supported using dot notation (e.g., \"address.city\").\n- Multiple conditions on the same field are supported (e.g., { \"price\": { \"$gte\": 100, \"$lte\": 1000 } }).\n- Only logical operators ($and, $or, $not) can be used at the top level.\n- All other operators must be used within a field condition.\n Valid: { \"field\": { \"$gt\": 100 } }\n Valid: { \"$and\": [...] }\n Invalid: { \"$gt\": 100 }\n- Logical operators must contain field conditions, not direct operators.\n Valid: { \"$and\": [{ \"field\": { \"$gt\": 100 } }] }\n Invalid: { \"$and\": [{ \"$gt\": 100 }] }\n- $not operator:\n - Must be an object\n - Cannot be empty\n - Can be used at field level or top level\n - Valid: { \"$not\": { \"field\": \"value\" } }\n - Valid: { \"field\": { \"$not\": { \"$eq\": \"value\" } } }\n- Array operators work on array fields only.\n- Empty arrays in conditions are handled gracefully.\n- Regex queries are case-sensitive by default; use patterns accordingly.\n\nExample Complex Query:\n{\n \"$and\": [\n { \"category\": { \"$in\": [\"electronics\", \"computers\"] } },\n { \"price\": { \"$gte\": 100, \"$lte\": 1000 } },\n { \"tags\": { \"$all\": [\"premium\"] } },\n { \"rating\": { \"$exists\": true, \"$gt\": 4 } },\n { \"$or\": [\n { \"stock\": { \"$gt\": 0 } },\n { \"preorder\": true }\n ]},\n { \"name\": { \"$regex\": \"^Sam.*son$\" } }\n ]\n}";
20
23
 
24
+ declare type OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';
25
+
21
26
  /**
22
27
  * Translator for OpenSearch filter queries.
23
28
  * Maintains OpenSearch-compatible syntax while ensuring proper validation
24
29
  * and normalization of values.
25
30
  */
26
- export declare class OpenSearchFilterTranslator extends BaseFilterTranslator {
31
+ export declare class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {
27
32
  protected getSupportedOperators(): OperatorSupport;
28
- translate(filter?: VectorFilter): VectorFilter;
33
+ translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter;
29
34
  private translateNode;
30
35
  /**
31
36
  * Handles translation of nested objects with dot notation fields
@@ -58,7 +63,11 @@ export declare class OpenSearchFilterTranslator extends BaseFilterTranslator {
58
63
  private createRangeQuery;
59
64
  }
60
65
 
61
- declare class OpenSearchVector extends MastraVector {
66
+ declare type OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
67
+
68
+ declare type OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;
69
+
70
+ declare class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {
62
71
  private client;
63
72
  /**
64
73
  * Creates a new OpenSearchVector client.
@@ -117,7 +126,7 @@ declare class OpenSearchVector extends MastraVector {
117
126
  * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.
118
127
  * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.
119
128
  */
120
- query({ indexName, queryVector, filter, topK, includeVector, }: QueryVectorParams): Promise<QueryResult[]>;
129
+ query({ indexName, queryVector, filter, topK, includeVector, }: OpenSearchVectorParams): Promise<QueryResult[]>;
121
130
  /**
122
131
  * Validates the dimensions of the vectors.
123
132
  *
@@ -129,7 +138,7 @@ declare class OpenSearchVector extends MastraVector {
129
138
  /**
130
139
  * Transforms the filter to the OpenSearch DSL.
131
140
  *
132
- * @param {VectorFilter} filter - The filter to transform.
141
+ * @param {OpenSearchVectorFilter} filter - The filter to transform.
133
142
  * @returns {Record<string, any>} The transformed filter.
134
143
  */
135
144
  private transformFilter;
@@ -156,4 +165,8 @@ declare class OpenSearchVector extends MastraVector {
156
165
  export { OpenSearchVector }
157
166
  export { OpenSearchVector as OpenSearchVector_alias_1 }
158
167
 
168
+ export declare type OpenSearchVectorFilter = VectorFilter<keyof OpenSearchOperatorValueMap, OpenSearchOperatorValueMap, OpenSearchLogicalOperatorValueMap, OpenSearchBlacklisted>;
169
+
170
+ declare type OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;
171
+
159
172
  export { }
package/dist/index.cjs CHANGED
@@ -12,7 +12,6 @@ var OpenSearchFilterTranslator = class extends filter.BaseFilterTranslator {
12
12
  ...filter.BaseFilterTranslator.DEFAULT_OPERATORS,
13
13
  logical: ["$and", "$or", "$not"],
14
14
  array: ["$in", "$nin", "$all"],
15
- element: ["$exists"],
16
15
  regex: ["$regex"],
17
16
  custom: []
18
17
  };
@@ -608,7 +607,7 @@ var OpenSearchVector = class extends vector.MastraVector {
608
607
  /**
609
608
  * Transforms the filter to the OpenSearch DSL.
610
609
  *
611
- * @param {VectorFilter} filter - The filter to transform.
610
+ * @param {OpenSearchVectorFilter} filter - The filter to transform.
612
611
  * @returns {Record<string, any>} The transformed filter.
613
612
  */
614
613
  transformFilter(filter) {
package/dist/index.js CHANGED
@@ -10,7 +10,6 @@ var OpenSearchFilterTranslator = class extends BaseFilterTranslator {
10
10
  ...BaseFilterTranslator.DEFAULT_OPERATORS,
11
11
  logical: ["$and", "$or", "$not"],
12
12
  array: ["$in", "$nin", "$all"],
13
- element: ["$exists"],
14
13
  regex: ["$regex"],
15
14
  custom: []
16
15
  };
@@ -606,7 +605,7 @@ var OpenSearchVector = class extends MastraVector {
606
605
  /**
607
606
  * Transforms the filter to the OpenSearch DSL.
608
607
  *
609
- * @param {VectorFilter} filter - The filter to transform.
608
+ * @param {OpenSearchVectorFilter} filter - The filter to transform.
610
609
  * @returns {Record<string, any>} The transformed filter.
611
610
  */
612
611
  transformFilter(filter) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/opensearch",
3
- "version": "0.10.4-alpha.0",
3
+ "version": "0.10.4-alpha.1",
4
4
  "description": "OpenSearch vector store provider for Mastra",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,12 +24,12 @@
24
24
  "devDependencies": {
25
25
  "@microsoft/api-extractor": "^7.52.8",
26
26
  "@types/node": "^20.19.0",
27
- "eslint": "^9.28.0",
27
+ "eslint": "^9.29.0",
28
28
  "tsup": "^8.5.0",
29
29
  "typescript": "^5.8.3",
30
30
  "vitest": "^3.2.3",
31
31
  "@internal/lint": "0.0.13",
32
- "@mastra/core": "0.10.7-alpha.1"
32
+ "@mastra/core": "0.10.7-alpha.2"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@mastra/core": ">=0.10.4-0 <0.11.0"
@@ -1,5 +1,6 @@
1
1
  import { beforeEach, describe, expect, it } from 'vitest';
2
2
 
3
+ import type { OpenSearchVectorFilter } from './filter';
3
4
  import { OpenSearchFilterTranslator } from './filter';
4
5
 
5
6
  describe('OpenSearchFilterTranslator', () => {
@@ -13,19 +14,19 @@ describe('OpenSearchFilterTranslator', () => {
13
14
  describe('basic operations', () => {
14
15
  it('handles empty filters', () => {
15
16
  expect(translator.translate({})).toEqual(undefined);
16
- expect(translator.translate(null as any)).toEqual(undefined);
17
- expect(translator.translate(undefined as any)).toEqual(undefined);
17
+ expect(translator.translate(null)).toEqual(undefined);
18
+ expect(translator.translate(undefined)).toEqual(undefined);
18
19
  });
19
20
 
20
21
  it('translates simple field equality to term query', () => {
21
- const filter = { field: 'value' };
22
+ const filter: OpenSearchVectorFilter = { field: 'value' };
22
23
  expect(translator.translate(filter)).toEqual({
23
24
  term: { 'metadata.field.keyword': 'value' },
24
25
  });
25
26
  });
26
27
 
27
28
  it('translates multiple top-level fields to bool must', () => {
28
- const filter = { field1: 'value1', field2: 'value2' };
29
+ const filter: OpenSearchVectorFilter = { field1: 'value1', field2: 'value2' };
29
30
  expect(translator.translate(filter)).toEqual({
30
31
  bool: {
31
32
  must: [{ term: { 'metadata.field1.keyword': 'value1' } }, { term: { 'metadata.field2.keyword': 'value2' } }],
@@ -62,14 +63,14 @@ describe('OpenSearchFilterTranslator', () => {
62
63
  // Comparison Operators
63
64
  describe('comparison operators', () => {
64
65
  it('translates $eq operator', () => {
65
- const filter = { field: { $eq: 'value' } };
66
+ const filter: OpenSearchVectorFilter = { field: { $eq: 'value' } };
66
67
  expect(translator.translate(filter)).toEqual({
67
68
  term: { 'metadata.field.keyword': 'value' },
68
69
  });
69
70
  });
70
71
 
71
72
  it('translates $ne operator', () => {
72
- const filter = { field: { $ne: 'value' } };
73
+ const filter: OpenSearchVectorFilter = { field: { $ne: 'value' } };
73
74
  expect(translator.translate(filter)).toEqual({
74
75
  bool: {
75
76
  must_not: [{ term: { 'metadata.field.keyword': 'value' } }],
@@ -79,7 +80,7 @@ describe('OpenSearchFilterTranslator', () => {
79
80
 
80
81
  it('handles date values', () => {
81
82
  const date = new Date('2024-01-01');
82
- const filter = { timestamp: { $gt: date } };
83
+ const filter: OpenSearchVectorFilter = { timestamp: { $gt: date } };
83
84
  expect(translator.translate(filter)).toEqual({
84
85
  range: { 'metadata.timestamp': { gt: date.toISOString() } },
85
86
  });
@@ -89,7 +90,7 @@ describe('OpenSearchFilterTranslator', () => {
89
90
  // Logical Operators
90
91
  describe('logical operators', () => {
91
92
  it('translates $and operator', () => {
92
- const filter = {
93
+ const filter: OpenSearchVectorFilter = {
93
94
  $and: [{ field1: 'value1' }, { field2: 'value2' }],
94
95
  };
95
96
  expect(translator.translate(filter)).toEqual({
@@ -100,7 +101,7 @@ describe('OpenSearchFilterTranslator', () => {
100
101
  });
101
102
 
102
103
  it('translates $or operator', () => {
103
- const filter = {
104
+ const filter: OpenSearchVectorFilter = {
104
105
  $or: [{ field1: 'value1' }, { field2: 'value2' }],
105
106
  };
106
107
  expect(translator.translate(filter)).toEqual({
@@ -114,7 +115,7 @@ describe('OpenSearchFilterTranslator', () => {
114
115
  });
115
116
 
116
117
  it('translates $not operator', () => {
117
- const filter = {
118
+ const filter: OpenSearchVectorFilter = {
118
119
  $not: { field: 'value' },
119
120
  };
120
121
  expect(translator.translate(filter)).toEqual({
@@ -125,7 +126,7 @@ describe('OpenSearchFilterTranslator', () => {
125
126
  });
126
127
 
127
128
  it('translates $not with $eq operator', () => {
128
- const filter = { field: { $not: { $eq: 'value' } } };
129
+ const filter: OpenSearchVectorFilter = { field: { $not: { $eq: 'value' } } };
129
130
  expect(translator.translate(filter)).toEqual({
130
131
  bool: {
131
132
  must_not: [{ term: { 'metadata.field.keyword': 'value' } }],
@@ -134,7 +135,7 @@ describe('OpenSearchFilterTranslator', () => {
134
135
  });
135
136
 
136
137
  it('translates $not with $ne operator', () => {
137
- const filter = { field: { $not: { $ne: 'value' } } };
138
+ const filter: OpenSearchVectorFilter = { field: { $not: { $ne: 'value' } } };
138
139
  expect(translator.translate(filter)).toEqual({
139
140
  bool: {
140
141
  must_not: [
@@ -149,14 +150,14 @@ describe('OpenSearchFilterTranslator', () => {
149
150
  });
150
151
 
151
152
  it('translates $not with $eq null', () => {
152
- const filter = { field: { $not: { $eq: null } } };
153
+ const filter: OpenSearchVectorFilter = { field: { $not: { $eq: null } } };
153
154
  expect(translator.translate(filter)).toEqual({
154
155
  exists: { field: 'metadata.field' },
155
156
  });
156
157
  });
157
158
 
158
159
  it('translates $not with $ne null', () => {
159
- const filter = { field: { $not: { $ne: null } } };
160
+ const filter: OpenSearchVectorFilter = { field: { $not: { $ne: null } } };
160
161
  expect(translator.translate(filter)).toEqual({
161
162
  bool: {
162
163
  must_not: [{ exists: { field: 'metadata.field' } }],
@@ -165,7 +166,7 @@ describe('OpenSearchFilterTranslator', () => {
165
166
  });
166
167
 
167
168
  it('translates $not with nested fields', () => {
168
- const filter = { 'user.profile.age': { $not: { $gt: 25 } } };
169
+ const filter: OpenSearchVectorFilter = { 'user.profile.age': { $not: { $gt: 25 } } };
169
170
  expect(translator.translate(filter)).toEqual({
170
171
  bool: {
171
172
  must_not: [
@@ -178,7 +179,7 @@ describe('OpenSearchFilterTranslator', () => {
178
179
  });
179
180
 
180
181
  it('translates $not with multiple operators', () => {
181
- const filter = { price: { $not: { $gte: 30, $lte: 70 } } };
182
+ const filter: OpenSearchVectorFilter = { price: { $not: { $gte: 30, $lte: 70 } } };
182
183
  expect(translator.translate(filter)).toEqual({
183
184
  bool: {
184
185
  must_not: [
@@ -191,7 +192,7 @@ describe('OpenSearchFilterTranslator', () => {
191
192
  });
192
193
 
193
194
  it('handles empty $and array', () => {
194
- const filter = {
195
+ const filter: OpenSearchVectorFilter = {
195
196
  $and: [],
196
197
  };
197
198
  // Empty $and should match everything
@@ -199,7 +200,7 @@ describe('OpenSearchFilterTranslator', () => {
199
200
  });
200
201
 
201
202
  it('handles empty $or array', () => {
202
- const filter = {
203
+ const filter: OpenSearchVectorFilter = {
203
204
  $or: [],
204
205
  };
205
206
  // Empty $or should match nothing
@@ -218,7 +219,7 @@ describe('OpenSearchFilterTranslator', () => {
218
219
  });
219
220
 
220
221
  it('handles $not with comparison operators', () => {
221
- const filter = {
222
+ const filter: OpenSearchVectorFilter = {
222
223
  price: { $not: { $gt: 100 } },
223
224
  };
224
225
  expect(translator.translate(filter)).toEqual({
@@ -229,7 +230,7 @@ describe('OpenSearchFilterTranslator', () => {
229
230
  });
230
231
 
231
232
  it('handles nested $not with $or', () => {
232
- const filter = {
233
+ const filter: OpenSearchVectorFilter = {
233
234
  $not: { $or: [{ category: 'electronics' }, { category: 'books' }] },
234
235
  };
235
236
  expect(translator.translate(filter)).toEqual({
@@ -249,7 +250,7 @@ describe('OpenSearchFilterTranslator', () => {
249
250
  });
250
251
 
251
252
  it('handles $not with $not operator', () => {
252
- const filter = {
253
+ const filter: OpenSearchVectorFilter = {
253
254
  $not: { $not: { category: 'electronics' } },
254
255
  };
255
256
  expect(translator.translate(filter)).toEqual({
@@ -266,7 +267,7 @@ describe('OpenSearchFilterTranslator', () => {
266
267
  });
267
268
 
268
269
  it('handles nested logical operators', () => {
269
- const filter = {
270
+ const filter: OpenSearchVectorFilter = {
270
271
  $and: [
271
272
  { field1: 'value1' },
272
273
  {
@@ -295,14 +296,14 @@ describe('OpenSearchFilterTranslator', () => {
295
296
  // Array Operators
296
297
  describe('array operators', () => {
297
298
  it('translates $in operator', () => {
298
- const filter = { field: { $in: ['value1', 'value2'] } };
299
+ const filter: OpenSearchVectorFilter = { field: { $in: ['value1', 'value2'] } };
299
300
  expect(translator.translate(filter)).toEqual({
300
301
  terms: { 'metadata.field.keyword': ['value1', 'value2'] },
301
302
  });
302
303
  });
303
304
 
304
305
  it('translates $nin operator', () => {
305
- const filter = { field: { $nin: ['value1', 'value2'] } };
306
+ const filter: OpenSearchVectorFilter = { field: { $nin: ['value1', 'value2'] } };
306
307
  expect(translator.translate(filter)).toEqual({
307
308
  bool: {
308
309
  must_not: [{ terms: { 'metadata.field.keyword': ['value1', 'value2'] } }],
@@ -311,7 +312,7 @@ describe('OpenSearchFilterTranslator', () => {
311
312
  });
312
313
 
313
314
  it('translates $all operator', () => {
314
- const filter = { field: { $all: ['value1', 'value2'] } };
315
+ const filter: OpenSearchVectorFilter = { field: { $all: ['value1', 'value2'] } };
315
316
  expect(translator.translate(filter)).toEqual({
316
317
  bool: {
317
318
  must: [{ term: { 'metadata.field.keyword': 'value1' } }, { term: { 'metadata.field.keyword': 'value2' } }],
@@ -320,7 +321,7 @@ describe('OpenSearchFilterTranslator', () => {
320
321
  });
321
322
 
322
323
  it('handles empty $in array', () => {
323
- const filter = { field: { $in: [] } };
324
+ const filter: OpenSearchVectorFilter = { field: { $in: [] } };
324
325
  // Empty $in should match nothing (empty terms)
325
326
  expect(translator.translate(filter)).toEqual({
326
327
  terms: { 'metadata.field.keyword': [] },
@@ -328,7 +329,7 @@ describe('OpenSearchFilterTranslator', () => {
328
329
  });
329
330
 
330
331
  it('handles empty $nin array', () => {
331
- const filter = { field: { $nin: [] } };
332
+ const filter: OpenSearchVectorFilter = { field: { $nin: [] } };
332
333
  // Empty $nin should match everything
333
334
  expect(translator.translate(filter)).toEqual({
334
335
  match_all: {},
@@ -336,7 +337,7 @@ describe('OpenSearchFilterTranslator', () => {
336
337
  });
337
338
 
338
339
  it('handles empty $all array', () => {
339
- const filter = { field: { $all: [] } };
340
+ const filter: OpenSearchVectorFilter = { field: { $all: [] } };
340
341
  // Empty $all should match nothing
341
342
  expect(translator.translate(filter)).toEqual({
342
343
  bool: {
@@ -346,7 +347,7 @@ describe('OpenSearchFilterTranslator', () => {
346
347
  });
347
348
 
348
349
  it('handles $not with array operators', () => {
349
- const filter = { tags: { $not: { $in: ['premium', 'new'] } } };
350
+ const filter: OpenSearchVectorFilter = { tags: { $not: { $in: ['premium', 'new'] } } };
350
351
  expect(translator.translate(filter)).toEqual({
351
352
  bool: {
352
353
  must_not: [
@@ -359,7 +360,7 @@ describe('OpenSearchFilterTranslator', () => {
359
360
  });
360
361
 
361
362
  it('handles $not with empty array operators', () => {
362
- const filter = { tags: { $not: { $in: [] } } };
363
+ const filter: OpenSearchVectorFilter = { tags: { $not: { $in: [] } } };
363
364
  expect(translator.translate(filter)).toEqual({
364
365
  bool: {
365
366
  must_not: [
@@ -375,14 +376,14 @@ describe('OpenSearchFilterTranslator', () => {
375
376
  // Element Operators
376
377
  describe('element operators', () => {
377
378
  it('translates $exists operator', () => {
378
- const filter = { field: { $exists: true } };
379
+ const filter: OpenSearchVectorFilter = { field: { $exists: true } };
379
380
  expect(translator.translate(filter)).toEqual({
380
381
  exists: { field: 'metadata.field' },
381
382
  });
382
383
  });
383
384
 
384
385
  it('translates $exists operator with false', () => {
385
- const filter = { field: { $exists: false } };
386
+ const filter: OpenSearchVectorFilter = { field: { $exists: false } };
386
387
  expect(translator.translate(filter)).toEqual({
387
388
  bool: {
388
389
  must_not: [{ exists: { field: 'metadata.field' } }],
@@ -394,14 +395,14 @@ describe('OpenSearchFilterTranslator', () => {
394
395
  // Regex Operators
395
396
  describe('regex operators', () => {
396
397
  it('translates $regex operator', () => {
397
- const filter = { field: { $regex: 'pattern' } };
398
+ const filter: OpenSearchVectorFilter = { field: { $regex: 'pattern' } };
398
399
  expect(translator.translate(filter)).toEqual({
399
400
  regexp: { 'metadata.field': 'pattern' },
400
401
  });
401
402
  });
402
403
 
403
404
  it('handles $regex with start anchor', () => {
404
- const filter = { category: { $regex: '^elect' } };
405
+ const filter: OpenSearchVectorFilter = { category: { $regex: '^elect' } };
405
406
  // Should use wildcard for better anchor handling
406
407
  expect(translator.translate(filter)).toEqual({
407
408
  wildcard: { 'metadata.category': 'elect*' },
@@ -409,7 +410,7 @@ describe('OpenSearchFilterTranslator', () => {
409
410
  });
410
411
 
411
412
  it('handles $regex with end anchor', () => {
412
- const filter = { category: { $regex: 'nics$' } };
413
+ const filter: OpenSearchVectorFilter = { category: { $regex: 'nics$' } };
413
414
  // Should use wildcard for better anchor handling
414
415
  expect(translator.translate(filter)).toEqual({
415
416
  wildcard: { 'metadata.category': '*nics' },
@@ -417,7 +418,7 @@ describe('OpenSearchFilterTranslator', () => {
417
418
  });
418
419
 
419
420
  it('handles $regex with both anchors', () => {
420
- const filter = { category: { $regex: '^electronics$' } };
421
+ const filter: OpenSearchVectorFilter = { category: { $regex: '^electronics$' } };
421
422
  // Should use exact match for both anchors
422
423
  expect(translator.translate(filter)).toEqual({
423
424
  wildcard: { 'metadata.category': 'electronics' },
@@ -425,7 +426,7 @@ describe('OpenSearchFilterTranslator', () => {
425
426
  });
426
427
 
427
428
  it('handles $not with $regex operator', () => {
428
- const filter = { category: { $not: { $regex: '^elect' } } };
429
+ const filter: OpenSearchVectorFilter = { category: { $not: { $regex: '^elect' } } };
429
430
  expect(translator.translate(filter)).toEqual({
430
431
  bool: {
431
432
  must_not: [
@@ -441,14 +442,14 @@ describe('OpenSearchFilterTranslator', () => {
441
442
  // Complex Queries
442
443
  describe('complex queries', () => {
443
444
  it('translates numeric operators', () => {
444
- const filter = { price: { $gt: 70, $lte: 100 } };
445
+ const filter: OpenSearchVectorFilter = { price: { $gt: 70, $lte: 100 } };
445
446
  expect(translator.translate(filter)).toEqual({
446
447
  range: { 'metadata.price': { gt: 70, lte: 100 } },
447
448
  });
448
449
  });
449
450
 
450
451
  it('translates multiple range operators on the same field', () => {
451
- const filter = { price: { $gte: 50, $lt: 200 } };
452
+ const filter: OpenSearchVectorFilter = { price: { $gte: 50, $lt: 200 } };
452
453
  expect(translator.translate(filter)).toEqual({
453
454
  range: { 'metadata.price': { gte: 50, lt: 200 } },
454
455
  });
@@ -456,14 +457,14 @@ describe('OpenSearchFilterTranslator', () => {
456
457
 
457
458
  it('translates all four range operators combined', () => {
458
459
  // This is an edge case that would never occur in practice, but tests the implementation
459
- const filter = { value: { $gt: 10, $gte: 20, $lt: 100, $lte: 90 } };
460
+ const filter: OpenSearchVectorFilter = { value: { $gt: 10, $gte: 20, $lt: 100, $lte: 90 } };
460
461
  expect(translator.translate(filter)).toEqual({
461
462
  range: { 'metadata.value': { gt: 10, gte: 20, lt: 100, lte: 90 } },
462
463
  });
463
464
  });
464
465
 
465
466
  it('translates mixed numeric and non-numeric operators', () => {
466
- const filter = { price: { $gt: 50, $exists: true } };
467
+ const filter: OpenSearchVectorFilter = { price: { $gt: 50, $exists: true } };
467
468
  expect(translator.translate(filter)).toEqual({
468
469
  bool: {
469
470
  must: [{ range: { 'metadata.price': { gt: 50 } } }, { exists: { field: 'metadata.price' } }],
@@ -471,7 +472,7 @@ describe('OpenSearchFilterTranslator', () => {
471
472
  });
472
473
  });
473
474
  it('translates mixed operators', () => {
474
- const filter = {
475
+ const filter: OpenSearchVectorFilter = {
475
476
  $and: [{ field1: { $gt: 10 } }, { field2: { $in: ['value1', 'value2'] } }, { field3: { $exists: true } }],
476
477
  };
477
478
  expect(translator.translate(filter)).toEqual({
@@ -486,7 +487,7 @@ describe('OpenSearchFilterTranslator', () => {
486
487
  });
487
488
 
488
489
  it('translates complex nested queries', () => {
489
- const filter = {
490
+ const filter: OpenSearchVectorFilter = {
490
491
  $and: [
491
492
  { status: 'active' },
492
493
  {
@@ -542,7 +543,7 @@ describe('OpenSearchFilterTranslator', () => {
542
543
 
543
544
  it('throws error for invalid array operator values', () => {
544
545
  const filter = { field: { $in: 'not-an-array' } };
545
- expect(() => translator.translate(filter)).toThrow();
546
+ expect(() => translator.translate(filter as any)).toThrow();
546
547
  });
547
548
 
548
549
  it('throws error for nested invalid operators', () => {
@@ -553,7 +554,7 @@ describe('OpenSearchFilterTranslator', () => {
553
554
 
554
555
  describe('special values', () => {
555
556
  it('handles boolean values', () => {
556
- const filter = { active: true, disabled: false };
557
+ const filter: OpenSearchVectorFilter = { active: true, disabled: false };
557
558
  expect(translator.translate(filter)).toEqual({
558
559
  bool: {
559
560
  must: [{ term: { 'metadata.active': true } }, { term: { 'metadata.disabled': false } }],
@@ -562,7 +563,7 @@ describe('OpenSearchFilterTranslator', () => {
562
563
  });
563
564
 
564
565
  it('handles null values', () => {
565
- const filter = { field: null };
566
+ const filter: OpenSearchVectorFilter = { field: null };
566
567
  expect(translator.translate(filter)).toEqual({
567
568
  term: { 'metadata.field': null },
568
569
  });
@@ -571,21 +572,21 @@ describe('OpenSearchFilterTranslator', () => {
571
572
 
572
573
  describe('array handling', () => {
573
574
  it('translates array values to terms query', () => {
574
- const filter = { tags: ['premium', 'new'] };
575
+ const filter: OpenSearchVectorFilter = { tags: ['premium', 'new'] };
575
576
  expect(translator.translate(filter)).toEqual({
576
577
  terms: { 'metadata.tags.keyword': ['premium', 'new'] },
577
578
  });
578
579
  });
579
580
 
580
581
  it('translates numeric array values to terms query', () => {
581
- const filter = { scores: [90, 95, 100] };
582
+ const filter: OpenSearchVectorFilter = { scores: [90, 95, 100] };
582
583
  expect(translator.translate(filter)).toEqual({
583
584
  terms: { 'metadata.scores': [90, 95, 100] },
584
585
  });
585
586
  });
586
587
 
587
588
  it('translates empty array values to empty terms query', () => {
588
- const filter = { tags: [] };
589
+ const filter: OpenSearchVectorFilter = { tags: [] };
589
590
  expect(translator.translate(filter)).toEqual({
590
591
  terms: { 'metadata.tags.keyword': [] },
591
592
  });
@@ -609,35 +610,35 @@ describe('OpenSearchFilterTranslator', () => {
609
610
 
610
611
  describe('field type handling', () => {
611
612
  it('adds .keyword suffix for string fields', () => {
612
- const filter = { field: 'value' };
613
+ const filter: OpenSearchVectorFilter = { field: 'value' };
613
614
  expect(translator.translate(filter)).toEqual({
614
615
  term: { 'metadata.field.keyword': 'value' },
615
616
  });
616
617
  });
617
618
 
618
619
  it('adds .keyword suffix for string array fields', () => {
619
- const filter = { field: { $in: ['value1', 'value2'] } };
620
+ const filter: OpenSearchVectorFilter = { field: { $in: ['value1', 'value2'] } };
620
621
  expect(translator.translate(filter)).toEqual({
621
622
  terms: { 'metadata.field.keyword': ['value1', 'value2'] },
622
623
  });
623
624
  });
624
625
 
625
626
  it('does not add .keyword suffix for numeric fields', () => {
626
- const filter = { field: 123 };
627
+ const filter: OpenSearchVectorFilter = { field: 123 };
627
628
  expect(translator.translate(filter)).toEqual({
628
629
  term: { 'metadata.field': 123 },
629
630
  });
630
631
  });
631
632
 
632
633
  it('does not add .keyword suffix for numeric array fields', () => {
633
- const filter = { field: { $in: [1, 2, 3] } };
634
+ const filter: OpenSearchVectorFilter = { field: { $in: [1, 2, 3] } };
634
635
  expect(translator.translate(filter)).toEqual({
635
636
  terms: { 'metadata.field': [1, 2, 3] },
636
637
  });
637
638
  });
638
639
 
639
640
  it('handles mixed field types in complex queries', () => {
640
- const filter = {
641
+ const filter: OpenSearchVectorFilter = {
641
642
  $and: [
642
643
  { textField: 'value' },
643
644
  { numericField: 123 },
@@ -1,30 +1,48 @@
1
- import type { FieldCondition, OperatorSupport, QueryOperator, VectorFilter } from '@mastra/core/vector/filter';
1
+ import type {
2
+ BlacklistedRootOperators,
3
+ LogicalOperatorValueMap,
4
+ OperatorSupport,
5
+ OperatorValueMap,
6
+ QueryOperator,
7
+ VectorFilter,
8
+ } from '@mastra/core/vector/filter';
2
9
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
3
10
 
11
+ type OpenSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;
12
+
13
+ type OpenSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;
14
+
15
+ type OpenSearchBlacklisted = BlacklistedRootOperators | '$nor';
16
+
17
+ export type OpenSearchVectorFilter = VectorFilter<
18
+ keyof OpenSearchOperatorValueMap,
19
+ OpenSearchOperatorValueMap,
20
+ OpenSearchLogicalOperatorValueMap,
21
+ OpenSearchBlacklisted
22
+ >;
4
23
  /**
5
24
  * Translator for OpenSearch filter queries.
6
25
  * Maintains OpenSearch-compatible syntax while ensuring proper validation
7
26
  * and normalization of values.
8
27
  */
9
- export class OpenSearchFilterTranslator extends BaseFilterTranslator {
28
+ export class OpenSearchFilterTranslator extends BaseFilterTranslator<OpenSearchVectorFilter> {
10
29
  protected override getSupportedOperators(): OperatorSupport {
11
30
  return {
12
31
  ...BaseFilterTranslator.DEFAULT_OPERATORS,
13
32
  logical: ['$and', '$or', '$not'],
14
33
  array: ['$in', '$nin', '$all'],
15
- element: ['$exists'],
16
34
  regex: ['$regex'],
17
35
  custom: [],
18
36
  };
19
37
  }
20
38
 
21
- translate(filter?: VectorFilter): VectorFilter {
39
+ translate(filter?: OpenSearchVectorFilter): OpenSearchVectorFilter {
22
40
  if (this.isEmpty(filter)) return undefined;
23
41
  this.validateFilter(filter);
24
42
  return this.translateNode(filter);
25
43
  }
26
44
 
27
- private translateNode(node: VectorFilter | FieldCondition): any {
45
+ private translateNode(node: OpenSearchVectorFilter): any {
28
46
  // Handle primitive values and arrays
29
47
  if (this.isPrimitive(node) || Array.isArray(node)) {
30
48
  return node;
@@ -1,5 +1,5 @@
1
1
  // To setup a Opensearch server, run the docker compose file in the opensearch directory
2
- import type { QueryResult, QueryVectorParams } from '@mastra/core';
2
+ import type { QueryResult } from '@mastra/core';
3
3
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { OpenSearchVector } from './index';
@@ -215,12 +215,11 @@ describe('OpenSearchVector', () => {
215
215
 
216
216
  await vectorDB.upsert({ indexName: testIndexName, vectors: testVectors, metadata: testMetadata });
217
217
 
218
- const queryParams: QueryVectorParams = {
218
+ const results = await vectorDB.query({
219
219
  indexName: testIndexName,
220
220
  queryVector: [1.0, 0.1, 0.1],
221
221
  topK: 3,
222
- };
223
- const results = await vectorDB.query(queryParams);
222
+ });
224
223
 
225
224
  expect(results).toHaveLength(3);
226
225
  expect(results[0]?.score).toBeGreaterThan(0);
@@ -1197,7 +1196,7 @@ describe('OpenSearchVector', () => {
1197
1196
  vectorDB.query({
1198
1197
  indexName,
1199
1198
  queryVector: [1, 0, 0],
1200
- filter: { price: { $invalid: 100 } },
1199
+ filter: { price: { $invalid: 100 } as any },
1201
1200
  }),
1202
1201
  ).rejects.toThrow('Unsupported operator: $invalid');
1203
1202
  });
@@ -11,9 +11,9 @@ import type {
11
11
  } from '@mastra/core';
12
12
  import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';
13
13
  import { MastraVector } from '@mastra/core/vector';
14
- import type { VectorFilter } from '@mastra/core/vector/filter';
15
14
  import { Client as OpenSearchClient } from '@opensearch-project/opensearch';
16
15
  import { OpenSearchFilterTranslator } from './filter';
16
+ import type { OpenSearchVectorFilter } from './filter';
17
17
 
18
18
  const METRIC_MAPPING = {
19
19
  cosine: 'cosinesimil',
@@ -27,7 +27,9 @@ const REVERSE_METRIC_MAPPING = {
27
27
  innerproduct: 'dotproduct',
28
28
  } as const;
29
29
 
30
- export class OpenSearchVector extends MastraVector {
30
+ type OpenSearchVectorParams = QueryVectorParams<OpenSearchVectorFilter>;
31
+
32
+ export class OpenSearchVector extends MastraVector<OpenSearchVectorFilter> {
31
33
  private client: OpenSearchClient;
32
34
 
33
35
  /**
@@ -243,7 +245,7 @@ export class OpenSearchVector extends MastraVector {
243
245
  filter,
244
246
  topK = 10,
245
247
  includeVector = false,
246
- }: QueryVectorParams): Promise<QueryResult[]> {
248
+ }: OpenSearchVectorParams): Promise<QueryResult[]> {
247
249
  try {
248
250
  const translatedFilter = this.transformFilter(filter);
249
251
 
@@ -300,10 +302,10 @@ export class OpenSearchVector extends MastraVector {
300
302
  /**
301
303
  * Transforms the filter to the OpenSearch DSL.
302
304
  *
303
- * @param {VectorFilter} filter - The filter to transform.
305
+ * @param {OpenSearchVectorFilter} filter - The filter to transform.
304
306
  * @returns {Record<string, any>} The transformed filter.
305
307
  */
306
- private transformFilter(filter?: VectorFilter) {
308
+ private transformFilter(filter?: OpenSearchVectorFilter): any {
307
309
  const translator = new OpenSearchFilterTranslator();
308
310
  return translator.translate(filter);
309
311
  }