@mastra/mongodb 0.11.1-alpha.0 → 0.11.1-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.
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
1
2
  import { MastraVector } from '@mastra/core/vector';
2
3
  import { MongoClient } from 'mongodb';
3
4
  import { v4 } from 'uuid';
@@ -116,28 +117,68 @@ var MongoDBVector = class extends MastraVector {
116
117
  }
117
118
  // Public methods
118
119
  async connect() {
119
- await this.client.connect();
120
+ try {
121
+ await this.client.connect();
122
+ } catch (error) {
123
+ throw new MastraError(
124
+ {
125
+ id: "STORAGE_MONGODB_VECTOR_CONNECT_FAILED",
126
+ domain: ErrorDomain.STORAGE,
127
+ category: ErrorCategory.THIRD_PARTY
128
+ },
129
+ error
130
+ );
131
+ }
120
132
  }
121
133
  async disconnect() {
122
- await this.client.close();
134
+ try {
135
+ await this.client.close();
136
+ } catch (error) {
137
+ throw new MastraError(
138
+ {
139
+ id: "STORAGE_MONGODB_VECTOR_DISCONNECT_FAILED",
140
+ domain: ErrorDomain.STORAGE,
141
+ category: ErrorCategory.THIRD_PARTY
142
+ },
143
+ error
144
+ );
145
+ }
123
146
  }
