@mastra/opensearch 0.0.0-vector-query-sources-20250516172905 → 0.0.0-vector-query-tool-provider-options-20250828222356

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,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/vector';
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
  });
@@ -1,19 +1,19 @@
1
+ import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';
1
2
  import type {
2
3
  CreateIndexParams,
3
4
  DeleteIndexParams,
4
5
  DeleteVectorParams,
5
6
  DescribeIndexParams,
6
7
  IndexStats,
7
- ParamsToArgs,
8
8
  QueryResult,
9
9
  QueryVectorParams,
10
10
  UpdateVectorParams,
11
11
  UpsertVectorParams,
12
- } from '@mastra/core';
12
+ } from '@mastra/core/vector';
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,36 +27,18 @@ 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
- /**
34
- * @deprecated Passing a string URL is deprecated. Use an object parameter: { url }.
35
- * @param url - The OpenSearch node URL (deprecated)
36
- */
37
- constructor(url: string);
38
35
  /**
39
36
  * Creates a new OpenSearchVector client.
40
37
  *
41
- * @param params - An object with a url property specifying the OpenSearch node.
38
+ * @param {string} url - The url of the OpenSearch node.
42
39
  */
43
- constructor(params: { url: string });
44
- constructor(paramsOrUrl: { url: string } | string) {
40
+ constructor({ url }: { url: string }) {
45
41
  super();
46
- let url: string;
47
- if (typeof paramsOrUrl === 'string') {
48
- // Deprecation warning for positional argument
49
- if (typeof console !== 'undefined' && console.warn) {
50
- console.warn(
51
- 'Deprecation Warning: OpenSearchVector constructor positional arguments are deprecated. Please use a single object parameter instead. This signature will be removed on May 20th, 2025.',
52
- );
53
- }
54
- url = paramsOrUrl;
55
- } else if (typeof paramsOrUrl === 'object' && paramsOrUrl !== null && 'url' in paramsOrUrl) {
56
- url = paramsOrUrl.url;
57
- } else {
58
- throw new Error('Invalid parameters for OpenSearchVector constructor. Expected { url: string }.');
59
- }
60
42
  this.client = new OpenSearchClient({ node: url });
61
43
  }
62
44
 
@@ -68,11 +50,15 @@ export class OpenSearchVector extends MastraVector {
68
50
  * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.
69
51
  * @returns {Promise<void>} A promise that resolves when the collection is created.
70
52
  */
71
- async createIndex(params: CreateIndexParams): Promise<void> {
72
- const { indexName, dimension, metric = 'cosine' } = params;
73
-
53
+ async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {
74
54
  if (!Number.isInteger(dimension) || dimension <= 0) {
75
- throw new Error('Dimension must be a positive integer');
55
+ throw new MastraError({
56
+ id: 'STORAGE_OPENSEARCH_VECTOR_CREATE_INDEX_INVALID_ARGS',
57
+ domain: ErrorDomain.STORAGE,
58
+ category: ErrorCategory.USER,
59
+ text: 'Dimension must be a positive integer',
60
+ details: { indexName, dimension },
61
+ });
76
62
  }
77
63
 
78
64
  try {
@@ -105,8 +91,15 @@ export class OpenSearchVector extends MastraVector {
105
91
  await this.validateExistingIndex(indexName, dimension, metric);
106
92
  return;
107
93
  }
108
- console.error(`Failed to create index ${indexName}:`, error);
109
- throw error;
94
+ throw new MastraError(
95
+ {
96
+ id: 'STORAGE_OPENSEARCH_VECTOR_CREATE_INDEX_FAILED',
97
+ domain: ErrorDomain.STORAGE,
98
+ category: ErrorCategory.THIRD_PARTY,
99
+ details: { indexName, dimension, metric },
100
+ },
101
+ error,
102
+ );
110
103
  }
111
104
  }
112
105
 
@@ -123,23 +116,25 @@ export class OpenSearchVector extends MastraVector {
123
116
  .filter((index: string | undefined) => index !== undefined);
124
117
 
125
118
  return indexes;
126
- } catch (error: any) {
127
- console.error('Failed to list indexes:', error);
128
- throw new Error(`Failed to list indexes: ${error.message}`);
119
+ } catch (error) {
120
+ throw new MastraError(
121
+ {
122
+ id: 'STORAGE_OPENSEARCH_VECTOR_LIST_INDEXES_FAILED',
123
+ domain: ErrorDomain.STORAGE,
124
+ category: ErrorCategory.THIRD_PARTY,
125
+ },
126
+ error,
127
+ );
129
128
  }
130
129
  }
131
130
 
132
131
  /**
133
132
  * Retrieves statistics about a vector index.
134
133
  *
135
- * @param params - The parameters for describing an index
136
- * @param params.indexName - The name of the index to describe
134
+ * @param {string} indexName - The name of the index to describe
137
135
  * @returns A promise that resolves to the index statistics including dimension, count and metric
138
136
  */
139
- async describeIndex(...args: ParamsToArgs<DescribeIndexParams>): Promise<IndexStats> {
140
- const params = this.normalizeArgs<DescribeIndexParams>('describeIndex', args);
141
-
142
- const { indexName } = params;
137
+ async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {
143
138
  const { body: indexInfo } = await this.client.indices.get({ index: indexName });
144
139
  const mappings = indexInfo[indexName]?.mappings;
145
140
  const embedding: any = mappings?.properties?.embedding;
@@ -160,14 +155,21 @@ export class OpenSearchVector extends MastraVector {
160
155
  * @param {string} indexName - The name of the index to delete.
161
156
  * @returns {Promise<void>} A promise that resolves when the index is deleted.
162
157
  */
163
- async deleteIndex(...args: ParamsToArgs<DeleteIndexParams>): Promise<void> {
164
- const params = this.normalizeArgs<DeleteIndexParams>('deleteIndex', args);
165
-
166
- const { indexName } = params;
158
+ async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {
167
159
  try {
168
160
  await this.client.indices.delete({ index: indexName });
169
161
  } catch (error) {
170
- console.error(`Failed to delete index ${indexName}:`, error);
162
+ const mastraError = new MastraError(
163
+ {
164
+ id: 'STORAGE_OPENSEARCH_VECTOR_DELETE_INDEX_FAILED',
165
+ domain: ErrorDomain.STORAGE,
166
+ category: ErrorCategory.THIRD_PARTY,
167
+ details: { indexName },
168
+ },
169
+ error,
170
+ );
171
+ this.logger?.error(mastraError.toString());
172
+ this.logger?.trackException(mastraError);
171
173
  }
172
174
  }
173
175
 
@@ -180,45 +182,50 @@ export class OpenSearchVector extends MastraVector {
180
182
  * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.
181
183
  * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.
182
184
  */
183
- async upsert(params: UpsertVectorParams): Promise<string[]> {
184
- const { indexName, vectors, metadata = [], ids } = params;
185
-
185
+ async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {
186
186
  const vectorIds = ids || vectors.map(() => crypto.randomUUID());
187
187
  const operations = [];
188
188
 
189
- // Get index stats to check dimension
190
- const indexInfo = await this.describeIndex({ indexName });
189
+ try {
190
+ // Get index stats to check dimension
191
+ const indexInfo = await this.describeIndex({ indexName });
191
192
 
192
- // Validate vector dimensions
193
- this.validateVectorDimensions(vectors, indexInfo.dimension);
193
+ // Validate vector dimensions
194
+ this.validateVectorDimensions(vectors, indexInfo.dimension);
194
195
 
195
- for (let i = 0; i < vectors.length; i++) {
196
- const operation = {
197
- index: {
198
- _index: indexName,
199
- _id: vectorIds[i],
200
- },
201
- };
196
+ for (let i = 0; i < vectors.length; i++) {
197
+ const operation = {
198
+ index: {
199
+ _index: indexName,
200
+ _id: vectorIds[i],
201
+ },
202
+ };
202
203
 
203
- const document = {
204
- id: vectorIds[i],
205
- embedding: vectors[i],
206
- metadata: metadata[i] || {},
207
- };
204
+ const document = {
205
+ id: vectorIds[i],
206
+ embedding: vectors[i],
207
+ metadata: metadata[i] || {},
208
+ };
208
209
 
209
- operations.push(operation);
210
- operations.push(document);
211
- }
210
+ operations.push(operation);
211
+ operations.push(document);
212
+ }
212
213
 
213
- try {
214
214
  if (operations.length > 0) {
215
215
  await this.client.bulk({ body: operations, refresh: true });
216
216
  }
217
217
 
218
218
  return vectorIds;
219
219
  } catch (error) {
220
- console.error('Failed to upsert vectors:', error);
221
- throw error;
220
+ throw new MastraError(
221
+ {
222
+ id: 'STORAGE_OPENSEARCH_VECTOR_UPSERT_FAILED',
223
+ domain: ErrorDomain.STORAGE,
224
+ category: ErrorCategory.THIRD_PARTY,
225
+ details: { indexName, vectorCount: vectors?.length || 0 },
226
+ },
227
+ error,
228
+ );
222
229
  }
223
230
  }
224
231
 
@@ -232,9 +239,13 @@ export class OpenSearchVector extends MastraVector {
232
239
  * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.
233
240
  * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.
234
241
  */
235
- async query(params: QueryVectorParams): Promise<QueryResult[]> {
236
- const { indexName, queryVector, filter, topK = 10, includeVector = false } = params;
237
-
242
+ async query({
243
+ indexName,
244
+ queryVector,
245
+ filter,
246
+ topK = 10,
247
+ includeVector = false,
248
+ }: OpenSearchVectorParams): Promise<QueryResult[]> {
238
249
  try {
239
250
  const translatedFilter = this.transformFilter(filter);
240
251
 
@@ -262,9 +273,16 @@ export class OpenSearchVector extends MastraVector {
262
273
  });
263
274
 
264
275
  return results;
265
- } catch (error: any) {
266
- console.error('Failed to query vectors:', error);
267
- throw new Error(`Failed to query vectors for index ${indexName}: ${error.message}`);
276
+ } catch (error) {
277
+ throw new MastraError(
278
+ {
279
+ id: 'STORAGE_OPENSEARCH_VECTOR_QUERY_FAILED',
280
+ domain: ErrorDomain.STORAGE,
281
+ category: ErrorCategory.THIRD_PARTY,
282
+ details: { indexName, topK },
283
+ },
284
+ error,
285
+ );
268
286
  }
269
287
  }
270
288
 
@@ -284,39 +302,14 @@ export class OpenSearchVector extends MastraVector {
284
302
  /**
285
303
  * Transforms the filter to the OpenSearch DSL.
286
304
  *
287
- * @param {VectorFilter} filter - The filter to transform.
305
+ * @param {OpenSearchVectorFilter} filter - The filter to transform.
288
306
  * @returns {Record<string, any>} The transformed filter.
289
307
  */
290
- private transformFilter(filter?: VectorFilter) {
308
+ private transformFilter(filter?: OpenSearchVectorFilter): any {
291
309
  const translator = new OpenSearchFilterTranslator();
292
310
  return translator.translate(filter);
293
311
  }
294
312
 
295
- /**
296
- * @deprecated Use {@link updateVector} instead. This method will be removed on May 20th, 2025.
297
- *
298
- * Updates a vector by its ID with the provided vector and/or metadata.
299
- * @param indexName - The name of the index containing the vector.
300
- * @param id - The ID of the vector to update.
301
- * @param update - An object containing the vector and/or metadata to update.
302
- * @param update.vector - An optional array of numbers representing the new vector.
303
- * @param update.metadata - An optional record containing the new metadata.
304
- * @returns A promise that resolves when the update is complete.
305
- * @throws Will throw an error if no updates are provided or if the update operation fails.
306
- */
307
- async updateIndexById(
308
- indexName: string,
309
- id: string,
310
- update: { vector?: number[]; metadata?: Record<string, any> },
311
- ): Promise<void> {
312
- this.logger.warn(
313
- `Deprecation Warning: updateIndexById() is deprecated.
314
- Please use updateVector() instead.
315
- updateIndexById() will be removed on May 20th, 2025.`,
316
- );
317
- await this.updateVector({ indexName, id, update });
318
- }
319
-
320
313
  /**
321
314
  * Updates a vector by its ID with the provided vector and/or metadata.
322
315
  * @param indexName - The name of the index containing the vector.
@@ -327,16 +320,16 @@ export class OpenSearchVector extends MastraVector {
327
320
  * @returns A promise that resolves when the update is complete.
328
321
  * @throws Will throw an error if no updates are provided or if the update operation fails.
329
322
  */
330
- async updateVector(...args: ParamsToArgs<UpdateVectorParams>): Promise<void> {
331
- const params = this.normalizeArgs<UpdateVectorParams>('updateVector', args);
332
- const { indexName, id, update } = params;
333
- if (!update.vector && !update.metadata) {
334
- throw new Error('No updates provided');
335
- }
336
-
323
+ async updateVector({ indexName, id, update }: UpdateVectorParams): Promise<void> {
324
+ let existingDoc;
337
325
  try {
326
+ if (!update.vector && !update.metadata) {
327
+ throw new Error('No updates provided');
328
+ }
329
+
338
330
  // First get the current document to merge with updates
339
- const { body: existingDoc } = await this.client
331
+ const { body } = await this.client
332
+
340
333
  .get({
341
334
  index: indexName,
342
335
  id: id,
@@ -345,25 +338,40 @@ export class OpenSearchVector extends MastraVector {
345
338
  throw new Error(`Document with ID ${id} not found in index ${indexName}`);
346
339
  });
347
340
 
348
- if (!existingDoc || !existingDoc._source) {
341
+ if (!body || !body._source) {
349
342
  throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);
350
343
  }
344
+ existingDoc = body;
345
+ } catch (error) {
346
+ throw new MastraError(
347
+ {
348
+ id: 'STORAGE_OPENSEARCH_VECTOR_UPDATE_VECTOR_FAILED',
349
+ domain: ErrorDomain.STORAGE,
350
+ category: ErrorCategory.USER,
351
+ details: { indexName, id },
352
+ },
353
+ error,
354
+ );
355
+ }
351
356
 
352
- const source = existingDoc._source;
353
- const updatedDoc: Record<string, any> = {
354
- id: source.id || id,
355
- };
357
+ const source = existingDoc._source;
358
+ const updatedDoc: Record<string, any> = {
359
+ id: source?.id || id,
360
+ };
356
361
 
362
+ try {
357
363
  // Update vector if provided
358
364
  if (update.vector) {
359
365
  // Get index stats to check dimension
366
+ console.log(`1`);
360
367
  const indexInfo = await this.describeIndex({ indexName });
361
368
 
362
369
  // Validate vector dimensions
370
+ console.log(`2`);
363
371
  this.validateVectorDimensions([update.vector], indexInfo.dimension);
364
372
 
365
373
  updatedDoc.embedding = update.vector;
366
- } else if (source.embedding) {
374
+ } else if (source?.embedding) {
367
375
  updatedDoc.embedding = source.embedding;
368
376
  }
369
377
 
@@ -371,10 +379,11 @@ export class OpenSearchVector extends MastraVector {
371
379
  if (update.metadata) {
372
380
  updatedDoc.metadata = update.metadata;
373
381
  } else {
374
- updatedDoc.metadata = source.metadata || {};
382
+ updatedDoc.metadata = source?.metadata || {};
375
383
  }
376
384
 
377
385
  // Update the document
386
+ console.log(`3`);
378
387
  await this.client.index({
379
388
  index: indexName,
380
389
  id: id,
@@ -382,29 +391,18 @@ export class OpenSearchVector extends MastraVector {
382
391
  refresh: true,
383
392
  });
384
393
  } catch (error) {
385
- console.error(`Failed to update document with ID ${id} in index ${indexName}:`, error);
386
- throw error;
394
+ throw new MastraError(
395
+ {
396
+ id: 'STORAGE_OPENSEARCH_VECTOR_UPDATE_VECTOR_FAILED',
397
+ domain: ErrorDomain.STORAGE,
398
+ category: ErrorCategory.THIRD_PARTY,
399
+ details: { indexName, id },
400
+ },
401
+ error,
402
+ );
387
403
  }
388
404
  }
389
405
 
390
- /**
391
- * @deprecated Use {@link deleteVector} instead. This method will be removed on May 20th, 2025.
392
- *
393
- * Deletes a vector by its ID.
394
- * @param indexName - The name of the index containing the vector.
395
- * @param id - The ID of the vector to delete.
396
- * @returns A promise that resolves when the deletion is complete.
397
- * @throws Will throw an error if the deletion operation fails.
398
- */
399
- async deleteIndexById(indexName: string, id: string): Promise<void> {
400
- this.logger.warn(
401
- `Deprecation Warning: deleteIndexById() is deprecated.
402
- Please use deleteVector() instead.
403
- deleteIndexById() will be removed on May 20th, 2025.`,
404
- );
405
- await this.deleteVector({ indexName, id });
406
- }
407
-
408
406
  /**
409
407
  * Deletes a vector by its ID.
410
408
  * @param indexName - The name of the index containing the vector.
@@ -412,9 +410,7 @@ export class OpenSearchVector extends MastraVector {
412
410
  * @returns A promise that resolves when the deletion is complete.
413
411
  * @throws Will throw an error if the deletion operation fails.
414
412
  */
415
- async deleteVector(...args: ParamsToArgs<DeleteVectorParams>): Promise<void> {
416
- const params = this.normalizeArgs<DeleteVectorParams>('deleteVector', args);
417
- const { indexName, id } = params;
413
+ async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {
418
414
  try {
419
415
  await this.client.delete({
420
416
  index: indexName,
@@ -422,11 +418,19 @@ export class OpenSearchVector extends MastraVector {
422
418
  refresh: true,
423
419
  });
424
420
  } catch (error: unknown) {
425
- console.error(`Failed to delete document with ID ${id} from index ${indexName}:`, error);
426
- // Don't throw error if document doesn't exist, just log it
427
- if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode !== 404) {
428
- throw error;
421
+ // Don't throw error if document doesn't exist (404)
422
+ if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {
423
+ return;
429
424
  }
425
+ throw new MastraError(
426
+ {
427
+ id: 'STORAGE_OPENSEARCH_VECTOR_DELETE_VECTOR_FAILED',
428
+ domain: ErrorDomain.STORAGE,
429
+ category: ErrorCategory.THIRD_PARTY,
430
+ details: { indexName, id },
431
+ },
432
+ error,
433
+ );
430
434
  }
431
435
  }
432
436
  }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Vector store prompt for OpenSearch. This prompt details supported filter operators, syntax, and usage examples.
3
+ * Use this as a guide for constructing valid filters for OpenSearch vector queries in Mastra.
4
+ */
5
+ export const OPENSEARCH_PROMPT = `When querying OpenSearch, you can ONLY use the operators listed below. Any other operators will be rejected.
6
+ Important: Do not explain how to construct the filter—use the specified operators and fields to search the content and return relevant results.
7
+ If a user tries to use an unsupported operator, reject the filter entirely and let them know that the operator is not supported.
8
+
9
+ Basic Comparison Operators:
10
+ - $eq: Exact match (default for field: value)
11
+ Example: { "category": "electronics" }
12
+ - $ne: Not equal
13
+ Example: { "category": { "$ne": "electronics" } }
14
+ - $gt: Greater than
15
+ Example: { "price": { "$gt": 100 } }
16
+ - $gte: Greater than or equal
17
+ Example: { "price": { "$gte": 100 } }
18
+ - $lt: Less than
19
+ Example: { "price": { "$lt": 100 } }
20
+ - $lte: Less than or equal
21
+ Example: { "price": { "$lte": 100 } }
22
+
23
+ Array Operators:
24
+ - $in: Match any value in array
25
+ Example: { "category": { "$in": ["electronics", "books"] } }
26
+ - $nin: Does not match any value in array
27
+ Example: { "category": { "$nin": ["electronics", "books"] } }
28
+ - $all: Match all values in array
29
+ Example: { "tags": { "$all": ["premium", "sale"] } }
30
+
31
+ Logical Operators:
32
+ - $and: Logical AND (implicit when using multiple conditions)
33
+ Example: { "$and": [{ "price": { "$gt": 100 } }, { "category": "electronics" }] }
34
+ - $or: Logical OR
35
+ Example: { "$or": [{ "price": { "$lt": 50 } }, { "category": "books" }] }
36
+ - $not: Logical NOT
37
+ Example: { "$not": { "category": "electronics" } }
38
+
39
+ Element Operators:
40
+ - $exists: Check if field exists
41
+ Example: { "rating": { "$exists": true } }
42
+
43
+ Regex Operator:
44
+ - $regex: Match using a regular expression (ECMAScript syntax)
45
+ Example: { "name": { "$regex": "^Sam.*son$" } }
46
+ Note: Regex queries are supported for string fields only. Use valid ECMAScript patterns; invalid patterns will throw an error.
47
+
48
+ Restrictions:
49
+ - Nested fields are supported using dot notation (e.g., "address.city").
50
+ - Multiple conditions on the same field are supported (e.g., { "price": { "$gte": 100, "$lte": 1000 } }).
51
+ - Only logical operators ($and, $or, $not) can be used at the top level.
52
+ - All other operators must be used within a field condition.
53
+ Valid: { "field": { "$gt": 100 } }
54
+ Valid: { "$and": [...] }
55
+ Invalid: { "$gt": 100 }
56
+ - Logical operators must contain field conditions, not direct operators.
57
+ Valid: { "$and": [{ "field": { "$gt": 100 } }] }
58
+ Invalid: { "$and": [{ "$gt": 100 }] }
59
+ - $not operator:
60
+ - Must be an object
61
+ - Cannot be empty
62
+ - Can be used at field level or top level
63
+ - Valid: { "$not": { "field": "value" } }
64
+ - Valid: { "field": { "$not": { "$eq": "value" } } }
65
+ - Array operators work on array fields only.
66
+ - Empty arrays in conditions are handled gracefully.
67
+ - Regex queries are case-sensitive by default; use patterns accordingly.
68
+
69
+ Example Complex Query:
70
+ {
71
+ "$and": [
72
+ { "category": { "$in": ["electronics", "computers"] } },
73
+ { "price": { "$gte": 100, "$lte": 1000 } },
74
+ { "tags": { "$all": ["premium"] } },
75
+ { "rating": { "$exists": true, "$gt": 4 } },
76
+ { "$or": [
77
+ { "stock": { "$gt": 0 } },
78
+ { "preorder": true }
79
+ ]},
80
+ { "name": { "$regex": "^Sam.*son$" } }
81
+ ]
82
+ }`;
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": ["./tsconfig.json", "../../tsconfig.build.json"],
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "**/*.test.ts", "src/**/*.mock.ts"]
9
+ }
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "extends": "../../tsconfig.node.json",
3
- "include": ["src/**/*"],
3
+ "include": ["src/**/*", "tsup.config.ts"],
4
4
  "exclude": ["node_modules", "**/*.test.ts"]
5
5
  }
package/tsup.config.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { generateTypes } from '@internal/types-builder';
2
+ import { defineConfig } from 'tsup';
3
+
4
+ export default defineConfig({
5
+ entry: ['src/index.ts'],
6
+ format: ['esm', 'cjs'],
7
+ clean: true,
8
+ dts: false,
9
+ splitting: true,
10
+ treeshake: {
11
+ preset: 'smallest',
12
+ },
13
+ sourcemap: true,
14
+ onSuccess: async () => {
15
+ await generateTypes(process.cwd());
16
+ },
17
+ });