@mastra/mongodb 0.12.0 → 0.12.1-alpha.0

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.cjs CHANGED
@@ -5,8 +5,8 @@ var vector = require('@mastra/core/vector');
5
5
  var mongodb = require('mongodb');
6
6
  var uuid = require('uuid');
7
7
  var filter = require('@mastra/core/vector/filter');
8
- var agent = require('@mastra/core/agent');
9
8
  var storage = require('@mastra/core/storage');
9
+ var agent = require('@mastra/core/agent');
10
10
 
11
11
  // src/vector/index.ts
12
12
  var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
@@ -189,12 +189,25 @@ var MongoDBVector = class extends vector.MastraVector {
189
189
  path: embeddingField,
190
190
  numDimensions,
191
191
  similarity: mongoMetric
192
+ },
193
+ {
194
+ type: "filter",
195
+ path: "_id"
192
196
  }
193
197
  ]
194
198
  },
195
199
  name: indexNameInternal,
196
200
  type: "vectorSearch"
197
201
  });
202
+ await collection.createSearchIndex({
203
+ definition: {
204
+ mappings: {
205
+ dynamic: true
206
+ }
207
+ },
208
+ name: `${indexName}_search_index`,
209
+ type: "search"
210
+ });
198
211
  } catch (error$1) {
199
212
  if (error$1.codeName !== "IndexAlreadyExists") {
200
213
  throw new error.MastraError(
@@ -321,18 +334,21 @@ var MongoDBVector = class extends vector.MastraVector {
321
334
  } else if (Object.keys(documentMongoFilter).length > 0) {
322
335
  combinedFilter = documentMongoFilter;
323
336
  }
337
+ const vectorSearch = {
338
+ index: indexNameInternal,
339
+ queryVector,
340
+ path: this.embeddingFieldName,
341
+ numCandidates: 100,
342
+ limit: topK
343
+ };
344
+ if (Object.keys(combinedFilter).length > 0) {
345
+ const candidateIds = await collection.aggregate([{ $match: combinedFilter }, { $project: { _id: 1 } }]).map((doc) => doc._id).toArray();
346
+ vectorSearch.filter = { _id: { $in: candidateIds } };
347
+ }
324
348
  const pipeline = [
325
349
  {
326
- $vectorSearch: {
327
- index: indexNameInternal,
328
- queryVector,
329
- path: this.embeddingFieldName,
330
- numCandidates: 100,
331
- limit: topK
332
- }
350
+ $vectorSearch: vectorSearch
333
351
  },
334
- // Apply the filter using $match stage
335
- ...Object.keys(combinedFilter).length > 0 ? [{ $match: combinedFilter }] : [],
336
352
  {
337
353
  $set: { score: { $meta: "vectorSearchScore" } }
338
354
  },
@@ -550,200 +566,713 @@ var MongoDBVector = class extends vector.MastraVector {
550
566
  return translator.translate(filter);
551
567
  }
552
568
  };
553
- function safelyParseJSON(jsonString) {
554
- try {
555
- return JSON.parse(jsonString);
556
- } catch {
557
- return {};
558
- }
559
- }
560
- var MongoDBStore = class extends storage.MastraStorage {
561
- #isConnected = false;
569
+ var MongoDBConnector = class _MongoDBConnector {
562
570
  #client;
563
- #db;
564
571
  #dbName;
565
- constructor(config) {
566
- super({ name: "MongoDBStore" });
572
+ #handler;
573
+ #isConnected;
574
+ #db;
575
+ constructor(options) {
576
+ this.#client = options.client;
577
+ this.#dbName = options.dbName;
578
+ this.#handler = options.handler;
567
579
  this.#isConnected = false;
568
- try {
569
- if (!config.url?.trim().length) {
570
- throw new Error(
571
- "MongoDBStore: url must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
572
- );
573
- }
574
- if (!config.dbName?.trim().length) {
575
- throw new Error(
576
- "MongoDBStore: dbName must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
577
- );
578
- }
579
- } catch (error$1) {
580
- throw new error.MastraError(
581
- {
582
- id: "STORAGE_MONGODB_STORE_CONSTRUCTOR_FAILED",
583
- domain: error.ErrorDomain.STORAGE,
584
- category: error.ErrorCategory.USER,
585
- details: { url: config.url, dbName: config.dbName }
586
- },
587
- error$1
580
+ }
581
+ static fromDatabaseConfig(config) {
582
+ if (!config.url?.trim().length) {
583
+ throw new Error(
584
+ "MongoDBStore: url must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
585
+ );
586
+ }
587
+ if (!config.dbName?.trim().length) {
588
+ throw new Error(
589
+ "MongoDBStore: dbName must be provided and cannot be empty. Passing an empty string may cause fallback to local MongoDB defaults."
588
590
  );
589
591
  }
590
- this.#dbName = config.dbName;
591
- this.#client = new mongodb.MongoClient(config.url, config.options);
592
+ return new _MongoDBConnector({
593
+ client: new mongodb.MongoClient(config.url, config.options),
594
+ dbName: config.dbName,
595
+ handler: void 0
596
+ });
597
+ }
598
+ static fromConnectionHandler(handler) {
599
+ return new _MongoDBConnector({
600
+ client: void 0,
601
+ dbName: void 0,
602
+ handler
603
+ });
592
604
  }
593
605
  async getConnection() {
594
- if (this.#isConnected) {
606
+ if (this.#client) {
607
+ if (this.#isConnected && this.#db) {
608
+ return this.#db;
609
+ }
610
+ await this.#client.connect();
611
+ this.#db = this.#client.db(this.#dbName);
612
+ this.#isConnected = true;
595
613
  return this.#db;
596
614
  }
597
- await this.#client.connect();
598
- this.#db = this.#client.db(this.#dbName);
599
- this.#isConnected = true;
600
- return this.#db;
615
+ throw new Error("MongoDBStore: client cannot be empty. Check your MongoDBConnector configuration.");
601
616
  }
602
617
  async getCollection(collectionName) {
618
+ if (this.#handler) {
619
+ return this.#handler.getCollection(collectionName);
620
+ }
603
621
  const db = await this.getConnection();
604
622
  return db.collection(collectionName);
605
623
  }
606
- async createTable() {
607
- }
608
- /**
609
- * No-op: This backend is schemaless and does not require schema changes.
610
- * @param tableName Name of the table
611
- * @param schema Schema of the table
612
- * @param ifNotExists Array of column names to add if they don't exist
613
- */
614
- async alterTable(_args) {
624
+ async close() {
625
+ if (this.#client) {
626
+ await this.#client.close();
627
+ this.#isConnected = false;
628
+ return;
629
+ }
630
+ if (this.#handler) {
631
+ await this.#handler.close();
632
+ }
615
633
  }
616
- async clearTable({ tableName }) {
634
+ };
635
+ function transformEvalRow(row) {
636
+ let testInfoValue = null;
637
+ if (row.test_info) {
617
638
  try {
618
- const collection = await this.getCollection(tableName);
619
- await collection.deleteMany({});
620
- } catch (error$1) {
621
- if (error$1 instanceof Error) {
622
- const matstraError = new error.MastraError(
623
- {
624
- id: "STORAGE_MONGODB_STORE_CLEAR_TABLE_FAILED",
625
- domain: error.ErrorDomain.STORAGE,
626
- category: error.ErrorCategory.THIRD_PARTY,
627
- details: { tableName }
628
- },
629
- error$1
630
- );
631
- this.logger.error(matstraError.message);
632
- this.logger?.trackException(matstraError);
633
- }
639
+ testInfoValue = typeof row.test_info === "string" ? storage.safelyParseJSON(row.test_info) : row.test_info;
640
+ } catch (e) {
641
+ console.warn("Failed to parse test_info:", e);
634
642
  }
635
643
  }
636
- async insert({ tableName, record }) {
644
+ let resultValue;
645
+ try {
646
+ resultValue = typeof row.result === "string" ? storage.safelyParseJSON(row.result) : row.result;
647
+ } catch (e) {
648
+ console.warn("Failed to parse result:", e);
649
+ throw new Error("Invalid result format");
650
+ }
651
+ return {
652
+ agentName: row.agent_name,
653
+ input: row.input,
654
+ output: row.output,
655
+ result: resultValue,
656
+ metricName: row.metric_name,
657
+ instructions: row.instructions,
658
+ testInfo: testInfoValue,
659
+ globalRunId: row.global_run_id,
660
+ runId: row.run_id,
661
+ createdAt: row.createdAt
662
+ };
663
+ }
664
+ var LegacyEvalsMongoDB = class extends storage.LegacyEvalsStorage {
665
+ operations;
666
+ constructor({ operations }) {
667
+ super();
668
+ this.operations = operations;
669
+ }
670
+ /** @deprecated use getEvals instead */
671
+ async getEvalsByAgentName(agentName, type) {
637
672
  try {
638
- const collection = await this.getCollection(tableName);
639
- await collection.insertOne(record);
673
+ const query = {
674
+ agent_name: agentName
675
+ };
676
+ if (type === "test") {
677
+ query["test_info"] = { $ne: null };
678
+ }
679
+ if (type === "live") {
680
+ query["test_info"] = null;
681
+ }
682
+ const collection = await this.operations.getCollection(storage.TABLE_EVALS);
683
+ const documents = await collection.find(query).sort({ created_at: "desc" }).toArray();
684
+ const result = documents.map((row) => transformEvalRow(row));
685
+ return result.filter((row) => {
686
+ if (type === "live") {
687
+ return !Boolean(row.testInfo?.testPath);
688
+ }
689
+ if (type === "test") {
690
+ return row.testInfo?.testPath !== null;
691
+ }
692
+ return true;
693
+ });
640
694
  } catch (error$1) {
641
- if (error$1 instanceof Error) {
642
- const matstraError = new error.MastraError(
643
- {
644
- id: "STORAGE_MONGODB_STORE_INSERT_FAILED",
645
- domain: error.ErrorDomain.STORAGE,
646
- category: error.ErrorCategory.THIRD_PARTY,
647
- details: { tableName }
648
- },
649
- error$1
650
- );
651
- this.logger.error(matstraError.message);
652
- this.logger?.trackException(matstraError);
695
+ if (error$1 instanceof Error && error$1.message.includes("no such table")) {
696
+ return [];
653
697
  }
698
+ throw new error.MastraError(
699
+ {
700
+ id: "STORAGE_MONGODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
701
+ domain: error.ErrorDomain.STORAGE,
702
+ category: error.ErrorCategory.THIRD_PARTY,
703
+ details: { agentName }
704
+ },
705
+ error$1
706
+ );
654
707
  }
655
708
  }
656
- async batchInsert({ tableName, records }) {
657
- if (!records.length) {
658
- return;
709
+ async getEvals(options = {}) {
710
+ const { agentName, type, page = 0, perPage = 100, dateRange } = options;
711
+ const fromDate = dateRange?.start;
712
+ const toDate = dateRange?.end;
713
+ const currentOffset = page * perPage;
714
+ const query = {};
715
+ if (agentName) {
716
+ query["agent_name"] = agentName;
717
+ }
718
+ if (type === "test") {
719
+ query["test_info"] = { $ne: null };
720
+ } else if (type === "live") {
721
+ query["test_info"] = null;
722
+ }
723
+ if (fromDate || toDate) {
724
+ query["createdAt"] = {};
725
+ if (fromDate) {
726
+ query["createdAt"]["$gte"] = fromDate;
727
+ }
728
+ if (toDate) {
729
+ query["createdAt"]["$lte"] = toDate;
730
+ }
659
731
  }
660
732
  try {
661
- const collection = await this.getCollection(tableName);
662
- await collection.insertMany(records);
733
+ const collection = await this.operations.getCollection(storage.TABLE_EVALS);
734
+ let total = 0;
735
+ if (page === 0 || perPage < 1e3) {
736
+ total = await collection.countDocuments(query);
737
+ }
738
+ if (total === 0) {
739
+ return {
740
+ evals: [],
741
+ total: 0,
742
+ page,
743
+ perPage,
744
+ hasMore: false
745
+ };
746
+ }
747
+ const documents = await collection.find(query).sort({ created_at: "desc" }).skip(currentOffset).limit(perPage).toArray();
748
+ const evals = documents.map((row) => transformEvalRow(row));
749
+ const filteredEvals = evals.filter((row) => {
750
+ if (type === "live") {
751
+ return !Boolean(row.testInfo?.testPath);
752
+ }
753
+ if (type === "test") {
754
+ return row.testInfo?.testPath !== null;
755
+ }
756
+ return true;
757
+ });
758
+ const hasMore = currentOffset + filteredEvals.length < total;
759
+ return {
760
+ evals: filteredEvals,
761
+ total,
762
+ page,
763
+ perPage,
764
+ hasMore
765
+ };
663
766
  } catch (error$1) {
664
767
  throw new error.MastraError(
665
768
  {
666
- id: "STORAGE_MONGODB_STORE_BATCH_INSERT_FAILED",
769
+ id: "STORAGE_MONGODB_STORE_GET_EVALS_FAILED",
667
770
  domain: error.ErrorDomain.STORAGE,
668
771
  category: error.ErrorCategory.THIRD_PARTY,
669
- details: { tableName }
772
+ details: {
773
+ agentName: agentName || "all",
774
+ type: type || "all",
775
+ page,
776
+ perPage
777
+ }
670
778
  },
671
779
  error$1
672
780
  );
673
781
  }
674
782
  }
675
- async load({ tableName, keys }) {
676
- this.logger.info(`Loading ${tableName} with keys ${JSON.stringify(keys)}`);
783
+ };
784
+
785
+ // src/storage/domains/utils.ts
786
+ function formatDateForMongoDB(date) {
787
+ return typeof date === "string" ? new Date(date) : date;
788
+ }
789
+
790
+ // src/storage/domains/memory/index.ts
791
+ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
792
+ operations;
793
+ constructor({ operations }) {
794
+ super();
795
+ this.operations = operations;
796
+ }
797
+ parseRow(row) {
798
+ let content = row.content;
799
+ if (typeof content === "string") {
800
+ try {
801
+ content = JSON.parse(content);
802
+ } catch {
803
+ }
804
+ }
805
+ const result = {
806
+ id: row.id,
807
+ content,
808
+ role: row.role,
809
+ createdAt: formatDateForMongoDB(row.createdAt),
810
+ threadId: row.thread_id,
811
+ resourceId: row.resourceId
812
+ };
813
+ if (row.type && row.type !== "v2") result.type = row.type;
814
+ return result;
815
+ }
816
+ async _getIncludedMessages({
817
+ threadId,
818
+ selectBy
819
+ }) {
820
+ const include = selectBy?.include;
821
+ if (!include) return null;
822
+ const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
823
+ const includedMessages = [];
824
+ for (const inc of include) {
825
+ const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
826
+ const searchThreadId = inc.threadId || threadId;
827
+ const allMessages = await collection.find({ thread_id: searchThreadId }).sort({ createdAt: 1 }).toArray();
828
+ const targetIndex = allMessages.findIndex((msg) => msg.id === id);
829
+ if (targetIndex === -1) continue;
830
+ const startIndex = Math.max(0, targetIndex - withPreviousMessages);
831
+ const endIndex = Math.min(allMessages.length - 1, targetIndex + withNextMessages);
832
+ for (let i = startIndex; i <= endIndex; i++) {
833
+ includedMessages.push(allMessages[i]);
834
+ }
835
+ }
836
+ const seen = /* @__PURE__ */ new Set();
837
+ const dedupedMessages = includedMessages.filter((msg) => {
838
+ if (seen.has(msg.id)) return false;
839
+ seen.add(msg.id);
840
+ return true;
841
+ });
842
+ return dedupedMessages.map((row) => this.parseRow(row));
843
+ }
844
+ async getMessages({
845
+ threadId,
846
+ selectBy,
847
+ format
848
+ }) {
677
849
  try {
678
- const collection = await this.getCollection(tableName);
679
- return await collection.find(keys).toArray();
850
+ const messages = [];
851
+ const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
852
+ if (selectBy?.include?.length) {
853
+ const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
854
+ if (includeMessages) {
855
+ messages.push(...includeMessages);
856
+ }
857
+ }
858
+ const excludeIds = messages.map((m) => m.id);
859
+ const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
860
+ const query = { thread_id: threadId };
861
+ if (excludeIds.length > 0) {
862
+ query.id = { $nin: excludeIds };
863
+ }
864
+ if (limit > 0) {
865
+ const remainingMessages = await collection.find(query).sort({ createdAt: -1 }).limit(limit).toArray();
866
+ messages.push(...remainingMessages.map((row) => this.parseRow(row)));
867
+ }
868
+ messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
869
+ const list = new agent.MessageList().add(messages, "memory");
870
+ if (format === "v2") return list.get.all.v2();
871
+ return list.get.all.v1();
680
872
  } catch (error$1) {
681
873
  throw new error.MastraError(
682
874
  {
683
- id: "STORAGE_MONGODB_STORE_LOAD_FAILED",
875
+ id: "MONGODB_STORE_GET_MESSAGES_FAILED",
684
876
  domain: error.ErrorDomain.STORAGE,
685
877
  category: error.ErrorCategory.THIRD_PARTY,
686
- details: { tableName }
878
+ details: { threadId }
687
879
  },
688
880
  error$1
689
881
  );
690
882
  }
691
883
  }
692
- async getThreadById({ threadId }) {
884
+ async getMessagesPaginated(args) {
885
+ const { threadId, format, selectBy } = args;
886
+ const { page = 0, perPage: perPageInput, dateRange } = selectBy?.pagination || {};
887
+ const perPage = perPageInput !== void 0 ? perPageInput : storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
888
+ const fromDate = dateRange?.start;
889
+ const toDate = dateRange?.end;
890
+ const messages = [];
891
+ if (selectBy?.include?.length) {
892
+ try {
893
+ const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
894
+ if (includeMessages) {
895
+ messages.push(...includeMessages);
896
+ }
897
+ } catch (error$1) {
898
+ throw new error.MastraError(
899
+ {
900
+ id: "MONGODB_STORE_GET_MESSAGES_PAGINATED_GET_INCLUDE_MESSAGES_FAILED",
901
+ domain: error.ErrorDomain.STORAGE,
902
+ category: error.ErrorCategory.THIRD_PARTY,
903
+ details: { threadId }
904
+ },
905
+ error$1
906
+ );
907
+ }
908
+ }
693
909
  try {
694
- const collection = await this.getCollection(storage.TABLE_THREADS);
695
- const result = await collection.findOne({ id: threadId });
696
- if (!result) {
697
- return null;
910
+ const currentOffset = page * perPage;
911
+ const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
912
+ const query = { thread_id: threadId };
913
+ if (fromDate) {
914
+ query.createdAt = { ...query.createdAt, $gte: fromDate };
915
+ }
916
+ if (toDate) {
917
+ query.createdAt = { ...query.createdAt, $lte: toDate };
698
918
  }
919
+ const total = await collection.countDocuments(query);
920
+ if (total === 0 && messages.length === 0) {
921
+ return {
922
+ messages: [],
923
+ total: 0,
924
+ page,
925
+ perPage,
926
+ hasMore: false
927
+ };
928
+ }
929
+ const excludeIds = messages.map((m) => m.id);
930
+ if (excludeIds.length > 0) {
931
+ query.id = { $nin: excludeIds };
932
+ }
933
+ const dataResult = await collection.find(query).sort({ createdAt: -1 }).skip(currentOffset).limit(perPage).toArray();
934
+ messages.push(...dataResult.map((row) => this.parseRow(row)));
935
+ const messagesToReturn = format === "v1" ? new agent.MessageList().add(messages, "memory").get.all.v1() : new agent.MessageList().add(messages, "memory").get.all.v2();
699
936
  return {
700
- ...result,
701
- metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
937
+ messages: messagesToReturn,
938
+ total,
939
+ page,
940
+ perPage,
941
+ hasMore: (page + 1) * perPage < total
702
942
  };
703
943
  } catch (error$1) {
704
- throw new error.MastraError(
944
+ const mastraError = new error.MastraError(
705
945
  {
706
- id: "STORAGE_MONGODB_STORE_GET_THREAD_BY_ID_FAILED",
946
+ id: "MONGODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
707
947
  domain: error.ErrorDomain.STORAGE,
708
948
  category: error.ErrorCategory.THIRD_PARTY,
709
949
  details: { threadId }
710
950
  },
711
951
  error$1
712
952
  );
953
+ this.logger?.trackException?.(mastraError);
954
+ this.logger?.error?.(mastraError.toString());
955
+ return { messages: [], total: 0, page, perPage, hasMore: false };
713
956
  }
714
957
  }
715
- async getThreadsByResourceId({ resourceId }) {
958
+ async saveMessages({
959
+ messages,
960
+ format
961
+ }) {
962
+ if (messages.length === 0) return messages;
716
963
  try {
717
- const collection = await this.getCollection(storage.TABLE_THREADS);
718
- const results = await collection.find({ resourceId }).toArray();
719
- if (!results.length) {
720
- return [];
964
+ const threadId = messages[0]?.threadId;
965
+ if (!threadId) {
966
+ throw new Error("Thread ID is required");
721
967
  }
722
- return results.map((result) => ({
723
- ...result,
724
- metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
725
- }));
968
+ const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
969
+ const threadsCollection = await this.operations.getCollection(storage.TABLE_THREADS);
970
+ const messagesToInsert = messages.map((message) => {
971
+ const time = message.createdAt || /* @__PURE__ */ new Date();
972
+ if (!message.threadId) {
973
+ throw new Error(
974
+ "Expected to find a threadId for message, but couldn't find one. An unexpected error has occurred."
975
+ );
976
+ }
977
+ if (!message.resourceId) {
978
+ throw new Error(
979
+ "Expected to find a resourceId for message, but couldn't find one. An unexpected error has occurred."
980
+ );
981
+ }
982
+ return {
983
+ updateOne: {
984
+ filter: { id: message.id },
985
+ update: {
986
+ $set: {
987
+ id: message.id,
988
+ thread_id: message.threadId,
989
+ content: typeof message.content === "object" ? JSON.stringify(message.content) : message.content,
990
+ role: message.role,
991
+ type: message.type || "v2",
992
+ createdAt: formatDateForMongoDB(time),
993
+ resourceId: message.resourceId
994
+ }
995
+ },
996
+ upsert: true
997
+ }
998
+ };
999
+ });
1000
+ await Promise.all([
1001
+ collection.bulkWrite(messagesToInsert),
1002
+ threadsCollection.updateOne({ id: threadId }, { $set: { updatedAt: /* @__PURE__ */ new Date() } })
1003
+ ]);
1004
+ const list = new agent.MessageList().add(messages, "memory");
1005
+ if (format === "v2") return list.get.all.v2();
1006
+ return list.get.all.v1();
726
1007
  } catch (error$1) {
727
1008
  throw new error.MastraError(
728
1009
  {
729
- id: "STORAGE_MONGODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
1010
+ id: "MONGODB_STORE_SAVE_MESSAGES_FAILED",
730
1011
  domain: error.ErrorDomain.STORAGE,
731
- category: error.ErrorCategory.THIRD_PARTY,
732
- details: { resourceId }
1012
+ category: error.ErrorCategory.THIRD_PARTY
733
1013
  },
734
1014
  error$1
735
1015
  );
736
1016
  }
737
1017
  }
738
- async saveThread({ thread }) {
739
- try {
740
- const collection = await this.getCollection(storage.TABLE_THREADS);
741
- await collection.updateOne(
1018
+ async updateMessages({
1019
+ messages
1020
+ }) {
1021
+ if (messages.length === 0) {
1022
+ return [];
1023
+ }
1024
+ const messageIds = messages.map((m) => m.id);
1025
+ const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
1026
+ const existingMessages = await collection.find({ id: { $in: messageIds } }).toArray();
1027
+ const existingMessagesParsed = existingMessages.map((msg) => this.parseRow(msg));
1028
+ if (existingMessagesParsed.length === 0) {
1029
+ return [];
1030
+ }
1031
+ const threadIdsToUpdate = /* @__PURE__ */ new Set();
1032
+ const bulkOps = [];
1033
+ for (const existingMessage of existingMessagesParsed) {
1034
+ const updatePayload = messages.find((m) => m.id === existingMessage.id);
1035
+ if (!updatePayload) continue;
1036
+ const { id, ...fieldsToUpdate } = updatePayload;
1037
+ if (Object.keys(fieldsToUpdate).length === 0) continue;
1038
+ threadIdsToUpdate.add(existingMessage.threadId);
1039
+ if (updatePayload.threadId && updatePayload.threadId !== existingMessage.threadId) {
1040
+ threadIdsToUpdate.add(updatePayload.threadId);
1041
+ }
1042
+ const updateDoc = {};
1043
+ const updatableFields = { ...fieldsToUpdate };
1044
+ if (updatableFields.content) {
1045
+ const newContent = {
1046
+ ...existingMessage.content,
1047
+ ...updatableFields.content,
1048
+ // Deep merge metadata if it exists on both
1049
+ ...existingMessage.content?.metadata && updatableFields.content.metadata ? {
1050
+ metadata: {
1051
+ ...existingMessage.content.metadata,
1052
+ ...updatableFields.content.metadata
1053
+ }
1054
+ } : {}
1055
+ };
1056
+ updateDoc.content = JSON.stringify(newContent);
1057
+ delete updatableFields.content;
1058
+ }
1059
+ for (const key in updatableFields) {
1060
+ if (Object.prototype.hasOwnProperty.call(updatableFields, key)) {
1061
+ const dbKey = key === "threadId" ? "thread_id" : key;
1062
+ let value = updatableFields[key];
1063
+ if (typeof value === "object" && value !== null) {
1064
+ value = JSON.stringify(value);
1065
+ }
1066
+ updateDoc[dbKey] = value;
1067
+ }
1068
+ }
1069
+ if (Object.keys(updateDoc).length > 0) {
1070
+ bulkOps.push({
1071
+ updateOne: {
1072
+ filter: { id },
1073
+ update: { $set: updateDoc }
1074
+ }
1075
+ });
1076
+ }
1077
+ }
1078
+ if (bulkOps.length > 0) {
1079
+ await collection.bulkWrite(bulkOps);
1080
+ }
1081
+ if (threadIdsToUpdate.size > 0) {
1082
+ const threadsCollection = await this.operations.getCollection(storage.TABLE_THREADS);
1083
+ await threadsCollection.updateMany(
1084
+ { id: { $in: Array.from(threadIdsToUpdate) } },
1085
+ { $set: { updatedAt: /* @__PURE__ */ new Date() } }
1086
+ );
1087
+ }
1088
+ const updatedMessages = await collection.find({ id: { $in: messageIds } }).toArray();
1089
+ return updatedMessages.map((row) => this.parseRow(row));
1090
+ }
1091
+ async getResourceById({ resourceId }) {
1092
+ try {
1093
+ const collection = await this.operations.getCollection(storage.TABLE_RESOURCES);
1094
+ const result = await collection.findOne({ id: resourceId });
1095
+ if (!result) {
1096
+ return null;
1097
+ }
1098
+ return {
1099
+ id: result.id,
1100
+ workingMemory: result.workingMemory || "",
1101
+ metadata: typeof result.metadata === "string" ? storage.safelyParseJSON(result.metadata) : result.metadata,
1102
+ createdAt: formatDateForMongoDB(result.createdAt),
1103
+ updatedAt: formatDateForMongoDB(result.updatedAt)
1104
+ };
1105
+ } catch (error$1) {
1106
+ throw new error.MastraError(
1107
+ {
1108
+ id: "STORAGE_MONGODB_STORE_GET_RESOURCE_BY_ID_FAILED",
1109
+ domain: error.ErrorDomain.STORAGE,
1110
+ category: error.ErrorCategory.THIRD_PARTY,
1111
+ details: { resourceId }
1112
+ },
1113
+ error$1
1114
+ );
1115
+ }
1116
+ }
1117
+ async saveResource({ resource }) {
1118
+ try {
1119
+ const collection = await this.operations.getCollection(storage.TABLE_RESOURCES);
1120
+ await collection.updateOne(
1121
+ { id: resource.id },
1122
+ {
1123
+ $set: {
1124
+ ...resource,
1125
+ metadata: JSON.stringify(resource.metadata)
1126
+ }
1127
+ },
1128
+ { upsert: true }
1129
+ );
1130
+ return resource;
1131
+ } catch (error$1) {
1132
+ throw new error.MastraError(
1133
+ {
1134
+ id: "STORAGE_MONGODB_STORE_SAVE_RESOURCE_FAILED",
1135
+ domain: error.ErrorDomain.STORAGE,
1136
+ category: error.ErrorCategory.THIRD_PARTY,
1137
+ details: { resourceId: resource.id }
1138
+ },
1139
+ error$1
1140
+ );
1141
+ }
1142
+ }
1143
+ async updateResource({
1144
+ resourceId,
1145
+ workingMemory,
1146
+ metadata
1147
+ }) {
1148
+ try {
1149
+ const existingResource = await this.getResourceById({ resourceId });
1150
+ if (!existingResource) {
1151
+ const newResource = {
1152
+ id: resourceId,
1153
+ workingMemory: workingMemory || "",
1154
+ metadata: metadata || {},
1155
+ createdAt: /* @__PURE__ */ new Date(),
1156
+ updatedAt: /* @__PURE__ */ new Date()
1157
+ };
1158
+ return this.saveResource({ resource: newResource });
1159
+ }
1160
+ const updatedResource = {
1161
+ ...existingResource,
1162
+ workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
1163
+ metadata: metadata ? { ...existingResource.metadata, ...metadata } : existingResource.metadata,
1164
+ updatedAt: /* @__PURE__ */ new Date()
1165
+ };
1166
+ const collection = await this.operations.getCollection(storage.TABLE_RESOURCES);
1167
+ const updateDoc = { updatedAt: updatedResource.updatedAt };
1168
+ if (workingMemory !== void 0) {
1169
+ updateDoc.workingMemory = workingMemory;
1170
+ }
1171
+ if (metadata) {
1172
+ updateDoc.metadata = JSON.stringify(updatedResource.metadata);
1173
+ }
1174
+ await collection.updateOne({ id: resourceId }, { $set: updateDoc });
1175
+ return updatedResource;
1176
+ } catch (error$1) {
1177
+ throw new error.MastraError(
1178
+ {
1179
+ id: "STORAGE_MONGODB_STORE_UPDATE_RESOURCE_FAILED",
1180
+ domain: error.ErrorDomain.STORAGE,
1181
+ category: error.ErrorCategory.THIRD_PARTY,
1182
+ details: { resourceId }
1183
+ },
1184
+ error$1
1185
+ );
1186
+ }
1187
+ }
1188
+ async getThreadById({ threadId }) {
1189
+ try {
1190
+ const collection = await this.operations.getCollection(storage.TABLE_THREADS);
1191
+ const result = await collection.findOne({ id: threadId });
1192
+ if (!result) {
1193
+ return null;
1194
+ }
1195
+ return {
1196
+ ...result,
1197
+ metadata: typeof result.metadata === "string" ? storage.safelyParseJSON(result.metadata) : result.metadata
1198
+ };
1199
+ } catch (error$1) {
1200
+ throw new error.MastraError(
1201
+ {
1202
+ id: "STORAGE_MONGODB_STORE_GET_THREAD_BY_ID_FAILED",
1203
+ domain: error.ErrorDomain.STORAGE,
1204
+ category: error.ErrorCategory.THIRD_PARTY,
1205
+ details: { threadId }
1206
+ },
1207
+ error$1
1208
+ );
1209
+ }
1210
+ }
1211
+ async getThreadsByResourceId({ resourceId }) {
1212
+ try {
1213
+ const collection = await this.operations.getCollection(storage.TABLE_THREADS);
1214
+ const results = await collection.find({ resourceId }).toArray();
1215
+ if (!results.length) {
1216
+ return [];
1217
+ }
1218
+ return results.map((result) => ({
1219
+ ...result,
1220
+ metadata: typeof result.metadata === "string" ? storage.safelyParseJSON(result.metadata) : result.metadata
1221
+ }));
1222
+ } catch (error$1) {
1223
+ throw new error.MastraError(
1224
+ {
1225
+ id: "STORAGE_MONGODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
1226
+ domain: error.ErrorDomain.STORAGE,
1227
+ category: error.ErrorCategory.THIRD_PARTY,
1228
+ details: { resourceId }
1229
+ },
1230
+ error$1
1231
+ );
1232
+ }
1233
+ }
1234
+ async getThreadsByResourceIdPaginated(args) {
1235
+ try {
1236
+ const { resourceId, page, perPage } = args;
1237
+ const collection = await this.operations.getCollection(storage.TABLE_THREADS);
1238
+ const query = { resourceId };
1239
+ const total = await collection.countDocuments(query);
1240
+ const threads = await collection.find(query).sort({ updatedAt: -1 }).skip(page * perPage).limit(perPage).toArray();
1241
+ return {
1242
+ threads: threads.map((thread) => ({
1243
+ id: thread.id,
1244
+ title: thread.title,
1245
+ resourceId: thread.resourceId,
1246
+ createdAt: formatDateForMongoDB(thread.createdAt),
1247
+ updatedAt: formatDateForMongoDB(thread.updatedAt),
1248
+ metadata: thread.metadata || {}
1249
+ })),
1250
+ total,
1251
+ page,
1252
+ perPage,
1253
+ hasMore: (page + 1) * perPage < total
1254
+ };
1255
+ } catch (error$1) {
1256
+ throw new error.MastraError(
1257
+ {
1258
+ id: "MONGODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1259
+ domain: error.ErrorDomain.STORAGE,
1260
+ category: error.ErrorCategory.THIRD_PARTY,
1261
+ details: { resourceId: args.resourceId }
1262
+ },
1263
+ error$1
1264
+ );
1265
+ }
1266
+ }
1267
+ async saveThread({ thread }) {
1268
+ try {
1269
+ const collection = await this.operations.getCollection(storage.TABLE_THREADS);
1270
+ await collection.updateOne(
742
1271
  { id: thread.id },
743
1272
  {
744
1273
  $set: {
745
1274
  ...thread,
746
- metadata: JSON.stringify(thread.metadata)
1275
+ metadata: thread.metadata
747
1276
  }
748
1277
  },
749
1278
  { upsert: true }
@@ -772,7 +1301,7 @@ var MongoDBStore = class extends storage.MastraStorage {
772
1301
  id: "STORAGE_MONGODB_STORE_UPDATE_THREAD_NOT_FOUND",
773
1302
  domain: error.ErrorDomain.STORAGE,
774
1303
  category: error.ErrorCategory.THIRD_PARTY,
775
- details: { threadId: id },
1304
+ details: { threadId: id, status: 404 },
776
1305
  text: `Thread ${id} not found`
777
1306
  });
778
1307
  }
@@ -785,13 +1314,13 @@ var MongoDBStore = class extends storage.MastraStorage {
785
1314
  }
786
1315
  };
787
1316
  try {
788
- const collection = await this.getCollection(storage.TABLE_THREADS);
1317
+ const collection = await this.operations.getCollection(storage.TABLE_THREADS);
789
1318
  await collection.updateOne(
790
1319
  { id },
791
1320
  {
792
1321
  $set: {
793
1322
  title,
794
- metadata: JSON.stringify(updatedThread.metadata)
1323
+ metadata: updatedThread.metadata
795
1324
  }
796
1325
  }
797
1326
  );
@@ -810,9 +1339,9 @@ var MongoDBStore = class extends storage.MastraStorage {
810
1339
  }
811
1340
  async deleteThread({ threadId }) {
812
1341
  try {
813
- const collectionMessages = await this.getCollection(storage.TABLE_MESSAGES);
1342
+ const collectionMessages = await this.operations.getCollection(storage.TABLE_MESSAGES);
814
1343
  await collectionMessages.deleteMany({ thread_id: threadId });
815
- const collectionThreads = await this.getCollection(storage.TABLE_THREADS);
1344
+ const collectionThreads = await this.operations.getCollection(storage.TABLE_THREADS);
816
1345
  await collectionThreads.deleteOne({ id: threadId });
817
1346
  } catch (error$1) {
818
1347
  throw new error.MastraError(
@@ -826,124 +1355,461 @@ var MongoDBStore = class extends storage.MastraStorage {
826
1355
  );
827
1356
  }
828
1357
  }
829
- async getMessages({
830
- threadId,
831
- selectBy,
832
- format
833
- }) {
1358
+ };
1359
+ var StoreOperationsMongoDB = class extends storage.StoreOperations {
1360
+ #connector;
1361
+ constructor(config) {
1362
+ super();
1363
+ this.#connector = config.connector;
1364
+ }
1365
+ async getCollection(collectionName) {
1366
+ return this.#connector.getCollection(collectionName);
1367
+ }
1368
+ async hasColumn(_table, _column) {
1369
+ return true;
1370
+ }
1371
+ async createTable() {
1372
+ }
1373
+ async alterTable(_args) {
1374
+ }
1375
+ async clearTable({ tableName }) {
1376
+ try {
1377
+ const collection = await this.getCollection(tableName);
1378
+ await collection.deleteMany({});
1379
+ } catch (error$1) {
1380
+ if (error$1 instanceof Error) {
1381
+ const matstraError = new error.MastraError(
1382
+ {
1383
+ id: "STORAGE_MONGODB_STORE_CLEAR_TABLE_FAILED",
1384
+ domain: error.ErrorDomain.STORAGE,
1385
+ category: error.ErrorCategory.THIRD_PARTY,
1386
+ details: { tableName }
1387
+ },
1388
+ error$1
1389
+ );
1390
+ this.logger.error(matstraError.message);
1391
+ this.logger?.trackException(matstraError);
1392
+ }
1393
+ }
1394
+ }
1395
+ async dropTable({ tableName }) {
834
1396
  try {
835
- const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
836
- const include = selectBy?.include || [];
837
- let messages = [];
838
- let allMessages = [];
839
- const collection = await this.getCollection(storage.TABLE_MESSAGES);
840
- allMessages = (await collection.find({ thread_id: threadId }).sort({ createdAt: -1 }).toArray()).map(
841
- (row) => this.parseRow(row)
1397
+ const collection = await this.getCollection(tableName);
1398
+ await collection.drop();
1399
+ } catch (error$1) {
1400
+ if (error$1 instanceof Error && error$1.message.includes("ns not found")) {
1401
+ return;
1402
+ }
1403
+ throw new error.MastraError(
1404
+ {
1405
+ id: "MONGODB_STORE_DROP_TABLE_FAILED",
1406
+ domain: error.ErrorDomain.STORAGE,
1407
+ category: error.ErrorCategory.THIRD_PARTY,
1408
+ details: { tableName }
1409
+ },
1410
+ error$1
842
1411
  );
843
- if (include.length) {
844
- const idToIndex = /* @__PURE__ */ new Map();
845
- allMessages.forEach((msg, idx) => {
846
- idToIndex.set(msg.id, idx);
847
- });
848
- const selectedIndexes = /* @__PURE__ */ new Set();
849
- for (const inc of include) {
850
- const idx = idToIndex.get(inc.id);
851
- if (idx === void 0) continue;
852
- for (let i = 1; i <= (inc.withPreviousMessages || 0); i++) {
853
- if (idx + i < allMessages.length) selectedIndexes.add(idx + i);
854
- }
855
- selectedIndexes.add(idx);
856
- for (let i = 1; i <= (inc.withNextMessages || 0); i++) {
857
- if (idx - i >= 0) selectedIndexes.add(idx - i);
1412
+ }
1413
+ }
1414
+ async insert({ tableName, record }) {
1415
+ try {
1416
+ const collection = await this.getCollection(tableName);
1417
+ const schema = storage.TABLE_SCHEMAS[tableName];
1418
+ const recordToInsert = Object.fromEntries(
1419
+ Object.entries(schema).map(([key, value]) => {
1420
+ if (value.type === "jsonb" && record[key] && typeof record[key] === "string") {
1421
+ return [key, storage.safelyParseJSON(record[key])];
858
1422
  }
859
- }
860
- messages.push(
861
- ...Array.from(selectedIndexes).map((i) => allMessages[i]).filter((m) => !!m)
1423
+ return [key, record[key]];
1424
+ })
1425
+ );
1426
+ await collection.insertOne(recordToInsert);
1427
+ } catch (error$1) {
1428
+ if (error$1 instanceof Error) {
1429
+ const matstraError = new error.MastraError(
1430
+ {
1431
+ id: "STORAGE_MONGODB_STORE_INSERT_FAILED",
1432
+ domain: error.ErrorDomain.STORAGE,
1433
+ category: error.ErrorCategory.THIRD_PARTY,
1434
+ details: { tableName }
1435
+ },
1436
+ error$1
862
1437
  );
1438
+ this.logger.error(matstraError.message);
1439
+ this.logger?.trackException(matstraError);
1440
+ }
1441
+ }
1442
+ }
1443
+ async batchInsert({ tableName, records }) {
1444
+ if (!records.length) {
1445
+ return;
1446
+ }
1447
+ try {
1448
+ const collection = await this.getCollection(tableName);
1449
+ await collection.insertMany(records);
1450
+ } catch (error$1) {
1451
+ throw new error.MastraError(
1452
+ {
1453
+ id: "STORAGE_MONGODB_STORE_BATCH_INSERT_FAILED",
1454
+ domain: error.ErrorDomain.STORAGE,
1455
+ category: error.ErrorCategory.THIRD_PARTY,
1456
+ details: { tableName }
1457
+ },
1458
+ error$1
1459
+ );
1460
+ }
1461
+ }
1462
+ async load({ tableName, keys }) {
1463
+ this.logger.info(`Loading ${tableName} with keys ${JSON.stringify(keys)}`);
1464
+ try {
1465
+ const collection = await this.getCollection(tableName);
1466
+ return await collection.find(keys).toArray();
1467
+ } catch (error$1) {
1468
+ throw new error.MastraError(
1469
+ {
1470
+ id: "STORAGE_MONGODB_STORE_LOAD_FAILED",
1471
+ domain: error.ErrorDomain.STORAGE,
1472
+ category: error.ErrorCategory.THIRD_PARTY,
1473
+ details: { tableName }
1474
+ },
1475
+ error$1
1476
+ );
1477
+ }
1478
+ }
1479
+ };
1480
+ function transformScoreRow(row) {
1481
+ let scorerValue = null;
1482
+ if (row.scorer) {
1483
+ try {
1484
+ scorerValue = typeof row.scorer === "string" ? storage.safelyParseJSON(row.scorer) : row.scorer;
1485
+ } catch (e) {
1486
+ console.warn("Failed to parse scorer:", e);
1487
+ }
1488
+ }
1489
+ let extractStepResultValue = null;
1490
+ if (row.extractStepResult) {
1491
+ try {
1492
+ extractStepResultValue = typeof row.extractStepResult === "string" ? storage.safelyParseJSON(row.extractStepResult) : row.extractStepResult;
1493
+ } catch (e) {
1494
+ console.warn("Failed to parse extractStepResult:", e);
1495
+ }
1496
+ }
1497
+ let analyzeStepResultValue = null;
1498
+ if (row.analyzeStepResult) {
1499
+ try {
1500
+ analyzeStepResultValue = typeof row.analyzeStepResult === "string" ? storage.safelyParseJSON(row.analyzeStepResult) : row.analyzeStepResult;
1501
+ } catch (e) {
1502
+ console.warn("Failed to parse analyzeStepResult:", e);
1503
+ }
1504
+ }
1505
+ let inputValue = null;
1506
+ if (row.input) {
1507
+ try {
1508
+ inputValue = typeof row.input === "string" ? storage.safelyParseJSON(row.input) : row.input;
1509
+ } catch (e) {
1510
+ console.warn("Failed to parse input:", e);
1511
+ }
1512
+ }
1513
+ let outputValue = null;
1514
+ if (row.output) {
1515
+ try {
1516
+ outputValue = typeof row.output === "string" ? storage.safelyParseJSON(row.output) : row.output;
1517
+ } catch (e) {
1518
+ console.warn("Failed to parse output:", e);
1519
+ }
1520
+ }
1521
+ let entityValue = null;
1522
+ if (row.entity) {
1523
+ try {
1524
+ entityValue = typeof row.entity === "string" ? storage.safelyParseJSON(row.entity) : row.entity;
1525
+ } catch (e) {
1526
+ console.warn("Failed to parse entity:", e);
1527
+ }
1528
+ }
1529
+ let runtimeContextValue = null;
1530
+ if (row.runtimeContext) {
1531
+ try {
1532
+ runtimeContextValue = typeof row.runtimeContext === "string" ? storage.safelyParseJSON(row.runtimeContext) : row.runtimeContext;
1533
+ } catch (e) {
1534
+ console.warn("Failed to parse runtimeContext:", e);
1535
+ }
1536
+ }
1537
+ return {
1538
+ id: row.id,
1539
+ entityId: row.entityId,
1540
+ entityType: row.entityType,
1541
+ scorerId: row.scorerId,
1542
+ traceId: row.traceId,
1543
+ runId: row.runId,
1544
+ scorer: scorerValue,
1545
+ extractStepResult: extractStepResultValue,
1546
+ analyzeStepResult: analyzeStepResultValue,
1547
+ score: row.score,
1548
+ reason: row.reason,
1549
+ extractPrompt: row.extractPrompt,
1550
+ analyzePrompt: row.analyzePrompt,
1551
+ reasonPrompt: row.reasonPrompt,
1552
+ input: inputValue,
1553
+ output: outputValue,
1554
+ additionalContext: row.additionalContext,
1555
+ runtimeContext: runtimeContextValue,
1556
+ entity: entityValue,
1557
+ source: row.source,
1558
+ resourceId: row.resourceId,
1559
+ threadId: row.threadId,
1560
+ createdAt: new Date(row.createdAt),
1561
+ updatedAt: new Date(row.updatedAt)
1562
+ };
1563
+ }
1564
+ var ScoresStorageMongoDB = class extends storage.ScoresStorage {
1565
+ operations;
1566
+ constructor({ operations }) {
1567
+ super();
1568
+ this.operations = operations;
1569
+ }
1570
+ async getScoreById({ id }) {
1571
+ try {
1572
+ const collection = await this.operations.getCollection(storage.TABLE_SCORERS);
1573
+ const document = await collection.findOne({ id });
1574
+ if (!document) {
1575
+ return null;
863
1576
  }
864
- const excludeIds = new Set(messages.map((m) => m.id));
865
- for (const msg of allMessages) {
866
- if (messages.length >= limit) break;
867
- if (!excludeIds.has(msg.id)) {
868
- messages.push(msg);
1577
+ return transformScoreRow(document);
1578
+ } catch (error$1) {
1579
+ throw new error.MastraError(
1580
+ {
1581
+ id: "STORAGE_MONGODB_STORE_GET_SCORE_BY_ID_FAILED",
1582
+ domain: error.ErrorDomain.STORAGE,
1583
+ category: error.ErrorCategory.THIRD_PARTY,
1584
+ details: { id }
1585
+ },
1586
+ error$1
1587
+ );
1588
+ }
1589
+ }
1590
+ async saveScore(score) {
1591
+ try {
1592
+ const now = /* @__PURE__ */ new Date();
1593
+ const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1594
+ const scoreData = {
1595
+ id: scoreId,
1596
+ entityId: score.entityId,
1597
+ entityType: score.entityType,
1598
+ scorerId: score.scorerId,
1599
+ traceId: score.traceId || "",
1600
+ runId: score.runId,
1601
+ scorer: typeof score.scorer === "string" ? score.scorer : JSON.stringify(score.scorer),
1602
+ extractStepResult: typeof score.extractStepResult === "string" ? score.extractStepResult : JSON.stringify(score.extractStepResult),
1603
+ analyzeStepResult: typeof score.analyzeStepResult === "string" ? score.analyzeStepResult : JSON.stringify(score.analyzeStepResult),
1604
+ score: score.score,
1605
+ reason: score.reason,
1606
+ extractPrompt: score.extractPrompt,
1607
+ analyzePrompt: score.analyzePrompt,
1608
+ reasonPrompt: score.reasonPrompt,
1609
+ input: typeof score.input === "string" ? score.input : JSON.stringify(score.input),
1610
+ output: typeof score.output === "string" ? score.output : JSON.stringify(score.output),
1611
+ additionalContext: score.additionalContext,
1612
+ runtimeContext: typeof score.runtimeContext === "string" ? score.runtimeContext : JSON.stringify(score.runtimeContext),
1613
+ entity: typeof score.entity === "string" ? score.entity : JSON.stringify(score.entity),
1614
+ source: score.source,
1615
+ resourceId: score.resourceId || "",
1616
+ threadId: score.threadId || "",
1617
+ createdAt: now,
1618
+ updatedAt: now
1619
+ };
1620
+ const collection = await this.operations.getCollection(storage.TABLE_SCORERS);
1621
+ await collection.insertOne(scoreData);
1622
+ const savedScore = {
1623
+ ...score,
1624
+ id: scoreId,
1625
+ createdAt: now,
1626
+ updatedAt: now
1627
+ };
1628
+ return { score: savedScore };
1629
+ } catch (error$1) {
1630
+ throw new error.MastraError(
1631
+ {
1632
+ id: "STORAGE_MONGODB_STORE_SAVE_SCORE_FAILED",
1633
+ domain: error.ErrorDomain.STORAGE,
1634
+ category: error.ErrorCategory.THIRD_PARTY,
1635
+ details: { scorerId: score.scorerId, runId: score.runId }
1636
+ },
1637
+ error$1
1638
+ );
1639
+ }
1640
+ }
1641
+ async getScoresByScorerId({
1642
+ scorerId,
1643
+ pagination,
1644
+ entityId,
1645
+ entityType
1646
+ }) {
1647
+ try {
1648
+ const query = { scorerId };
1649
+ if (entityId) {
1650
+ query.entityId = entityId;
1651
+ }
1652
+ if (entityType) {
1653
+ query.entityType = entityType;
1654
+ }
1655
+ const collection = await this.operations.getCollection(storage.TABLE_SCORERS);
1656
+ const total = await collection.countDocuments(query);
1657
+ const currentOffset = pagination.page * pagination.perPage;
1658
+ if (total === 0) {
1659
+ return {
1660
+ scores: [],
1661
+ pagination: {
1662
+ total: 0,
1663
+ page: pagination.page,
1664
+ perPage: pagination.perPage,
1665
+ hasMore: false
1666
+ }
1667
+ };
1668
+ }
1669
+ const documents = await collection.find(query).sort({ createdAt: "desc" }).skip(currentOffset).limit(pagination.perPage).toArray();
1670
+ const scores = documents.map((row) => transformScoreRow(row));
1671
+ const hasMore = currentOffset + scores.length < total;
1672
+ return {
1673
+ scores,
1674
+ pagination: {
1675
+ total,
1676
+ page: pagination.page,
1677
+ perPage: pagination.perPage,
1678
+ hasMore
869
1679
  }
1680
+ };
1681
+ } catch (error$1) {
1682
+ throw new error.MastraError(
1683
+ {
1684
+ id: "STORAGE_MONGODB_STORE_GET_SCORES_BY_SCORER_ID_FAILED",
1685
+ domain: error.ErrorDomain.STORAGE,
1686
+ category: error.ErrorCategory.THIRD_PARTY,
1687
+ details: { scorerId, page: pagination.page, perPage: pagination.perPage }
1688
+ },
1689
+ error$1
1690
+ );
1691
+ }
1692
+ }
1693
+ async getScoresByRunId({
1694
+ runId,
1695
+ pagination
1696
+ }) {
1697
+ try {
1698
+ const collection = await this.operations.getCollection(storage.TABLE_SCORERS);
1699
+ const total = await collection.countDocuments({ runId });
1700
+ const currentOffset = pagination.page * pagination.perPage;
1701
+ if (total === 0) {
1702
+ return {
1703
+ scores: [],
1704
+ pagination: {
1705
+ total: 0,
1706
+ page: pagination.page,
1707
+ perPage: pagination.perPage,
1708
+ hasMore: false
1709
+ }
1710
+ };
870
1711
  }
871
- messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
872
- const list = new agent.MessageList().add(messages.slice(0, limit), "memory");
873
- if (format === `v2`) return list.get.all.v2();
874
- return list.get.all.v1();
1712
+ const documents = await collection.find({ runId }).sort({ createdAt: "desc" }).skip(currentOffset).limit(pagination.perPage).toArray();
1713
+ const scores = documents.map((row) => transformScoreRow(row));
1714
+ const hasMore = currentOffset + scores.length < total;
1715
+ return {
1716
+ scores,
1717
+ pagination: {
1718
+ total,
1719
+ page: pagination.page,
1720
+ perPage: pagination.perPage,
1721
+ hasMore
1722
+ }
1723
+ };
875
1724
  } catch (error$1) {
876
1725
  throw new error.MastraError(
877
1726
  {
878
- id: "STORAGE_MONGODB_STORE_GET_MESSAGES_FAILED",
1727
+ id: "STORAGE_MONGODB_STORE_GET_SCORES_BY_RUN_ID_FAILED",
879
1728
  domain: error.ErrorDomain.STORAGE,
880
1729
  category: error.ErrorCategory.THIRD_PARTY,
881
- details: { threadId }
1730
+ details: { runId, page: pagination.page, perPage: pagination.perPage }
882
1731
  },
883
1732
  error$1
884
1733
  );
885
1734
  }
886
1735
  }
887
- async saveMessages({
888
- messages,
889
- format
1736
+ async getScoresByEntityId({
1737
+ entityId,
1738
+ entityType,
1739
+ pagination
890
1740
  }) {
891
- if (!messages.length) {
892
- return messages;
1741
+ try {
1742
+ const collection = await this.operations.getCollection(storage.TABLE_SCORERS);
1743
+ const total = await collection.countDocuments({ entityId, entityType });
1744
+ const currentOffset = pagination.page * pagination.perPage;
1745
+ if (total === 0) {
1746
+ return {
1747
+ scores: [],
1748
+ pagination: {
1749
+ total: 0,
1750
+ page: pagination.page,
1751
+ perPage: pagination.perPage,
1752
+ hasMore: false
1753
+ }
1754
+ };
1755
+ }
1756
+ const documents = await collection.find({ entityId, entityType }).sort({ createdAt: "desc" }).skip(currentOffset).limit(pagination.perPage).toArray();
1757
+ const scores = documents.map((row) => transformScoreRow(row));
1758
+ const hasMore = currentOffset + scores.length < total;
1759
+ return {
1760
+ scores,
1761
+ pagination: {
1762
+ total,
1763
+ page: pagination.page,
1764
+ perPage: pagination.perPage,
1765
+ hasMore
1766
+ }
1767
+ };
1768
+ } catch (error$1) {
1769
+ throw new error.MastraError(
1770
+ {
1771
+ id: "STORAGE_MONGODB_STORE_GET_SCORES_BY_ENTITY_ID_FAILED",
1772
+ domain: error.ErrorDomain.STORAGE,
1773
+ category: error.ErrorCategory.THIRD_PARTY,
1774
+ details: { entityId, entityType, page: pagination.page, perPage: pagination.perPage }
1775
+ },
1776
+ error$1
1777
+ );
1778
+ }
1779
+ }
1780
+ };
1781
+ var TracesStorageMongoDB = class extends storage.TracesStorage {
1782
+ operations;
1783
+ constructor({ operations }) {
1784
+ super();
1785
+ this.operations = operations;
1786
+ }
1787
+ async getTraces(args) {
1788
+ if (args.fromDate || args.toDate) {
1789
+ args.dateRange = {
1790
+ start: args.fromDate,
1791
+ end: args.toDate
1792
+ };
893
1793
  }
894
- const threadId = messages[0]?.threadId;
895
- if (!threadId) {
896
- this.logger.error("Thread ID is required to save messages");
897
- throw new Error("Thread ID is required");
1794
+ try {
1795
+ const result = await this.getTracesPaginated(args);
1796
+ return result.traces;
1797
+ } catch (error$1) {
1798
+ throw new error.MastraError(
1799
+ {
1800
+ id: "STORAGE_MONGODB_STORE_GET_TRACES_FAILED",
1801
+ domain: error.ErrorDomain.STORAGE,
1802
+ category: error.ErrorCategory.THIRD_PARTY
1803
+ },
1804
+ error$1
1805
+ );
898
1806
  }
899
- try {
900
- const messagesToInsert = messages.map((message) => {
901
- const time = message.createdAt || /* @__PURE__ */ new Date();
902
- return {
903
- id: message.id,
904
- thread_id: threadId,
905
- content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
906
- role: message.role,
907
- type: message.type,
908
- resourceId: message.resourceId,
909
- createdAt: time instanceof Date ? time.toISOString() : time
910
- };
911
- });
912
- const collection = await this.getCollection(storage.TABLE_MESSAGES);
913
- const threadsCollection = await this.getCollection(storage.TABLE_THREADS);
914
- await Promise.all([
915
- collection.bulkWrite(
916
- messagesToInsert.map((msg) => ({
917
- updateOne: {
918
- filter: { id: msg.id },
919
- update: { $set: msg },
920
- upsert: true
921
- }
922
- }))
923
- ),
924
- threadsCollection.updateOne({ id: threadId }, { $set: { updatedAt: /* @__PURE__ */ new Date() } })
925
- ]);
926
- const list = new agent.MessageList().add(messages, "memory");
927
- if (format === `v2`) return list.get.all.v2();
928
- return list.get.all.v1();
929
- } catch (error) {
930
- this.logger.error("Failed to save messages in database: " + error?.message);
931
- throw error;
932
- }
933
- }
934
- async getTraces({
935
- name,
936
- scope,
937
- page,
938
- perPage,
939
- attributes,
940
- filters
941
- } = {
942
- page: 0,
943
- perPage: 100
944
- }) {
945
- const limit = perPage;
946
- const offset = page * perPage;
1807
+ }
1808
+ async getTracesPaginated(args) {
1809
+ const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
1810
+ const fromDate = dateRange?.start;
1811
+ const toDate = dateRange?.end;
1812
+ const currentOffset = page * perPage;
947
1813
  const query = {};
948
1814
  if (name) {
949
1815
  query["name"] = new RegExp(name);
@@ -953,7 +1819,7 @@ var MongoDBStore = class extends storage.MastraStorage {
953
1819
  }
954
1820
  if (attributes) {
955
1821
  query["$and"] = Object.entries(attributes).map(([key, value]) => ({
956
- attributes: new RegExp(`"${key}":"${value}"`)
1822
+ [`attributes.${key}`]: value
957
1823
  }));
958
1824
  }
959
1825
  if (filters) {
@@ -961,31 +1827,57 @@ var MongoDBStore = class extends storage.MastraStorage {
961
1827
  query[key] = value;
962
1828
  });
963
1829
  }
1830
+ if (fromDate || toDate) {
1831
+ query["createdAt"] = {};
1832
+ if (fromDate) {
1833
+ query["createdAt"]["$gte"] = fromDate;
1834
+ }
1835
+ if (toDate) {
1836
+ query["createdAt"]["$lte"] = toDate;
1837
+ }
1838
+ }
964
1839
  try {
965
- const collection = await this.getCollection(storage.TABLE_TRACES);
1840
+ const collection = await this.operations.getCollection(storage.TABLE_TRACES);
1841
+ const total = await collection.countDocuments(query);
1842
+ if (total === 0) {
1843
+ return {
1844
+ traces: [],
1845
+ total: 0,
1846
+ page,
1847
+ perPage,
1848
+ hasMore: false
1849
+ };
1850
+ }
966
1851
  const result = await collection.find(query, {
967
1852
  sort: { startTime: -1 }
968
- }).limit(limit).skip(offset).toArray();
969
- return result.map((row) => ({
1853
+ }).limit(perPage).skip(currentOffset).toArray();
1854
+ const traces = result.map((row) => ({
970
1855
  id: row.id,
971
1856
  parentSpanId: row.parentSpanId,
972
1857
  traceId: row.traceId,
973
1858
  name: row.name,
974
1859
  scope: row.scope,
975
1860
  kind: row.kind,
976
- status: safelyParseJSON(row.status),
977
- events: safelyParseJSON(row.events),
978
- links: safelyParseJSON(row.links),
979
- attributes: safelyParseJSON(row.attributes),
1861
+ status: storage.safelyParseJSON(row.status),
1862
+ events: storage.safelyParseJSON(row.events),
1863
+ links: storage.safelyParseJSON(row.links),
1864
+ attributes: storage.safelyParseJSON(row.attributes),
980
1865
  startTime: row.startTime,
981
1866
  endTime: row.endTime,
982
- other: safelyParseJSON(row.other),
1867
+ other: storage.safelyParseJSON(row.other),
983
1868
  createdAt: row.createdAt
984
1869
  }));
1870
+ return {
1871
+ traces,
1872
+ total,
1873
+ page,
1874
+ perPage,
1875
+ hasMore: currentOffset + traces.length < total
1876
+ };
985
1877
  } catch (error$1) {
986
1878
  throw new error.MastraError(
987
1879
  {
988
- id: "STORAGE_MONGODB_STORE_GET_TRACES_FAILED",
1880
+ id: "STORAGE_MONGODB_STORE_GET_TRACES_PAGINATED_FAILED",
989
1881
  domain: error.ErrorDomain.STORAGE,
990
1882
  category: error.ErrorCategory.THIRD_PARTY
991
1883
  },
@@ -993,106 +1885,19 @@ var MongoDBStore = class extends storage.MastraStorage {
993
1885
  );
994
1886
  }
995
1887
  }
996
- async getWorkflowRuns({
997
- workflowName,
998
- fromDate,
999
- toDate,
1000
- limit,
1001
- offset
1002
- } = {}) {
1003
- const query = {};
1004
- if (workflowName) {
1005
- query["workflow_name"] = workflowName;
1006
- }
1007
- if (fromDate || toDate) {
1008
- query["createdAt"] = {};
1009
- if (fromDate) {
1010
- query["createdAt"]["$gte"] = fromDate;
1011
- }
1012
- if (toDate) {
1013
- query["createdAt"]["$lte"] = toDate;
1014
- }
1015
- }
1016
- try {
1017
- const collection = await this.getCollection(storage.TABLE_WORKFLOW_SNAPSHOT);
1018
- let total = 0;
1019
- if (limit !== void 0 && offset !== void 0) {
1020
- total = await collection.countDocuments(query);
1021
- }
1022
- const request = collection.find(query).sort({ createdAt: "desc" });
1023
- if (limit) {
1024
- request.limit(limit);
1025
- }
1026
- if (offset) {
1027
- request.skip(offset);
1028
- }
1029
- const result = await request.toArray();
1030
- const runs = result.map((row) => {
1031
- let parsedSnapshot = row.snapshot;
1032
- if (typeof parsedSnapshot === "string") {
1033
- try {
1034
- parsedSnapshot = JSON.parse(row.snapshot);
1035
- } catch (e) {
1036
- console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1037
- }
1038
- }
1039
- return {
1040
- workflowName: row.workflow_name,
1041
- runId: row.run_id,
1042
- snapshot: parsedSnapshot,
1043
- createdAt: new Date(row.createdAt),
1044
- updatedAt: new Date(row.updatedAt)
1045
- };
1046
- });
1047
- return { runs, total: total || runs.length };
1048
- } catch (error$1) {
1049
- throw new error.MastraError(
1050
- {
1051
- id: "STORAGE_MONGODB_STORE_GET_WORKFLOW_RUNS_FAILED",
1052
- domain: error.ErrorDomain.STORAGE,
1053
- category: error.ErrorCategory.THIRD_PARTY
1054
- },
1055
- error$1
1056
- );
1057
- }
1888
+ async batchTraceInsert({ records }) {
1889
+ this.logger.debug("Batch inserting traces", { count: records.length });
1890
+ await this.operations.batchInsert({
1891
+ tableName: storage.TABLE_TRACES,
1892
+ records
1893
+ });
1058
1894
  }
1059
- async getEvalsByAgentName(agentName, type) {
1060
- try {
1061
- const query = {
1062
- agent_name: agentName
1063
- };
1064
- if (type === "test") {
1065
- query["test_info"] = { $ne: null };
1066
- }
1067
- if (type === "live") {
1068
- query["test_info"] = null;
1069
- }
1070
- const collection = await this.getCollection(storage.TABLE_EVALS);
1071
- const documents = await collection.find(query).sort({ created_at: "desc" }).toArray();
1072
- const result = documents.map((row) => this.transformEvalRow(row));
1073
- return result.filter((row) => {
1074
- if (type === "live") {
1075
- return !Boolean(row.testInfo?.testPath);
1076
- }
1077
- if (type === "test") {
1078
- return row.testInfo?.testPath !== null;
1079
- }
1080
- return true;
1081
- });
1082
- } catch (error$1) {
1083
- if (error$1 instanceof Error && error$1.message.includes("no such table")) {
1084
- return [];
1085
- }
1086
- throw new error.MastraError(
1087
- {
1088
- id: "STORAGE_MONGODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
1089
- domain: error.ErrorDomain.STORAGE,
1090
- category: error.ErrorCategory.THIRD_PARTY,
1091
- details: { agentName }
1092
- },
1093
- error$1
1094
- );
1095
- }
1895
+ };
1896
+ var WorkflowsStorageMongoDB = class extends storage.WorkflowsStorage {
1897
+ operations;
1898
+ constructor({ operations }) {
1899
+ super();
1900
+ this.operations = operations;
1096
1901
  }
1097
1902
  async persistWorkflowSnapshot({
1098
1903
  workflowName,
@@ -1100,17 +1905,16 @@ var MongoDBStore = class extends storage.MastraStorage {
1100
1905
  snapshot
1101
1906
  }) {
1102
1907
  try {
1103
- const now = (/* @__PURE__ */ new Date()).toISOString();
1104
- const collection = await this.getCollection(storage.TABLE_WORKFLOW_SNAPSHOT);
1908
+ const collection = await this.operations.getCollection(storage.TABLE_WORKFLOW_SNAPSHOT);
1105
1909
  await collection.updateOne(
1106
1910
  { workflow_name: workflowName, run_id: runId },
1107
1911
  {
1108
1912
  $set: {
1109
- snapshot: JSON.stringify(snapshot),
1110
- updatedAt: now
1111
- },
1112
- $setOnInsert: {
1113
- createdAt: now
1913
+ workflow_name: workflowName,
1914
+ run_id: runId,
1915
+ snapshot,
1916
+ createdAt: /* @__PURE__ */ new Date(),
1917
+ updatedAt: /* @__PURE__ */ new Date()
1114
1918
  }
1115
1919
  },
1116
1920
  { upsert: true }
@@ -1132,7 +1936,7 @@ var MongoDBStore = class extends storage.MastraStorage {
1132
1936
  runId
1133
1937
  }) {
1134
1938
  try {
1135
- const result = await this.load({
1939
+ const result = await this.operations.load({
1136
1940
  tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
1137
1941
  keys: {
1138
1942
  workflow_name: workflowName,
@@ -1142,7 +1946,7 @@ var MongoDBStore = class extends storage.MastraStorage {
1142
1946
  if (!result?.length) {
1143
1947
  return null;
1144
1948
  }
1145
- return JSON.parse(result[0].snapshot);
1949
+ return typeof result[0].snapshot === "string" ? storage.safelyParseJSON(result[0].snapshot) : result[0].snapshot;
1146
1950
  } catch (error$1) {
1147
1951
  throw new error.MastraError(
1148
1952
  {
@@ -1155,19 +1959,63 @@ var MongoDBStore = class extends storage.MastraStorage {
1155
1959
  );
1156
1960
  }
1157
1961
  }
1158
- async getWorkflowRunById({
1159
- runId,
1160
- workflowName
1161
- }) {
1962
+ async getWorkflowRuns(args) {
1963
+ const options = args || {};
1964
+ try {
1965
+ const query = {};
1966
+ if (options.workflowName) {
1967
+ query["workflow_name"] = options.workflowName;
1968
+ }
1969
+ if (options.fromDate) {
1970
+ query["createdAt"] = { $gte: options.fromDate };
1971
+ }
1972
+ if (options.toDate) {
1973
+ if (query["createdAt"]) {
1974
+ query["createdAt"].$lte = options.toDate;
1975
+ } else {
1976
+ query["createdAt"] = { $lte: options.toDate };
1977
+ }
1978
+ }
1979
+ if (options.resourceId) {
1980
+ query["resourceId"] = options.resourceId;
1981
+ }
1982
+ const collection = await this.operations.getCollection(storage.TABLE_WORKFLOW_SNAPSHOT);
1983
+ const total = await collection.countDocuments(query);
1984
+ let cursor = collection.find(query).sort({ createdAt: -1 });
1985
+ if (options.offset) {
1986
+ cursor = cursor.skip(options.offset);
1987
+ }
1988
+ if (options.limit) {
1989
+ cursor = cursor.limit(options.limit);
1990
+ }
1991
+ const results = await cursor.toArray();
1992
+ const runs = results.map((row) => this.parseWorkflowRun(row));
1993
+ return {
1994
+ runs,
1995
+ total
1996
+ };
1997
+ } catch (error$1) {
1998
+ throw new error.MastraError(
1999
+ {
2000
+ id: "STORAGE_MONGODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2001
+ domain: error.ErrorDomain.STORAGE,
2002
+ category: error.ErrorCategory.THIRD_PARTY,
2003
+ details: { workflowName: options.workflowName || "unknown" }
2004
+ },
2005
+ error$1
2006
+ );
2007
+ }
2008
+ }
2009
+ async getWorkflowRunById(args) {
1162
2010
  try {
1163
2011
  const query = {};
1164
- if (runId) {
1165
- query["run_id"] = runId;
2012
+ if (args.runId) {
2013
+ query["run_id"] = args.runId;
1166
2014
  }
1167
- if (workflowName) {
1168
- query["workflow_name"] = workflowName;
2015
+ if (args.workflowName) {
2016
+ query["workflow_name"] = args.workflowName;
1169
2017
  }
1170
- const collection = await this.getCollection(storage.TABLE_WORKFLOW_SNAPSHOT);
2018
+ const collection = await this.operations.getCollection(storage.TABLE_WORKFLOW_SNAPSHOT);
1171
2019
  const result = await collection.findOne(query);
1172
2020
  if (!result) {
1173
2021
  return null;
@@ -1179,7 +2027,7 @@ var MongoDBStore = class extends storage.MastraStorage {
1179
2027
  id: "STORAGE_MONGODB_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
1180
2028
  domain: error.ErrorDomain.STORAGE,
1181
2029
  category: error.ErrorCategory.THIRD_PARTY,
1182
- details: { runId }
2030
+ details: { runId: args.runId }
1183
2031
  },
1184
2032
  error$1
1185
2033
  );
@@ -1189,7 +2037,7 @@ var MongoDBStore = class extends storage.MastraStorage {
1189
2037
  let parsedSnapshot = row.snapshot;
1190
2038
  if (typeof parsedSnapshot === "string") {
1191
2039
  try {
1192
- parsedSnapshot = JSON.parse(row.snapshot);
2040
+ parsedSnapshot = typeof row.snapshot === "string" ? storage.safelyParseJSON(row.snapshot) : row.snapshot;
1193
2041
  } catch (e) {
1194
2042
  console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1195
2043
  }
@@ -1198,85 +2046,187 @@ var MongoDBStore = class extends storage.MastraStorage {
1198
2046
  workflowName: row.workflow_name,
1199
2047
  runId: row.run_id,
1200
2048
  snapshot: parsedSnapshot,
1201
- createdAt: row.createdAt,
1202
- updatedAt: row.updatedAt,
2049
+ createdAt: new Date(row.createdAt),
2050
+ updatedAt: new Date(row.updatedAt),
1203
2051
  resourceId: row.resourceId
1204
2052
  };
1205
2053
  }
1206
- parseRow(row) {
1207
- let content = row.content;
1208
- try {
1209
- content = JSON.parse(row.content);
1210
- } catch {
1211
- }
2054
+ };
2055
+
2056
+ // src/storage/index.ts
2057
+ var MongoDBStore = class extends storage.MastraStorage {
2058
+ #connector;
2059
+ stores;
2060
+ get supports() {
1212
2061
  return {
1213
- id: row.id,
1214
- content,
1215
- role: row.role,
1216
- type: row.type,
1217
- createdAt: new Date(row.createdAt),
1218
- threadId: row.thread_id,
1219
- resourceId: row.resourceId
2062
+ selectByIncludeResourceScope: true,
2063
+ resourceWorkingMemory: true,
2064
+ hasColumn: false,
2065
+ createTable: false
1220
2066
  };
1221
2067
  }
1222
- transformEvalRow(row) {
1223
- let testInfoValue = null;
1224
- if (row.test_info) {
1225
- try {
1226
- testInfoValue = typeof row.test_info === "string" ? JSON.parse(row.test_info) : row.test_info;
1227
- } catch (e) {
1228
- console.warn("Failed to parse test_info:", e);
2068
+ constructor(config) {
2069
+ super({ name: "MongoDBStore" });
2070
+ this.stores = {};
2071
+ try {
2072
+ if ("connectorHandler" in config) {
2073
+ this.#connector = MongoDBConnector.fromConnectionHandler(config.connectorHandler);
2074
+ return;
1229
2075
  }
2076
+ } catch (error$1) {
2077
+ throw new error.MastraError(
2078
+ {
2079
+ id: "STORAGE_MONGODB_STORE_CONSTRUCTOR_FAILED",
2080
+ domain: error.ErrorDomain.STORAGE,
2081
+ category: error.ErrorCategory.USER,
2082
+ details: { connectionHandler: true }
2083
+ },
2084
+ error$1
2085
+ );
1230
2086
  }
1231
- const resultValue = JSON.parse(row.result);
1232
- if (!resultValue || typeof resultValue !== "object" || !("score" in resultValue)) {
1233
- throw new error.MastraError({
1234
- id: "STORAGE_MONGODB_STORE_INVALID_METRIC_FORMAT",
1235
- text: `Invalid MetricResult format: ${JSON.stringify(resultValue)}`,
1236
- domain: error.ErrorDomain.STORAGE,
1237
- category: error.ErrorCategory.USER
2087
+ try {
2088
+ this.#connector = MongoDBConnector.fromDatabaseConfig({
2089
+ options: config.options,
2090
+ url: config.url,
2091
+ dbName: config.dbName
1238
2092
  });
2093
+ } catch (error$1) {
2094
+ throw new error.MastraError(
2095
+ {
2096
+ id: "STORAGE_MONGODB_STORE_CONSTRUCTOR_FAILED",
2097
+ domain: error.ErrorDomain.STORAGE,
2098
+ category: error.ErrorCategory.USER,
2099
+ details: { url: config?.url, dbName: config?.dbName }
2100
+ },
2101
+ error$1
2102
+ );
1239
2103
  }
1240
- return {
1241
- input: row.input,
1242
- output: row.output,
1243
- result: resultValue,
1244
- agentName: row.agent_name,
1245
- metricName: row.metric_name,
1246
- instructions: row.instructions,
1247
- testInfo: testInfoValue,
1248
- globalRunId: row.global_run_id,
1249
- runId: row.run_id,
1250
- createdAt: row.created_at
2104
+ const operations = new StoreOperationsMongoDB({
2105
+ connector: this.#connector
2106
+ });
2107
+ const memory = new MemoryStorageMongoDB({
2108
+ operations
2109
+ });
2110
+ const traces = new TracesStorageMongoDB({
2111
+ operations
2112
+ });
2113
+ const legacyEvals = new LegacyEvalsMongoDB({
2114
+ operations
2115
+ });
2116
+ const scores = new ScoresStorageMongoDB({
2117
+ operations
2118
+ });
2119
+ const workflows = new WorkflowsStorageMongoDB({
2120
+ operations
2121
+ });
2122
+ this.stores = {
2123
+ operations,
2124
+ memory,
2125
+ traces,
2126
+ legacyEvals,
2127
+ scores,
2128
+ workflows
1251
2129
  };
1252
2130
  }
1253
- async getTracesPaginated(_args) {
1254
- throw new error.MastraError({
1255
- id: "STORAGE_MONGODB_STORE_GET_TRACES_PAGINATED_FAILED",
1256
- domain: error.ErrorDomain.STORAGE,
1257
- category: error.ErrorCategory.THIRD_PARTY,
1258
- text: "Method not implemented."
1259
- });
2131
+ async createTable({
2132
+ tableName,
2133
+ schema
2134
+ }) {
2135
+ return this.stores.operations.createTable({ tableName, schema });
2136
+ }
2137
+ async alterTable(_args) {
2138
+ return this.stores.operations.alterTable(_args);
2139
+ }
2140
+ async dropTable({ tableName }) {
2141
+ return this.stores.operations.dropTable({ tableName });
2142
+ }
2143
+ async clearTable({ tableName }) {
2144
+ return this.stores.operations.clearTable({ tableName });
2145
+ }
2146
+ async insert({ tableName, record }) {
2147
+ return this.stores.operations.insert({ tableName, record });
2148
+ }
2149
+ async batchInsert({ tableName, records }) {
2150
+ return this.stores.operations.batchInsert({ tableName, records });
2151
+ }
2152
+ async load({ tableName, keys }) {
2153
+ return this.stores.operations.load({ tableName, keys });
2154
+ }
2155
+ async getThreadById({ threadId }) {
2156
+ return this.stores.memory.getThreadById({ threadId });
2157
+ }
2158
+ async getThreadsByResourceId({ resourceId }) {
2159
+ return this.stores.memory.getThreadsByResourceId({ resourceId });
2160
+ }
2161
+ async saveThread({ thread }) {
2162
+ return this.stores.memory.saveThread({ thread });
2163
+ }
2164
+ async updateThread({
2165
+ id,
2166
+ title,
2167
+ metadata
2168
+ }) {
2169
+ return this.stores.memory.updateThread({ id, title, metadata });
2170
+ }
2171
+ async deleteThread({ threadId }) {
2172
+ return this.stores.memory.deleteThread({ threadId });
2173
+ }
2174
+ async getMessages({
2175
+ threadId,
2176
+ selectBy,
2177
+ format
2178
+ }) {
2179
+ return this.stores.memory.getMessages({ threadId, selectBy, format });
2180
+ }
2181
+ async saveMessages(args) {
2182
+ return this.stores.memory.saveMessages(args);
1260
2183
  }
1261
2184
  async getThreadsByResourceIdPaginated(_args) {
1262
- throw new error.MastraError({
1263
- id: "STORAGE_MONGODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1264
- domain: error.ErrorDomain.STORAGE,
1265
- category: error.ErrorCategory.THIRD_PARTY,
1266
- text: "Method not implemented."
1267
- });
2185
+ return this.stores.memory.getThreadsByResourceIdPaginated(_args);
1268
2186
  }
1269
2187
  async getMessagesPaginated(_args) {
1270
- throw new error.MastraError({
1271
- id: "STORAGE_MONGODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
1272
- domain: error.ErrorDomain.STORAGE,
1273
- category: error.ErrorCategory.THIRD_PARTY,
1274
- text: "Method not implemented."
1275
- });
2188
+ return this.stores.memory.getMessagesPaginated(_args);
2189
+ }
2190
+ async updateMessages(_args) {
2191
+ return this.stores.memory.updateMessages(_args);
2192
+ }
2193
+ async getTraces(args) {
2194
+ return this.stores.traces.getTraces(args);
2195
+ }
2196
+ async getTracesPaginated(args) {
2197
+ return this.stores.traces.getTracesPaginated(args);
2198
+ }
2199
+ async getWorkflowRuns(args) {
2200
+ return this.stores.workflows.getWorkflowRuns(args);
2201
+ }
2202
+ async getEvals(options = {}) {
2203
+ return this.stores.legacyEvals.getEvals(options);
2204
+ }
2205
+ async getEvalsByAgentName(agentName, type) {
2206
+ return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
2207
+ }
2208
+ async persistWorkflowSnapshot({
2209
+ workflowName,
2210
+ runId,
2211
+ snapshot
2212
+ }) {
2213
+ return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
2214
+ }
2215
+ async loadWorkflowSnapshot({
2216
+ workflowName,
2217
+ runId
2218
+ }) {
2219
+ return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
2220
+ }
2221
+ async getWorkflowRunById({
2222
+ runId,
2223
+ workflowName
2224
+ }) {
2225
+ return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
1276
2226
  }
1277
2227
  async close() {
1278
2228
  try {
1279
- await this.#client.close();
2229
+ await this.#connector.close();
1280
2230
  } catch (error$1) {
1281
2231
  throw new error.MastraError(
1282
2232
  {
@@ -1288,9 +2238,55 @@ var MongoDBStore = class extends storage.MastraStorage {
1288
2238
  );
1289
2239
  }
1290
2240
  }
1291
- async updateMessages(_args) {
1292
- this.logger.error("updateMessages is not yet implemented in MongoDBStore");
1293
- throw new Error("Method not implemented");
2241
+ /**
2242
+ * SCORERS
2243
+ */
2244
+ async getScoreById({ id }) {
2245
+ return this.stores.scores.getScoreById({ id });
2246
+ }
2247
+ async saveScore(score) {
2248
+ return this.stores.scores.saveScore(score);
2249
+ }
2250
+ async getScoresByRunId({
2251
+ runId,
2252
+ pagination
2253
+ }) {
2254
+ return this.stores.scores.getScoresByRunId({ runId, pagination });
2255
+ }
2256
+ async getScoresByEntityId({
2257
+ entityId,
2258
+ entityType,
2259
+ pagination
2260
+ }) {
2261
+ return this.stores.scores.getScoresByEntityId({ entityId, entityType, pagination });
2262
+ }
2263
+ async getScoresByScorerId({
2264
+ scorerId,
2265
+ pagination,
2266
+ entityId,
2267
+ entityType
2268
+ }) {
2269
+ return this.stores.scores.getScoresByScorerId({ scorerId, pagination, entityId, entityType });
2270
+ }
2271
+ /**
2272
+ * RESOURCES
2273
+ */
2274
+ async getResourceById({ resourceId }) {
2275
+ return this.stores.memory.getResourceById({ resourceId });
2276
+ }
2277
+ async saveResource({ resource }) {
2278
+ return this.stores.memory.saveResource({ resource });
2279
+ }
2280
+ async updateResource({
2281
+ resourceId,
2282
+ workingMemory,
2283
+ metadata
2284
+ }) {
2285
+ return this.stores.memory.updateResource({
2286
+ resourceId,
2287
+ workingMemory,
2288
+ metadata
2289
+ });
1294
2290
  }
1295
2291
  };
1296
2292