124
147
  async createIndex({ indexName, dimension, metric = "cosine" }) {
125
- if (!Number.isInteger(dimension) || dimension <= 0) {
126
- throw new Error("Dimension must be a positive integer");
127
- }
128
- const mongoMetric = this.mongoMetricMap[metric];
129
- if (!mongoMetric) {
130
- throw new Error(`Invalid metric: "${metric}". Must be one of: cosine, euclidean, dotproduct`);
131
- }
132
- const collectionExists = await this.db.listCollections({ name: indexName }).hasNext();
133
- if (!collectionExists) {
134
- await this.db.createCollection(indexName);
148
+ let mongoMetric;
149
+ try {
150
+ if (!Number.isInteger(dimension) || dimension <= 0) {
151
+ throw new Error("Dimension must be a positive integer");
152
+ }
153
+ mongoMetric = this.mongoMetricMap[metric];
154
+ if (!mongoMetric) {
155
+ throw new Error(`Invalid metric: "${metric}". Must be one of: cosine, euclidean, dotproduct`);
156
+ }
157
+ } catch (error) {
158
+ throw new MastraError(
159
+ {
160
+ id: "STORAGE_MONGODB_VECTOR_CREATE_INDEX_INVALID_ARGS",
161
+ domain: ErrorDomain.STORAGE,
162
+ category: ErrorCategory.USER,
163
+ details: {
164
+ indexName,
165
+ dimension,
166
+ metric
167
+ }
168
+ },
169
+ error
170
+ );
135
171
  }
136
- const collection = await this.getCollection(indexName);
137
- const indexNameInternal = `${indexName}_vector_index`;
138
- const embeddingField = this.embeddingFieldName;
139
- const numDimensions = dimension;
172
+ let collection;
140
173
  try {
174
+ const collectionExists = await this.db.listCollections({ name: indexName }).hasNext();
175
+ if (!collectionExists) {
176
+ await this.db.createCollection(indexName);
177
+ }
178
+ collection = await this.getCollection(indexName);
179
+ const indexNameInternal = `${indexName}_vector_index`;
180
+ const embeddingField = this.embeddingFieldName;
181
+ const numDimensions = dimension;
141
182
  await collection.createSearchIndex({
142
183
  definition: {
143
184
  fields: [
@@ -154,10 +195,31 @@ var MongoDBVector = class extends MastraVector {
154
195
  });
155
196
  } catch (error) {
156
197
  if (error.codeName !== "IndexAlreadyExists") {
157
- throw error;
198
+ throw new MastraError(
199
+ {
200
+ id: "STORAGE_MONGODB_VECTOR_CREATE_INDEX_FAILED",
201
+ domain: ErrorDomain.STORAGE,
202
+ category: ErrorCategory.THIRD_PARTY
203
+ },
204
+ error
205
+ );
158
206
  }
159
207
  }
160
- await collection.updateOne({ _id: "__index_metadata__" }, { $set: { dimension, metric } }, { upsert: true });
208
+ try {
209
+ await collection?.updateOne({ _id: "__index_metadata__" }, { $set: { dimension, metric } }, { upsert: true });
210
+ } catch (error) {
211
+ throw new MastraError(
212
+ {
213
+ id: "STORAGE_MONGODB_VECTOR_CREATE_INDEX_FAILED_STORE_METADATA",
214
+ domain: ErrorDomain.STORAGE,
215
+ category: ErrorCategory.THIRD_PARTY,
216
+ details: {
217
+ indexName
218
+ }
219
+ },
220
+ error
221
+ );
222
+ }
161
223
  }
162
224
  /**
163
225
  * Waits for the index to be ready.
@@ -187,40 +249,54 @@ var MongoDBVector = class extends MastraVector {
187
249
  throw new Error(`Index "${indexNameInternal}" did not become ready within timeout`);
188
250
  }
189
251
  async upsert({ indexName, vectors, metadata, ids, documents }) {
190
- const collection = await this.getCollection(indexName);
191
- this.collectionForValidation = collection;
192
- const stats = await this.describeIndex({ indexName });
193
- await this.validateVectorDimensions(vectors, stats.dimension);
194
- const generatedIds = ids || vectors.map(() => v4());
195
- const operations = vectors.map((vector, idx) => {
196
- const id = generatedIds[idx];
197
- const meta = metadata?.[idx] || {};
198
- const doc = documents?.[idx];
199
- const normalizedMeta = Object.keys(meta).reduce(
200
- (acc, key) => {
201
- acc[key] = meta[key] instanceof Date ? meta[key].toISOString() : meta[key];
202
- return acc;
252
+ try {
253
+ const collection = await this.getCollection(indexName);
254
+ this.collectionForValidation = collection;
255
+ const stats = await this.describeIndex({ indexName });
256
+ await this.validateVectorDimensions(vectors, stats.dimension);
257
+ const generatedIds = ids || vectors.map(() => v4());
258
+ const operations = vectors.map((vector, idx) => {
259
+ const id = generatedIds[idx];
260
+ const meta = metadata?.[idx] || {};
261
+ const doc = documents?.[idx];
262
+ const normalizedMeta = Object.keys(meta).reduce(
263
+ (acc, key) => {
264
+ acc[key] = meta[key] instanceof Date ? meta[key].toISOString() : meta[key];
265
+ return acc;
266
+ },
267
+ {}
268
+ );
269
+ const updateDoc = {
270
+ [this.embeddingFieldName]: vector,
271
+ [this.metadataFieldName]: normalizedMeta
272
+ };
273
+ if (doc !== void 0) {
274
+ updateDoc[this.documentFieldName] = doc;
275
+ }
276
+ return {
277
+ updateOne: {
278
+ filter: { _id: id },
279
+ // '_id' is a string as per MongoDBDocument interface
280
+ update: { $set: updateDoc },
281
+ upsert: true
282
+ }
283
+ };
284
+ });
285
+ await collection.bulkWrite(operations);
286
+ return generatedIds;
287
+ } catch (error) {
288
+ throw new MastraError(
289
+ {
290
+ id: "STORAGE_MONGODB_VECTOR_UPSERT_FAILED",
291
+ domain: ErrorDomain.STORAGE,
292
+ category: ErrorCategory.THIRD_PARTY,
293
+ details: {
294
+ indexName
295
+ }
203
296
  },
204
- {}
297
+ error
205
298
  );
206
- const updateDoc = {
207
- [this.embeddingFieldName]: vector,
208
- [this.metadataFieldName]: normalizedMeta
209
- };
210
- if (doc !== void 0) {
211
- updateDoc[this.documentFieldName] = doc;
212
- }
213
- return {
214
- updateOne: {
215
- filter: { _id: id },
216
- // '_id' is a string as per MongoDBDocument interface
217
- update: { $set: updateDoc },
218
- upsert: true
219
- }
220
- };
221
- });
222
- await collection.bulkWrite(operations);
223
- return generatedIds;
299
+ }
224
300
  }
225
301
  async query({
226
302
  indexName,
@@ -230,44 +306,44 @@ var MongoDBVector = class extends MastraVector {
230
306
  includeVector = false,
231
307
  documentFilter
232
308
  }) {
233
- const collection = await this.getCollection(indexName, true);
234
- const indexNameInternal = `${indexName}_vector_index`;
235
- const mongoFilter = this.transformFilter(filter);
236
- const documentMongoFilter = documentFilter ? { [this.documentFieldName]: documentFilter } : {};
237
- let combinedFilter = {};
238
- if (Object.keys(mongoFilter).length > 0 && Object.keys(documentMongoFilter).length > 0) {
239
- combinedFilter = { $and: [mongoFilter, documentMongoFilter] };
240
- } else if (Object.keys(mongoFilter).length > 0) {
241
- combinedFilter = mongoFilter;
242
- } else if (Object.keys(documentMongoFilter).length > 0) {
243
- combinedFilter = documentMongoFilter;
244
- }
245
- const pipeline = [
246
- {
247
- $vectorSearch: {
248
- index: indexNameInternal,
249
- queryVector,
250
- path: this.embeddingFieldName,
251
- numCandidates: 100,
252
- limit: topK
253
- }
254
- },
255
- // Apply the filter using $match stage
256
- ...Object.keys(combinedFilter).length > 0 ? [{ $match: combinedFilter }] : [],
257
- {
258
- $set: { score: { $meta: "vectorSearchScore" } }
259
- },
260
- {
261
- $project: {
262
- _id: 1,
263
- score: 1,
264
- metadata: `$${this.metadataFieldName}`,
265
- document: `$${this.documentFieldName}`,
266
- ...includeVector && { vector: `$${this.embeddingFieldName}` }
267
- }
268
- }
269
- ];
270
309
  try {
310
+ const collection = await this.getCollection(indexName, true);
311
+ const indexNameInternal = `${indexName}_vector_index`;
312
+ const mongoFilter = this.transformFilter(filter);
313
+ const documentMongoFilter = documentFilter ? { [this.documentFieldName]: documentFilter } : {};
314
+ let combinedFilter = {};
315
+ if (Object.keys(mongoFilter).length > 0 && Object.keys(documentMongoFilter).length > 0) {
316
+ combinedFilter = { $and: [mongoFilter, documentMongoFilter] };
317
+ } else if (Object.keys(mongoFilter).length > 0) {
318
+ combinedFilter = mongoFilter;
319
+ } else if (Object.keys(documentMongoFilter).length > 0) {
320
+ combinedFilter = documentMongoFilter;
321
+ }
322
+ const pipeline = [
323
+ {
324
+ $vectorSearch: {
325
+ index: indexNameInternal,
326
+ queryVector,
327
+ path: this.embeddingFieldName,
328
+ numCandidates: 100,
329
+ limit: topK
330
+ }
331
+ },
332
+ // Apply the filter using $match stage
333
+ ...Object.keys(combinedFilter).length > 0 ? [{ $match: combinedFilter }] : [],
334
+ {
335
+ $set: { score: { $meta: "vectorSearchScore" } }
336
+ },
337
+ {
338
+ $project: {
339
+ _id: 1,
340
+ score: 1,
341
+ metadata: `$${this.metadataFieldName}`,
342
+ document: `$${this.documentFieldName}`,
343
+ ...includeVector && { vector: `$${this.embeddingFieldName}` }
344
+ }
345
+ }
346
+ ];
271
347
  const results = await collection.aggregate(pipeline).toArray();
272
348
  return results.map((result) => ({
273
349
  id: result._id,
@@ -277,13 +353,33 @@ var MongoDBVector = class extends MastraVector {
277
353
  document: result.document
278
354
  }));
279
355
  } catch (error) {
280
- console.error("Error during vector search:", error);
281
- throw error;
356
+ throw new MastraError(
357
+ {
358
+ id: "STORAGE_MONGODB_VECTOR_QUERY_FAILED",
359
+ domain: ErrorDomain.STORAGE,
360
+ category: ErrorCategory.THIRD_PARTY,
361
+ details: {
362
+ indexName
363
+ }
364
+ },
365
+ error
366
+ );
282
367
  }
283
368
  }
284
369
  async listIndexes() {
285
- const collections = await this.db.listCollections().toArray();
286
- return collections.map((col) => col.name);
370
+ try {
371
+ const collections = await this.db.listCollections().toArray();
372
+ return collections.map((col) => col.name);
373
+ } catch (error) {
374
+ throw new MastraError(
375
+ {
376
+ id: "STORAGE_MONGODB_VECTOR_LIST_INDEXES_FAILED",
377
+ domain: ErrorDomain.STORAGE,
378
+ category: ErrorCategory.THIRD_PARTY
379
+ },
380
+ error
381
+ );
382
+ }
287
383
  }
288
384
  /**
289
385
  * Retrieves statistics about a vector index.
@@ -292,24 +388,52 @@ var MongoDBVector = class extends MastraVector {
292
388
  * @returns A promise that resolves to the index statistics including dimension, count and metric
293
389
  */
294
390
  async describeIndex({ indexName }) {
295
- const collection = await this.getCollection(indexName, true);
296
- const count = await collection.countDocuments({ _id: { $ne: "__index_metadata__" } });
297
- const metadataDoc = await collection.findOne({ _id: "__index_metadata__" });
298
- const dimension = metadataDoc?.dimension || 0;
299
- const metric = metadataDoc?.metric || "cosine";
300
- return {
301
- dimension,
302
- count,
303
- metric
304
- };
391
+ try {
392
+ const collection = await this.getCollection(indexName, true);
393
+ const count = await collection.countDocuments({ _id: { $ne: "__index_metadata__" } });
394
+ const metadataDoc = await collection.findOne({ _id: "__index_metadata__" });
395
+ const dimension = metadataDoc?.dimension || 0;
396
+ const metric = metadataDoc?.metric || "cosine";
397
+ return {
398
+ dimension,
399
+ count,
400
+ metric
401
+ };
402
+ } catch (error) {
403
+ throw new MastraError(
404
+ {
405
+ id: "STORAGE_MONGODB_VECTOR_DESCRIBE_INDEX_FAILED",
406
+ domain: ErrorDomain.STORAGE,
407
+ category: ErrorCategory.THIRD_PARTY,
408
+ details: {
409
+ indexName
410
+ }
411
+ },
412
+ error
413
+ );
414
+ }
305
415
  }
306
416
  async deleteIndex({ indexName }) {
307
417
  const collection = await this.getCollection(indexName, false);
308
- if (collection) {
309
- await collection.drop();
310
- this.collections.delete(indexName);
311
- } else {
312
- throw new Error(`Index (Collection) "${indexName}" does not exist`);
418
+ try {
419
+ if (collection) {
420
+ await collection.drop();
421
+ this.collections.delete(indexName);
422
+ } else {
423
+ throw new Error(`Index (Collection) "${indexName}" does not exist`);
424
+ }
425
+ } catch (error) {
426
+ throw new MastraError(
427
+ {
428
+ id: "STORAGE_MONGODB_VECTOR_DELETE_INDEX_FAILED",
429
+ domain: ErrorDomain.STORAGE,
430
+ category: ErrorCategory.THIRD_PARTY,
431
+ details: {
432
+ indexName
433
+ }
434
+ },
435
+ error
436
+ );
313
437
  }
314
438
  }
315
439
  /**
@@ -346,7 +470,18 @@ var MongoDBVector = class extends MastraVector {
346
470
  }
347
471
  await collection.findOneAndUpdate({ _id: id }, { $set: updateDoc });
348
472
  } catch (error) {
349
- throw new Error(`Failed to update vector by id: ${id} for index name: ${indexName}: ${error.message}`);
473
+ throw new MastraError(
474
+ {
475
+ id: "STORAGE_MONGODB_VECTOR_UPDATE_VECTOR_FAILED",
476
+ domain: ErrorDomain.STORAGE,
477
+ category: ErrorCategory.THIRD_PARTY,
478
+ details: {
479
+ indexName,
480
+ id
481
+ }
482
+ },
483
+ error
484
+ );
350
485
  }
351
486
  }
352
487
  /**
@@ -361,7 +496,18 @@ var MongoDBVector = class extends MastraVector {
361
496
  const collection = await this.getCollection(indexName, true);
362
497
  await collection.deleteOne({ _id: id });
363
498
  } catch (error) {
364
- throw new Error(`Failed to delete vector by id: ${id} for index name: ${indexName}: ${error.message}`);
499
+ throw new MastraError(
500
+ {
501
+ id: "STORAGE_MONGODB_VECTOR_DELETE_VECTOR_FAILED",
502
+ domain: ErrorDomain.STORAGE,
503
+ category: ErrorCategory.THIRD_PARTY,
504
+ details: {
505
+ indexName,
506
+ id
507
+ }
508
+ },
509
+ error
510
+ );
365
511
  }
366
512
  }
367
513
  // Private methods
@@ -417,14 +563,26 @@ var MongoDBStore = class extends MastraStorage {
417
563
  constructor(config) {
418
564
  super({ name: "MongoDBStore" });
419
565
  this.#isConnected = false;
420
- if (!config.url?.trim().length) {
421
- throw new Error(
422
- "MongoDBStore: url must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
423
- );
424
- }
425
- if (!config.dbName?.trim().length) {
426
- throw new Error(
427
- "MongoDBStore: dbName must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
566
+ try {
567
+ if (!config.url?.trim().length) {
568
+ throw new Error(
569
+ "MongoDBStore: url must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
570
+ );
571
+ }
572
+ if (!config.dbName?.trim().length) {
573
+ throw new Error(
574
+ "MongoDBStore: dbName must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
575
+ );
576
+ }
577
+ } catch (error) {
578
+ throw new MastraError(
579
+ {
580
+ id: "STORAGE_MONGODB_STORE_CONSTRUCTOR_FAILED",
581
+ domain: ErrorDomain.STORAGE,
582
+ category: ErrorCategory.USER,
583
+ details: { url: config.url, dbName: config.dbName }
584
+ },
585
+ error
428
586
  );
429
587
  }
430
588
  this.#dbName = config.dbName;
@@ -459,7 +617,17 @@ var MongoDBStore = class extends MastraStorage {
459
617
  await collection.deleteMany({});
460
618
  } catch (error) {
461
619
  if (error instanceof Error) {
462
- this.logger.error(error.message);
620
+ const matstraError = new MastraError(
621
+ {
622
+ id: "STORAGE_MONGODB_STORE_CLEAR_TABLE_FAILED",
623
+ domain: ErrorDomain.STORAGE,
624
+ category: ErrorCategory.THIRD_PARTY,
625
+ details: { tableName }
626
+ },
627
+ error
628
+ );
629
+ this.logger.error(matstraError.message);
630
+ this.logger?.trackException(matstraError);
463
631
  }
464
632
  }
465
633
  }
@@ -468,8 +636,19 @@ var MongoDBStore = class extends MastraStorage {
468
636
  const collection = await this.getCollection(tableName);
469
637
  await collection.insertOne(record);
470
638
  } catch (error) {
471
- this.logger.error(`Error upserting into table ${tableName}: ${error}`);
472
- throw error;
639
+ if (error instanceof Error) {
640
+ const matstraError = new MastraError(
641
+ {
642
+ id: "STORAGE_MONGODB_STORE_INSERT_FAILED",
643
+ domain: ErrorDomain.STORAGE,
644
+ category: ErrorCategory.THIRD_PARTY,
645
+ details: { tableName }
646
+ },
647
+ error
648
+ );
649
+ this.logger.error(matstraError.message);
650
+ this.logger?.trackException(matstraError);
651
+ }
473
652
  }
474
653
  }
475
654
  async batchInsert({ tableName, records }) {
@@ -480,8 +659,15 @@ var MongoDBStore = class extends MastraStorage {
480
659
  const collection = await this.getCollection(tableName);
481
660
  await collection.insertMany(records);
482
661
  } catch (error) {
483
- this.logger.error(`Error upserting into table ${tableName}: ${error}`);
484
- throw error;
662
+ throw new MastraError(
663
+ {
664
+ id: "STORAGE_MONGODB_STORE_BATCH_INSERT_FAILED",
665
+ domain: ErrorDomain.STORAGE,
666
+ category: ErrorCategory.THIRD_PARTY,
667
+ details: { tableName }
668
+ },
669
+ error
670
+ );
485
671
  }
486
672
  }
487
673
  async load({ tableName, keys }) {
@@ -490,8 +676,15 @@ var MongoDBStore = class extends MastraStorage {
490
676
  const collection = await this.getCollection(tableName);
491
677
  return await collection.find(keys).toArray();
492
678
  } catch (error) {
493
- this.logger.error(`Error loading ${tableName} with keys ${JSON.stringify(keys)}: ${error}`);
494
- throw error;
679
+ throw new MastraError(
680
+ {
681
+ id: "STORAGE_MONGODB_STORE_LOAD_FAILED",
682
+ domain: ErrorDomain.STORAGE,
683
+ category: ErrorCategory.THIRD_PARTY,
684
+ details: { tableName }
685
+ },
686
+ error
687
+ );
495
688
  }
496
689
  }
497
690
  async getThreadById({ threadId }) {
@@ -506,8 +699,15 @@ var MongoDBStore = class extends MastraStorage {
506
699
  metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
507
700
  };
508
701
  } catch (error) {
509
- this.logger.error(`Error loading thread with ID ${threadId}: ${error}`);
510
- throw error;
702
+ throw new MastraError(
703
+ {
704
+ id: "STORAGE_MONGODB_STORE_GET_THREAD_BY_ID_FAILED",
705
+ domain: ErrorDomain.STORAGE,
706
+ category: ErrorCategory.THIRD_PARTY,
707
+ details: { threadId }
708
+ },
709
+ error
710
+ );
511
711
  }
512
712
  }
513
713
  async getThreadsByResourceId({ resourceId }) {
@@ -522,8 +722,15 @@ var MongoDBStore = class extends MastraStorage {
522
722
  metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
523
723
  }));
524
724
  } catch (error) {
525
- this.logger.error(`Error loading threads by resourceId ${resourceId}: ${error}`);
526
- throw error;
725
+ throw new MastraError(
726
+ {
727
+ id: "STORAGE_MONGODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
728
+ domain: ErrorDomain.STORAGE,
729
+ category: ErrorCategory.THIRD_PARTY,
730
+ details: { resourceId }
731
+ },
732
+ error
733
+ );
527
734
  }
528
735
  }
529
736
  async saveThread({ thread }) {
@@ -541,8 +748,15 @@ var MongoDBStore = class extends MastraStorage {
541
748
  );
542
749
  return thread;
543
750
  } catch (error) {
544
- this.logger.error(`Error saving thread ${thread.id}: ${error}`);
545
- throw error;
751
+ throw new MastraError(
752
+ {
753
+ id: "STORAGE_MONGODB_STORE_SAVE_THREAD_FAILED",
754
+ domain: ErrorDomain.STORAGE,
755
+ category: ErrorCategory.THIRD_PARTY,
756
+ details: { threadId: thread.id }
757
+ },
758
+ error
759
+ );
546
760
  }
547
761
  }
548
762
  async updateThread({
@@ -552,7 +766,13 @@ var MongoDBStore = class extends MastraStorage {
552
766
  }) {
553
767
  const thread = await this.getThreadById({ threadId: id });
554
768
  if (!thread) {
555
- throw new Error(`Thread ${id} not found`);
769
+ throw new MastraError({
770
+ id: "STORAGE_MONGODB_STORE_UPDATE_THREAD_NOT_FOUND",
771
+ domain: ErrorDomain.STORAGE,
772
+ category: ErrorCategory.THIRD_PARTY,
773
+ details: { threadId: id },
774
+ text: `Thread ${id} not found`
775
+ });
556
776
  }
557
777
  const updatedThread = {
558
778
  ...thread,
@@ -574,8 +794,15 @@ var MongoDBStore = class extends MastraStorage {
574
794
  }
575
795
  );
576
796
  } catch (error) {
577
- this.logger.error(`Error updating thread ${id}:) ${error}`);
578
- throw error;
797
+ throw new MastraError(
798
+ {
799
+ id: "STORAGE_MONGODB_STORE_UPDATE_THREAD_FAILED",
800
+ domain: ErrorDomain.STORAGE,
801
+ category: ErrorCategory.THIRD_PARTY,
802
+ details: { threadId: id }
803
+ },
804
+ error
805
+ );
579
806
  }
580
807
  return updatedThread;
581
808
  }
@@ -586,8 +813,15 @@ var MongoDBStore = class extends MastraStorage {
586
813
  const collectionThreads = await this.getCollection(TABLE_THREADS);
587
814
  await collectionThreads.deleteOne({ id: threadId });
588
815
  } catch (error) {
589
- this.logger.error(`Error deleting thread ${threadId}: ${error}`);
590
- throw error;
816
+ throw new MastraError(
817
+ {
818
+ id: "STORAGE_MONGODB_STORE_DELETE_THREAD_FAILED",
819
+ domain: ErrorDomain.STORAGE,
820
+ category: ErrorCategory.THIRD_PARTY,
821
+ details: { threadId }
822
+ },
823
+ error
824
+ );
591
825
  }
592
826
  }
593
827
  async getMessages({
@@ -596,7 +830,7 @@ var MongoDBStore = class extends MastraStorage {
596
830
  format
597
831
  }) {
598
832
  try {
599
- const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
833
+ const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
600
834
  const include = selectBy?.include || [];
601
835
  let messages = [];
602
836
  let allMessages = [];
@@ -637,8 +871,15 @@ var MongoDBStore = class extends MastraStorage {
637
871
  if (format === `v2`) return list.get.all.v2();
638
872
  return list.get.all.v1();
639
873
  } catch (error) {
640
- this.logger.error("Error getting messages:", error);
641
- throw error;
874
+ throw new MastraError(
875
+ {
876
+ id: "STORAGE_MONGODB_STORE_GET_MESSAGES_FAILED",
877
+ domain: ErrorDomain.STORAGE,
878
+ category: ErrorCategory.THIRD_PARTY,
879
+ details: { threadId }
880
+ },
881
+ error
882
+ );
642
883
  }
643
884
  }
644
885
  async saveMessages({
@@ -669,7 +910,15 @@ var MongoDBStore = class extends MastraStorage {
669
910
  const collection = await this.getCollection(TABLE_MESSAGES);
670
911
  const threadsCollection = await this.getCollection(TABLE_THREADS);
671
912
  await Promise.all([
672
- collection.insertMany(messagesToInsert),
913
+ collection.bulkWrite(
914
+ messagesToInsert.map((msg) => ({
915
+ updateOne: {
916
+ filter: { id: msg.id },
917
+ update: { $set: msg },
918
+ upsert: true
919
+ }
920
+ }))
921
+ ),
673
922
  threadsCollection.updateOne({ id: threadId }, { $set: { updatedAt: /* @__PURE__ */ new Date() } })
674
923
  ]);
675
924
  const list = new MessageList().add(messages, "memory");
@@ -695,41 +944,52 @@ var MongoDBStore = class extends MastraStorage {
695
944
  const offset = page * perPage;
696
945
  const query = {};
697
946
  if (name) {
698
- query["name"] = `%${name}%`;
947
+ query["name"] = new RegExp(name);
699
948
  }
700
949
  if (scope) {
701
950
  query["scope"] = scope;
702
951
  }
703
952
  if (attributes) {
704
- Object.keys(attributes).forEach((key) => {
705
- query[`attributes.${key}`] = attributes[key];
706
- });
953
+ query["$and"] = Object.entries(attributes).map(([key, value]) => ({
954
+ attributes: new RegExp(`"${key}":"${value}"`)
955
+ }));
707
956
  }
708
957
  if (filters) {
709
958
  Object.entries(filters).forEach(([key, value]) => {
710
959
  query[key] = value;
711
960
  });
712
961
  }
713
- const collection = await this.getCollection(TABLE_TRACES);
714
- const result = await collection.find(query, {
715
- sort: { startTime: -1 }
716
- }).limit(limit).skip(offset).toArray();
717
- return result.map((row) => ({
718
- id: row.id,
719
- parentSpanId: row.parentSpanId,
720
- traceId: row.traceId,
721
- name: row.name,
722
- scope: row.scope,
723
- kind: row.kind,
724
- status: safelyParseJSON(row.status),
725
- events: safelyParseJSON(row.events),
726
- links: safelyParseJSON(row.links),
727
- attributes: safelyParseJSON(row.attributes),
728
- startTime: row.startTime,
729
- endTime: row.endTime,
730
- other: safelyParseJSON(row.other),
731
- createdAt: row.createdAt
732
- }));
962
+ try {
963
+ const collection = await this.getCollection(TABLE_TRACES);
964
+ const result = await collection.find(query, {
965
+ sort: { startTime: -1 }
966
+ }).limit(limit).skip(offset).toArray();
967
+ return result.map((row) => ({
968
+ id: row.id,
969
+ parentSpanId: row.parentSpanId,
970
+ traceId: row.traceId,
971
+ name: row.name,
972
+ scope: row.scope,
973
+ kind: row.kind,
974
+ status: safelyParseJSON(row.status),
975
+ events: safelyParseJSON(row.events),
976
+ links: safelyParseJSON(row.links),
977
+ attributes: safelyParseJSON(row.attributes),
978
+ startTime: row.startTime,
979
+ endTime: row.endTime,
980
+ other: safelyParseJSON(row.other),
981
+ createdAt: row.createdAt
982
+ }));
983
+ } catch (error) {
984
+ throw new MastraError(
985
+ {
986
+ id: "STORAGE_MONGODB_STORE_GET_TRACES_FAILED",
987
+ domain: ErrorDomain.STORAGE,
988
+ category: ErrorCategory.THIRD_PARTY
989
+ },
990
+ error
991
+ );
992
+ }
733
993
  }
734
994
  async getWorkflowRuns({
735
995
  workflowName,
@@ -751,37 +1011,48 @@ var MongoDBStore = class extends MastraStorage {
751
1011
  query["createdAt"]["$lte"] = toDate;
752
1012
  }
753
1013
  }
754
- const collection = await this.getCollection(TABLE_WORKFLOW_SNAPSHOT);
755
- let total = 0;
756
- if (limit !== void 0 && offset !== void 0) {
757
- total = await collection.countDocuments(query);
758
- }
759
- const request = collection.find(query).sort({ createdAt: "desc" });
760
- if (limit) {
761
- request.limit(limit);
762
- }
763
- if (offset) {
764
- request.skip(offset);
765
- }
766
- const result = await request.toArray();
767
- const runs = result.map((row) => {
768
- let parsedSnapshot = row.snapshot;
769
- if (typeof parsedSnapshot === "string") {
770
- try {
771
- parsedSnapshot = JSON.parse(row.snapshot);
772
- } catch (e) {
773
- console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
774
- }
1014
+ try {
1015
+ const collection = await this.getCollection(TABLE_WORKFLOW_SNAPSHOT);
1016
+ let total = 0;
1017
+ if (limit !== void 0 && offset !== void 0) {
1018
+ total = await collection.countDocuments(query);
775
1019
  }
776
- return {
777
- workflowName: row.workflow_name,
778
- runId: row.run_id,
779
- snapshot: parsedSnapshot,
780
- createdAt: new Date(row.createdAt),
781
- updatedAt: new Date(row.updatedAt)
782
- };
783
- });
784
- return { runs, total: total || runs.length };
1020
+ const request = collection.find(query).sort({ createdAt: "desc" });
1021
+ if (limit) {
1022
+ request.limit(limit);
1023
+ }
1024
+ if (offset) {
1025
+ request.skip(offset);
1026
+ }
1027
+ const result = await request.toArray();
1028
+ const runs = result.map((row) => {
1029
+ let parsedSnapshot = row.snapshot;
1030
+ if (typeof parsedSnapshot === "string") {
1031
+ try {
1032
+ parsedSnapshot = JSON.parse(row.snapshot);
1033
+ } catch (e) {
1034
+ console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1035
+ }
1036
+ }
1037
+ return {
1038
+ workflowName: row.workflow_name,
1039
+ runId: row.run_id,
1040
+ snapshot: parsedSnapshot,
1041
+ createdAt: new Date(row.createdAt),
1042
+ updatedAt: new Date(row.updatedAt)
1043
+ };
1044
+ });
1045
+ return { runs, total: total || runs.length };
1046
+ } catch (error) {
1047
+ throw new MastraError(
1048
+ {
1049
+ id: "STORAGE_MONGODB_STORE_GET_WORKFLOW_RUNS_FAILED",
1050
+ domain: ErrorDomain.STORAGE,
1051
+ category: ErrorCategory.THIRD_PARTY
1052
+ },
1053
+ error
1054
+ );
1055
+ }
785
1056
  }
786
1057
  async getEvalsByAgentName(agentName, type) {
787
1058
  try {
@@ -810,8 +1081,15 @@ var MongoDBStore = class extends MastraStorage {
810
1081
  if (error instanceof Error && error.message.includes("no such table")) {
811
1082
  return [];
812
1083
  }
813
- this.logger.error("Failed to get evals for the specified agent: " + error?.message);
814
- throw error;
1084
+ throw new MastraError(
1085
+ {
1086
+ id: "STORAGE_MONGODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
1087
+ domain: ErrorDomain.STORAGE,
1088
+ category: ErrorCategory.THIRD_PARTY,
1089
+ details: { agentName }
1090
+ },
1091
+ error
1092
+ );
815
1093
  }
816
1094
  }
817
1095
  async persistWorkflowSnapshot({
@@ -836,8 +1114,15 @@ var MongoDBStore = class extends MastraStorage {
836
1114
  { upsert: true }
837
1115
  );
838
1116
  } catch (error) {
839
- this.logger.error(`Error persisting workflow snapshot: ${error}`);
840
- throw error;
1117
+ throw new MastraError(
1118
+ {
1119
+ id: "STORAGE_MONGODB_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
1120
+ domain: ErrorDomain.STORAGE,
1121
+ category: ErrorCategory.THIRD_PARTY,
1122
+ details: { workflowName, runId }
1123
+ },
1124
+ error
1125
+ );
841
1126
  }
842
1127
  }
843
1128
  async loadWorkflowSnapshot({
@@ -857,8 +1142,15 @@ var MongoDBStore = class extends MastraStorage {
857
1142
  }
858
1143
  return JSON.parse(result[0].snapshot);
859
1144
  } catch (error) {
860
- console.error("Error loading workflow snapshot:", error);
861
- throw error;
1145
+ throw new MastraError(
1146
+ {
1147
+ id: "STORAGE_MONGODB_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
1148
+ domain: ErrorDomain.STORAGE,
1149
+ category: ErrorCategory.THIRD_PARTY,
1150
+ details: { workflowName, runId }
1151
+ },
1152
+ error
1153
+ );
862
1154
  }
863
1155
  }
864
1156
  async getWorkflowRunById({
@@ -880,8 +1172,15 @@ var MongoDBStore = class extends MastraStorage {
880
1172
  }
881
1173
  return this.parseWorkflowRun(result);
882
1174
  } catch (error) {
883
- console.error("Error getting workflow run by ID:", error);
884
- throw error;
1175
+ throw new MastraError(
1176
+ {
1177
+ id: "STORAGE_MONGODB_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
1178
+ domain: ErrorDomain.STORAGE,
1179
+ category: ErrorCategory.THIRD_PARTY,
1180
+ details: { runId }
1181
+ },
1182
+ error
1183
+ );
885
1184
  }
886
1185
  }
887
1186
  parseWorkflowRun(row) {
@@ -927,10 +1226,19 @@ var MongoDBStore = class extends MastraStorage {
927
1226
  console.warn("Failed to parse test_info:", e);
928
1227
  }
929
1228
  }
1229
+ const resultValue = JSON.parse(row.result);
1230
+ if (!resultValue || typeof resultValue !== "object" || !("score" in resultValue)) {
1231
+ throw new MastraError({
1232
+ id: "STORAGE_MONGODB_STORE_INVALID_METRIC_FORMAT",
1233
+ text: `Invalid MetricResult format: ${JSON.stringify(resultValue)}`,
1234
+ domain: ErrorDomain.STORAGE,
1235
+ category: ErrorCategory.USER
1236
+ });
1237
+ }
930
1238
  return {
931
1239
  input: row.input,
932
1240
  output: row.output,
933
- result: row.result,
1241
+ result: resultValue,
934
1242
  agentName: row.agent_name,
935
1243
  metricName: row.metric_name,
936
1244
  instructions: row.instructions,
@@ -941,16 +1249,42 @@ var MongoDBStore = class extends MastraStorage {
941
1249
  };
942
1250
  }
943
1251
  async getTracesPaginated(_args) {
944
- throw new Error("Method not implemented.");
1252
+ throw new MastraError({
1253
+ id: "STORAGE_MONGODB_STORE_GET_TRACES_PAGINATED_FAILED",
1254
+ domain: ErrorDomain.STORAGE,
1255
+ category: ErrorCategory.THIRD_PARTY,
1256
+ text: "Method not implemented."
1257
+ });
945
1258
  }
946
1259
  async getThreadsByResourceIdPaginated(_args) {
947
- throw new Error("Method not implemented.");
1260
+ throw new MastraError({
1261
+ id: "STORAGE_MONGODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1262
+ domain: ErrorDomain.STORAGE,
1263
+ category: ErrorCategory.THIRD_PARTY,
1264
+ text: "Method not implemented."
1265
+ });
948
1266
  }
949
1267
  async getMessagesPaginated(_args) {
950
- throw new Error("Method not implemented.");
1268
+ throw new MastraError({
1269
+ id: "STORAGE_MONGODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
1270
+ domain: ErrorDomain.STORAGE,
1271
+ category: ErrorCategory.THIRD_PARTY,
1272
+ text: "Method not implemented."
1273
+ });
951
1274
  }
952
1275
  async close() {
953
- await this.#client.close();
1276
+ try {
1277
+ await this.#client.close();
1278
+ } catch (error) {
1279
+ throw new MastraError(
1280
+ {
1281
+ id: "STORAGE_MONGODB_STORE_CLOSE_FAILED",
1282
+ domain: ErrorDomain.STORAGE,
1283
+ category: ErrorCategory.USER
1284
+ },
1285
+ error
1286
+ );
1287
+ }
954
1288
  }
955
1289
  async updateMessages(_args) {
956
1290
  this.logger.error("updateMessages is not yet implemented in MongoDBStore");