@mastra/mongodb 1.0.0-beta.1 → 1.0.0-beta.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @mastra/mongodb
2
2
 
3
+ ## 1.0.0-beta.3
4
+
5
+ ### Patch Changes
6
+
7
+ - feat(storage): support querying messages from multiple threads ([#10663](https://github.com/mastra-ai/mastra/pull/10663))
8
+ - Fixed TypeScript errors where `threadId: string | string[]` was being passed to places expecting `Scalar` type
9
+ - Added proper multi-thread support for `listMessages` across all adapters when `threadId` is an array
10
+ - Updated `_getIncludedMessages` to look up message threadId by ID (since message IDs are globally unique)
11
+ - **upstash**: Added `msg-idx:{messageId}` index for O(1) message lookups (backwards compatible with fallback to scan for old messages, with automatic backfill)
12
+
13
+ - fix: ensure score responses match saved payloads for Mastra Stores. ([#10557](https://github.com/mastra-ai/mastra/pull/10557))
14
+
15
+ - Unify transformScoreRow functions across storage adapters ([#10648](https://github.com/mastra-ai/mastra/pull/10648))
16
+
17
+ Added a unified `transformScoreRow` function in `@mastra/core/storage` that provides schema-driven row transformation for score data. This eliminates code duplication across 10 storage adapters while maintaining store-specific behavior through configurable options:
18
+ - `preferredTimestampFields`: Preferred source fields for timestamps (PostgreSQL, Cloudflare D1)
19
+ - `convertTimestamps`: Convert timestamp strings to Date objects (MSSQL, MongoDB, ClickHouse)
20
+ - `nullValuePattern`: Skip values matching pattern (ClickHouse's `'_null_'`)
21
+ - `fieldMappings`: Map source column names to schema fields (LibSQL's `additionalLLMContext`)
22
+
23
+ Each store adapter now uses the unified function with appropriate options, reducing ~200 lines of duplicate transformation logic while ensuring consistent behavior across all storage backends.
24
+
25
+ - Updated dependencies [[`ac0d2f4`](https://github.com/mastra-ai/mastra/commit/ac0d2f4ff8831f72c1c66c2be809706d17f65789), [`1a0d3fc`](https://github.com/mastra-ai/mastra/commit/1a0d3fc811482c9c376cdf79ee615c23bae9b2d6), [`85a628b`](https://github.com/mastra-ai/mastra/commit/85a628b1224a8f64cd82ea7f033774bf22df7a7e), [`c237233`](https://github.com/mastra-ai/mastra/commit/c23723399ccedf7f5744b3f40997b79246bfbe64), [`15f9e21`](https://github.com/mastra-ai/mastra/commit/15f9e216177201ea6e3f6d0bfb063fcc0953444f), [`ff94dea`](https://github.com/mastra-ai/mastra/commit/ff94dea935f4e34545c63bcb6c29804732698809), [`5b2ff46`](https://github.com/mastra-ai/mastra/commit/5b2ff4651df70c146523a7fca773f8eb0a2272f8), [`db41688`](https://github.com/mastra-ai/mastra/commit/db4168806d007417e2e60b4f68656dca4e5f40c9), [`5ca599d`](https://github.com/mastra-ai/mastra/commit/5ca599d0bb59a1595f19f58473fcd67cc71cef58), [`bff1145`](https://github.com/mastra-ai/mastra/commit/bff114556b3cbadad9b2768488708f8ad0e91475), [`5c8ca24`](https://github.com/mastra-ai/mastra/commit/5c8ca247094e0cc2cdbd7137822fb47241f86e77), [`e191844`](https://github.com/mastra-ai/mastra/commit/e1918444ca3f80e82feef1dad506cd4ec6e2875f), [`22553f1`](https://github.com/mastra-ai/mastra/commit/22553f11c63ee5e966a9c034a349822249584691), [`7237163`](https://github.com/mastra-ai/mastra/commit/72371635dbf96a87df4b073cc48fc655afbdce3d), [`2500740`](https://github.com/mastra-ai/mastra/commit/2500740ea23da067d6e50ec71c625ab3ce275e64), [`873ecbb`](https://github.com/mastra-ai/mastra/commit/873ecbb517586aa17d2f1e99283755b3ebb2863f), [`4f9bbe5`](https://github.com/mastra-ai/mastra/commit/4f9bbe5968f42c86f4930b8193de3c3c17e5bd36), [`02e51fe`](https://github.com/mastra-ai/mastra/commit/02e51feddb3d4155cfbcc42624fd0d0970d032c0), [`8f3fa3a`](https://github.com/mastra-ai/mastra/commit/8f3fa3a652bb77da092f913ec51ae46e3a7e27dc), [`cd29ad2`](https://github.com/mastra-ai/mastra/commit/cd29ad23a255534e8191f249593849ed29160886), [`bdf4d8c`](https://github.com/mastra-ai/mastra/commit/bdf4d8cdc656d8a2c21d81834bfa3bfa70f56c16), [`854e3da`](https://github.com/mastra-ai/mastra/commit/854e3dad5daac17a91a20986399d3a51f54bf68b), [`ce18d38`](https://github.com/mastra-ai/mastra/commit/ce18d38678c65870350d123955014a8432075fd9), [`cccf9c8`](https://github.com/mastra-ai/mastra/commit/cccf9c8b2d2dfc1a5e63919395b83d78c89682a0), [`61a5705`](https://github.com/mastra-ai/mastra/commit/61a570551278b6743e64243b3ce7d73de915ca8a), [`db70a48`](https://github.com/mastra-ai/mastra/commit/db70a48aeeeeb8e5f92007e8ede52c364ce15287), [`f0fdc14`](https://github.com/mastra-ai/mastra/commit/f0fdc14ee233d619266b3d2bbdeea7d25cfc6d13), [`db18bc9`](https://github.com/mastra-ai/mastra/commit/db18bc9c3825e2c1a0ad9a183cc9935f6691bfa1), [`9b37b56`](https://github.com/mastra-ai/mastra/commit/9b37b565e1f2a76c24f728945cc740c2b09be9da), [`41a23c3`](https://github.com/mastra-ai/mastra/commit/41a23c32f9877d71810f37e24930515df2ff7a0f), [`5d171ad`](https://github.com/mastra-ai/mastra/commit/5d171ad9ef340387276b77c2bb3e83e83332d729), [`f03ae60`](https://github.com/mastra-ai/mastra/commit/f03ae60500fe350c9d828621006cdafe1975fdd8), [`d1e74a0`](https://github.com/mastra-ai/mastra/commit/d1e74a0a293866dece31022047f5dbab65a304d0), [`39e7869`](https://github.com/mastra-ai/mastra/commit/39e7869bc7d0ee391077ce291474d8a84eedccff), [`5761926`](https://github.com/mastra-ai/mastra/commit/57619260c4a2cdd598763abbacd90de594c6bc76), [`c900fdd`](https://github.com/mastra-ai/mastra/commit/c900fdd504c41348efdffb205cfe80d48c38fa33), [`604a79f`](https://github.com/mastra-ai/mastra/commit/604a79fecf276e26a54a3fe01bb94e65315d2e0e), [`887f0b4`](https://github.com/mastra-ai/mastra/commit/887f0b4746cdbd7cb7d6b17ac9f82aeb58037ea5), [`2562143`](https://github.com/mastra-ai/mastra/commit/256214336b4faa78646c9c1776612393790d8784), [`ef11a61`](https://github.com/mastra-ai/mastra/commit/ef11a61920fa0ed08a5b7ceedd192875af119749)]:
26
+ - @mastra/core@1.0.0-beta.6
27
+
28
+ ## 1.0.0-beta.2
29
+
30
+ ### Patch Changes
31
+
32
+ - Add new deleteVectors, updateVector by filter ([#10408](https://github.com/mastra-ai/mastra/pull/10408))
33
+
34
+ - Updated dependencies [[`21a15de`](https://github.com/mastra-ai/mastra/commit/21a15de369fe82aac26bb642ed7be73505475e8b), [`feb7ee4`](https://github.com/mastra-ai/mastra/commit/feb7ee4d09a75edb46c6669a3beaceec78811747), [`b0e2ea5`](https://github.com/mastra-ai/mastra/commit/b0e2ea5b52c40fae438b9e2f7baee6f0f89c5442), [`c456e01`](https://github.com/mastra-ai/mastra/commit/c456e0149e3c176afcefdbd9bb1d2c5917723725), [`ab035c2`](https://github.com/mastra-ai/mastra/commit/ab035c2ef6d8cc7bb25f06f1a38508bd9e6f126b), [`1a46a56`](https://github.com/mastra-ai/mastra/commit/1a46a566f45a3fcbadc1cf36bf86d351f264bfa3), [`3cf540b`](https://github.com/mastra-ai/mastra/commit/3cf540b9fbfea8f4fc8d3a2319a4e6c0b0cbfd52), [`1c6ce51`](https://github.com/mastra-ai/mastra/commit/1c6ce51f875915ab57fd36873623013699a2a65d), [`898a972`](https://github.com/mastra-ai/mastra/commit/898a9727d286c2510d6b702dfd367e6aaf5c6b0f), [`a97003a`](https://github.com/mastra-ai/mastra/commit/a97003aa1cf2f4022a41912324a1e77263b326b8), [`ccc141e`](https://github.com/mastra-ai/mastra/commit/ccc141ed27da0abc3a3fc28e9e5128152e8e37f4), [`fe3b897`](https://github.com/mastra-ai/mastra/commit/fe3b897c2ccbcd2b10e81b099438c7337feddf89), [`00123ba`](https://github.com/mastra-ai/mastra/commit/00123ba96dc9e5cd0b110420ebdba56d8f237b25), [`29c4309`](https://github.com/mastra-ai/mastra/commit/29c4309f818b24304c041bcb4a8f19b5f13f6b62), [`16785ce`](https://github.com/mastra-ai/mastra/commit/16785ced928f6f22638f4488cf8a125d99211799), [`de8239b`](https://github.com/mastra-ai/mastra/commit/de8239bdcb1d8c0cfa06da21f1569912a66bbc8a), [`b5e6cd7`](https://github.com/mastra-ai/mastra/commit/b5e6cd77fc8c8e64e0494c1d06cee3d84e795d1e), [`3759cb0`](https://github.com/mastra-ai/mastra/commit/3759cb064935b5f74c65ac2f52a1145f7352899d), [`651e772`](https://github.com/mastra-ai/mastra/commit/651e772eb1475fb13e126d3fcc01751297a88214), [`b61b93f`](https://github.com/mastra-ai/mastra/commit/b61b93f9e058b11dd2eec169853175d31dbdd567), [`bae33d9`](https://github.com/mastra-ai/mastra/commit/bae33d91a63fbb64d1e80519e1fc1acaed1e9013), [`c0b731f`](https://github.com/mastra-ai/mastra/commit/c0b731fb27d712dc8582e846df5c0332a6a0c5ba), [`43ca8f2`](https://github.com/mastra-ai/mastra/commit/43ca8f2c7334851cc7b4d3d2f037d8784bfbdd5f), [`2ca67cc`](https://github.com/mastra-ai/mastra/commit/2ca67cc3bb1f6a617353fdcab197d9efebe60d6f), [`9e67002`](https://github.com/mastra-ai/mastra/commit/9e67002b52c9be19936c420a489dbee9c5fd6a78), [`35edc49`](https://github.com/mastra-ai/mastra/commit/35edc49ac0556db609189641d6341e76771b81fc)]:
35
+ - @mastra/core@1.0.0-beta.5
36
+
3
37
  ## 1.0.0-beta.1
4
38
 
5
39
  ### Patch Changes
package/README.md CHANGED
@@ -161,10 +161,11 @@ The following distance metrics are supported:
161
161
 
162
162
  > **Note:** `documentFilter` allows filtering results based on the content of the `document` field. Example: `{ $contains: 'specific text' }` will return only vectors whose associated document contains the specified text.
163
163
 
164
+ - `updateVector({ indexName, id?, filter?, update })`: Update a single vector by ID or metadata filter
165
+ - `deleteVector({ indexName, id })`: Delete a single vector by ID
166
+ - `deleteVectors({ indexName, ids?, filter? })`: Delete multiple vectors by IDs or metadata filter
164
167
  - `listIndexes()`: List all vector-enabled collections
165
168
  - `describeIndex(indexName)`: Get collection statistics (dimension, count, metric)
166
- - `updateIndexById(indexName, id, { vector?, metadata? })`: Update a vector and/or its metadata by ID
167
- - `deleteIndexById(indexName, id)`: Delete a vector by ID
168
169
  - `deleteIndex(indexName)`: Delete a collection
169
170
  - `disconnect()`: Close the MongoDB connection
170
171
 
package/dist/index.cjs CHANGED
@@ -13,7 +13,7 @@ var evals = require('@mastra/core/evals');
13
13
 
14
14
  // package.json
15
15
  var package_default = {
16
- version: "1.0.0-beta.1"};
16
+ version: "1.0.0-beta.3"};
17
17
  var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
18
18
  getSupportedOperators() {
19
19
  return {
@@ -355,12 +355,17 @@ var MongoDBVector = class extends vector.MastraVector {
355
355
  limit: topK
356
356
  };
357
357
  if (Object.keys(combinedFilter).length > 0) {
358
- const candidateIds = await collection.aggregate([{ $match: combinedFilter }, { $project: { _id: 1 } }]).map((doc) => doc._id).toArray();
358
+ const filterWithExclusion = {
359
+ $and: [{ _id: { $ne: "__index_metadata__" } }, combinedFilter]
360
+ };
361
+ const candidateIds = await collection.aggregate([{ $match: filterWithExclusion }, { $project: { _id: 1 } }]).map((doc) => doc._id).toArray();
359
362
  if (candidateIds.length > 0) {
360
363
  vectorSearch.filter = { _id: { $in: candidateIds } };
361
364
  } else {
362
365
  return [];
363
366
  }
367
+ } else {
368
+ vectorSearch.filter = { _id: { $ne: "__index_metadata__" } };
364
369
  }
365
370
  const pipeline = [
366
371
  {
@@ -481,7 +486,26 @@ var MongoDBVector = class extends vector.MastraVector {
481
486
  * @returns A promise that resolves when the update is complete.
482
487
  * @throws Will throw an error if no updates are provided or if the update operation fails.
483
488
  */
484
- async updateVector({ indexName, id, update }) {
489
+ async updateVector(params) {
490
+ const { indexName, update } = params;
491
+ if ("id" in params && params.id && "filter" in params && params.filter) {
492
+ throw new error.MastraError({
493
+ id: "STORAGE_MONGODB_VECTOR_UPDATE_MUTUALLY_EXCLUSIVE_PARAMS",
494
+ domain: error.ErrorDomain.STORAGE,
495
+ category: error.ErrorCategory.USER,
496
+ details: { indexName },
497
+ text: "id and filter are mutually exclusive - provide only one"
498
+ });
499
+ }
500
+ if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
501
+ throw new error.MastraError({
502
+ id: "STORAGE_MONGODB_VECTOR_UPDATE_MISSING_PARAMS",
503
+ domain: error.ErrorDomain.STORAGE,
504
+ category: error.ErrorCategory.USER,
505
+ text: "Either id or filter must be provided",
506
+ details: { indexName }
507
+ });
508
+ }
485
509
  try {
486
510
  if (!update.vector && !update.metadata) {
487
511
  throw new Error("No updates provided");
@@ -503,17 +527,49 @@ var MongoDBVector = class extends vector.MastraVector {
503
527
  );
504
528
  updateDoc[this.metadataFieldName] = normalizedMeta;
505
529
  }
506
- await collection.findOneAndUpdate({ _id: id }, { $set: updateDoc });
530
+ if ("id" in params && params.id) {
531
+ await collection.findOneAndUpdate({ _id: params.id }, { $set: updateDoc });
532
+ } else if ("filter" in params && params.filter) {
533
+ const filter = params.filter;
534
+ if (!filter || Object.keys(filter).length === 0) {
535
+ throw new error.MastraError({
536
+ id: "STORAGE_MONGODB_VECTOR_UPDATE_EMPTY_FILTER",
537
+ domain: error.ErrorDomain.STORAGE,
538
+ category: error.ErrorCategory.USER,
539
+ details: { indexName },
540
+ text: "Cannot update with empty filter"
541
+ });
542
+ }
543
+ const mongoFilter = this.transformFilter(filter);
544
+ const transformedFilter = this.transformMetadataFilter(mongoFilter);
545
+ if (!transformedFilter || Object.keys(transformedFilter).length === 0) {
546
+ throw new error.MastraError({
547
+ id: "STORAGE_MONGODB_VECTOR_UPDATE_INVALID_FILTER",
548
+ domain: error.ErrorDomain.STORAGE,
549
+ category: error.ErrorCategory.USER,
550
+ details: { indexName },
551
+ text: "Filter produced empty query"
552
+ });
553
+ }
554
+ await collection.updateMany(transformedFilter, { $set: updateDoc });
555
+ }
507
556
  } catch (error$1) {
557
+ if (error$1 instanceof error.MastraError) {
558
+ throw error$1;
559
+ }
560
+ const errorDetails = { indexName };
561
+ if ("id" in params && params.id) {
562
+ errorDetails.id = params.id;
563
+ }
564
+ if ("filter" in params && params.filter) {
565
+ errorDetails.filter = JSON.stringify(params.filter);
566
+ }
508
567
  throw new error.MastraError(
509
568
  {
510
569
  id: "STORAGE_MONGODB_VECTOR_UPDATE_VECTOR_FAILED",
511
570
  domain: error.ErrorDomain.STORAGE,
512
571
  category: error.ErrorCategory.THIRD_PARTY,
513
- details: {
514
- indexName,
515
- id
516
- }
572
+ details: errorDetails
517
573
  },
518
574
  error$1
519
575
  );
@@ -545,6 +601,83 @@ var MongoDBVector = class extends vector.MastraVector {
545
601
  );
546
602
  }
547
603
  }
604
+ async deleteVectors({ indexName, filter, ids }) {
605
+ if (!filter && !ids) {
606
+ throw new error.MastraError({
607
+ id: "STORAGE_MONGODB_VECTOR_DELETE_MISSING_PARAMS",
608
+ domain: error.ErrorDomain.STORAGE,
609
+ category: error.ErrorCategory.USER,
610
+ details: { indexName },
611
+ text: "Either filter or ids must be provided"
612
+ });
613
+ }
614
+ if (filter && ids) {
615
+ throw new error.MastraError({
616
+ id: "STORAGE_MONGODB_VECTOR_DELETE_CONFLICTING_PARAMS",
617
+ domain: error.ErrorDomain.STORAGE,
618
+ category: error.ErrorCategory.USER,
619
+ details: { indexName },
620
+ text: "Cannot provide both filter and ids - they are mutually exclusive"
621
+ });
622
+ }
623
+ try {
624
+ const collection = await this.getCollection(indexName, true);
625
+ if (ids) {
626
+ if (ids.length === 0) {
627
+ throw new error.MastraError({
628
+ id: "STORAGE_MONGODB_VECTOR_DELETE_EMPTY_IDS",
629
+ domain: error.ErrorDomain.STORAGE,
630
+ category: error.ErrorCategory.USER,
631
+ details: { indexName },
632
+ text: "Cannot delete with empty ids array"
633
+ });
634
+ }
635
+ await collection.deleteMany({ _id: { $in: ids } });
636
+ } else {
637
+ if (!filter || Object.keys(filter).length === 0) {
638
+ throw new error.MastraError({
639
+ id: "STORAGE_MONGODB_VECTOR_DELETE_EMPTY_FILTER",
640
+ domain: error.ErrorDomain.STORAGE,
641
+ category: error.ErrorCategory.USER,
642
+ details: { indexName },
643
+ text: "Cannot delete with empty filter"
644
+ });
645
+ }
646
+ const mongoFilter = this.transformFilter(filter);
647
+ const transformedFilter = this.transformMetadataFilter(mongoFilter);
648
+ if (!transformedFilter || Object.keys(transformedFilter).length === 0) {
649
+ throw new error.MastraError({
650
+ id: "STORAGE_MONGODB_VECTOR_DELETE_INVALID_FILTER",
651
+ domain: error.ErrorDomain.STORAGE,
652
+ category: error.ErrorCategory.USER,
653
+ details: { indexName },
654
+ text: "Filter produced empty query"
655
+ });
656
+ }
657
+ const finalFilter = {
658
+ $and: [{ _id: { $ne: "__index_metadata__" } }, transformedFilter]
659
+ };
660
+ await collection.deleteMany(finalFilter);
661
+ }
662
+ } catch (error$1) {
663
+ if (error$1 instanceof error.MastraError) {
664
+ throw error$1;
665
+ }
666
+ throw new error.MastraError(
667
+ {
668
+ id: "STORAGE_MONGODB_VECTOR_DELETE_VECTORS_FAILED",
669
+ domain: error.ErrorDomain.STORAGE,
670
+ category: error.ErrorCategory.THIRD_PARTY,
671
+ details: {
672
+ indexName,
673
+ ...filter && { filter: JSON.stringify(filter) },
674
+ ...ids && { idsCount: ids.length }
675
+ }
676
+ },
677
+ error$1
678
+ );
679
+ }
680
+ }
548
681
  // Private methods
549
682
  async getCollection(indexName, throwIfNotExists = true) {
550
683
  if (this.collections.has(indexName)) {
@@ -592,16 +725,26 @@ var MongoDBVector = class extends vector.MastraVector {
592
725
  */
593
726
  transformMetadataFilter(filter) {
594
727
  if (!filter || typeof filter !== "object") return filter;
728
+ if (Array.isArray(filter)) {
729
+ return filter.map((item) => this.transformMetadataFilter(item));
730
+ }
595
731
  const transformed = {};
596
732
  for (const [key, value] of Object.entries(filter)) {
597
733
  if (key.startsWith("$")) {
598
734
  if (Array.isArray(value)) {
599
735
  transformed[key] = value.map((item) => this.transformMetadataFilter(item));
600
- } else {
736
+ } else if (typeof value === "object" && value !== null) {
601
737
  transformed[key] = this.transformMetadataFilter(value);
738
+ } else {
739
+ transformed[key] = value;
602
740
  }
603
741
  } else if (key.startsWith("metadata.")) {
604
- transformed[key] = value;
742
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
743
+ const hasOperator = Object.keys(value).some((k) => k.startsWith("$"));
744
+ transformed[key] = hasOperator ? value : value;
745
+ } else {
746
+ transformed[key] = value;
747
+ }
605
748
  } else if (this.isMetadataField(key)) {
606
749
  transformed[`metadata.${key}`] = value;
607
750
  } else {
@@ -695,8 +838,6 @@ var MongoDBConnector = class _MongoDBConnector {
695
838
  }
696
839
  }
697
840
  };
698
-
699
- // src/storage/domains/utils.ts
700
841
  function formatDateForMongoDB(date) {
701
842
  return typeof date === "string" ? new Date(date) : date;
702
843
  }
@@ -727,18 +868,16 @@ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
727
868
  if (row.type && row.type !== "v2") result.type = row.type;
728
869
  return result;
729
870
  }
730
- async _getIncludedMessages({
731
- threadId,
732
- include
733
- }) {
734
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
735
- if (!include) return null;
871
+ async _getIncludedMessages({ include }) {
872
+ if (!include || include.length === 0) return null;
736
873
  const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
737
874
  const includedMessages = [];
738
875
  for (const inc of include) {
739
876
  const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
740
- const searchThreadId = inc.threadId || threadId;
741
- const allMessages = await collection.find({ thread_id: searchThreadId }).sort({ createdAt: 1 }).toArray();
877
+ const targetMessage = await collection.findOne({ id });
878
+ if (!targetMessage) continue;
879
+ const messageThreadId = targetMessage.thread_id;
880
+ const allMessages = await collection.find({ thread_id: messageThreadId }).sort({ createdAt: 1 }).toArray();
742
881
  const targetIndex = allMessages.findIndex((msg) => msg.id === id);
743
882
  if (targetIndex === -1) continue;
744
883
  const startIndex = Math.max(0, targetIndex - withPreviousMessages);
@@ -779,15 +918,16 @@ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
779
918
  }
780
919
  async listMessages(args) {
781
920
  const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
782
- if (!threadId.trim()) {
921
+ const threadIds = Array.isArray(threadId) ? threadId : [threadId];
922
+ if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
783
923
  throw new error.MastraError(
784
924
  {
785
925
  id: "STORAGE_MONGODB_LIST_MESSAGES_INVALID_THREAD_ID",
786
926
  domain: error.ErrorDomain.STORAGE,
787
927
  category: error.ErrorCategory.THIRD_PARTY,
788
- details: { threadId }
928
+ details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
789
929
  },
790
- new Error("threadId must be a non-empty string")
930
+ new Error("threadId must be a non-empty string or array of non-empty strings")
791
931
  );
792
932
  }
793
933
  if (page < 0) {
@@ -807,7 +947,7 @@ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
807
947
  const { field, direction } = this.parseOrderBy(orderBy, "ASC");
808
948
  const sortOrder = direction === "ASC" ? 1 : -1;
809
949
  const collection = await this.operations.getCollection(storage.TABLE_MESSAGES);
810
- const query = { thread_id: threadId };
950
+ const query = { thread_id: threadIds.length === 1 ? threadIds[0] : { $in: threadIds } };
811
951
  if (resourceId) {
812
952
  query.resourceId = resourceId;
813
953
  }
@@ -839,7 +979,7 @@ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
839
979
  }
840
980
  const messageIds = new Set(messages.map((m) => m.id));
841
981
  if (include && include.length > 0) {
842
- const includeMessages = await this._getIncludedMessages({ threadId, include });
982
+ const includeMessages = await this._getIncludedMessages({ include });
843
983
  if (includeMessages) {
844
984
  for (const includeMsg of includeMessages) {
845
985
  if (!messageIds.has(includeMsg.id)) {
@@ -860,7 +1000,10 @@ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
860
1000
  }
861
1001
  return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
862
1002
  });
863
- const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1003
+ const threadIdSet = new Set(threadIds);
1004
+ const returnedThreadMessageIds = new Set(
1005
+ finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
1006
+ );
864
1007
  const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
865
1008
  const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
866
1009
  return {
@@ -877,7 +1020,7 @@ var MemoryStorageMongoDB = class extends storage.MemoryStorage {
877
1020
  domain: error.ErrorDomain.STORAGE,
878
1021
  category: error.ErrorCategory.THIRD_PARTY,
879
1022
  details: {
880
- threadId,
1023
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
881
1024
  resourceId: resourceId ?? ""
882
1025
  }
883
1026
  },
@@ -1757,98 +1900,9 @@ var StoreOperationsMongoDB = class extends storage.StoreOperations {
1757
1900
  }
1758
1901
  };
1759
1902
  function transformScoreRow(row) {
1760
- let scorerValue = null;
1761
- if (row.scorer) {
1762
- try {
1763
- scorerValue = typeof row.scorer === "string" ? storage.safelyParseJSON(row.scorer) : row.scorer;
1764
- } catch (e) {
1765
- console.warn("Failed to parse scorer:", e);
1766
- }
1767
- }
1768
- let preprocessStepResultValue = null;
1769
- if (row.preprocessStepResult) {
1770
- try {
1771
- preprocessStepResultValue = typeof row.preprocessStepResult === "string" ? storage.safelyParseJSON(row.preprocessStepResult) : row.preprocessStepResult;
1772
- } catch (e) {
1773
- console.warn("Failed to parse preprocessStepResult:", e);
1774
- }
1775
- }
1776
- let analyzeStepResultValue = null;
1777
- if (row.analyzeStepResult) {
1778
- try {
1779
- analyzeStepResultValue = typeof row.analyzeStepResult === "string" ? storage.safelyParseJSON(row.analyzeStepResult) : row.analyzeStepResult;
1780
- } catch (e) {
1781
- console.warn("Failed to parse analyzeStepResult:", e);
1782
- }
1783
- }
1784
- let inputValue = null;
1785
- if (row.input) {
1786
- try {
1787
- inputValue = typeof row.input === "string" ? storage.safelyParseJSON(row.input) : row.input;
1788
- } catch (e) {
1789
- console.warn("Failed to parse input:", e);
1790
- }
1791
- }
1792
- let outputValue = null;
1793
- if (row.output) {
1794
- try {
1795
- outputValue = typeof row.output === "string" ? storage.safelyParseJSON(row.output) : row.output;
1796
- } catch (e) {
1797
- console.warn("Failed to parse output:", e);
1798
- }
1799
- }
1800
- let entityValue = null;
1801
- if (row.entity) {
1802
- try {
1803
- entityValue = typeof row.entity === "string" ? storage.safelyParseJSON(row.entity) : row.entity;
1804
- } catch (e) {
1805
- console.warn("Failed to parse entity:", e);
1806
- }
1807
- }
1808
- let requestContextValue = null;
1809
- if (row.requestContext) {
1810
- try {
1811
- requestContextValue = typeof row.requestContext === "string" ? storage.safelyParseJSON(row.requestContext) : row.requestContext;
1812
- } catch (e) {
1813
- console.warn("Failed to parse requestContext:", e);
1814
- }
1815
- }
1816
- let metadataValue = null;
1817
- if (row.metadata) {
1818
- try {
1819
- metadataValue = typeof row.metadata === "string" ? storage.safelyParseJSON(row.metadata) : row.metadata;
1820
- } catch (e) {
1821
- console.warn("Failed to parse metadata:", e);
1822
- }
1823
- }
1824
- return {
1825
- id: row.id,
1826
- entityId: row.entityId,
1827
- entityType: row.entityType,
1828
- scorerId: row.scorerId,
1829
- traceId: row.traceId,
1830
- spanId: row.spanId,
1831
- runId: row.runId,
1832
- scorer: scorerValue,
1833
- preprocessStepResult: preprocessStepResultValue,
1834
- preprocessPrompt: row.preprocessPrompt,
1835
- analyzeStepResult: analyzeStepResultValue,
1836
- generateScorePrompt: row.generateScorePrompt,
1837
- score: row.score,
1838
- analyzePrompt: row.analyzePrompt,
1839
- reasonPrompt: row.reasonPrompt,
1840
- metadata: metadataValue,
1841
- input: inputValue,
1842
- output: outputValue,
1843
- additionalContext: row.additionalContext,
1844
- requestContext: requestContextValue,
1845
- entity: entityValue,
1846
- source: row.source,
1847
- resourceId: row.resourceId,
1848
- threadId: row.threadId,
1849
- createdAt: new Date(row.createdAt),
1850
- updatedAt: new Date(row.updatedAt)
1851
- };
1903
+ return storage.transformScoreRow(row, {
1904
+ convertTimestamps: true
1905
+ });
1852
1906
  }
1853
1907
  var ScoresStorageMongoDB = class extends storage.ScoresStorage {
1854
1908
  operations;
@@ -1893,36 +1947,29 @@ var ScoresStorageMongoDB = class extends storage.ScoresStorage {
1893
1947
  try {
1894
1948
  const now = /* @__PURE__ */ new Date();
1895
1949
  const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1896
- const scoreData = {
1897
- id: scoreId,
1898
- entityId: validatedScore.entityId,
1899
- entityType: validatedScore.entityType,
1900
- scorerId: validatedScore.scorerId,
1901
- traceId: validatedScore.traceId || "",
1902
- spanId: validatedScore.spanId || "",
1903
- runId: validatedScore.runId,
1904
- scorer: typeof validatedScore.scorer === "string" ? storage.safelyParseJSON(validatedScore.scorer) : validatedScore.scorer,
1905
- preprocessStepResult: typeof validatedScore.preprocessStepResult === "string" ? storage.safelyParseJSON(validatedScore.preprocessStepResult) : validatedScore.preprocessStepResult,
1906
- analyzeStepResult: typeof validatedScore.analyzeStepResult === "string" ? storage.safelyParseJSON(validatedScore.analyzeStepResult) : validatedScore.analyzeStepResult,
1907
- score: validatedScore.score,
1908
- reason: validatedScore.reason,
1909
- preprocessPrompt: validatedScore.preprocessPrompt,
1910
- generateScorePrompt: validatedScore.generateScorePrompt,
1911
- generateReasonPrompt: validatedScore.generateReasonPrompt,
1912
- analyzePrompt: validatedScore.analyzePrompt,
1913
- input: typeof validatedScore.input === "string" ? storage.safelyParseJSON(validatedScore.input) : validatedScore.input,
1914
- output: typeof validatedScore.output === "string" ? storage.safelyParseJSON(validatedScore.output) : validatedScore.output,
1915
- additionalContext: validatedScore.additionalContext,
1916
- requestContext: typeof validatedScore.requestContext === "string" ? storage.safelyParseJSON(validatedScore.requestContext) : validatedScore.requestContext,
1917
- entity: typeof validatedScore.entity === "string" ? storage.safelyParseJSON(validatedScore.entity) : validatedScore.entity,
1918
- source: validatedScore.source,
1919
- resourceId: validatedScore.resourceId || "",
1920
- threadId: validatedScore.threadId || "",
1921
- createdAt: now,
1922
- updatedAt: now
1950
+ const scorer = typeof validatedScore.scorer === "string" ? storage.safelyParseJSON(validatedScore.scorer) : validatedScore.scorer;
1951
+ const preprocessStepResult = typeof validatedScore.preprocessStepResult === "string" ? storage.safelyParseJSON(validatedScore.preprocessStepResult) : validatedScore.preprocessStepResult;
1952
+ const analyzeStepResult = typeof validatedScore.analyzeStepResult === "string" ? storage.safelyParseJSON(validatedScore.analyzeStepResult) : validatedScore.analyzeStepResult;
1953
+ const input = typeof validatedScore.input === "string" ? storage.safelyParseJSON(validatedScore.input) : validatedScore.input;
1954
+ const output = typeof validatedScore.output === "string" ? storage.safelyParseJSON(validatedScore.output) : validatedScore.output;
1955
+ const requestContext = typeof validatedScore.requestContext === "string" ? storage.safelyParseJSON(validatedScore.requestContext) : validatedScore.requestContext;
1956
+ const entity = typeof validatedScore.entity === "string" ? storage.safelyParseJSON(validatedScore.entity) : validatedScore.entity;
1957
+ const createdAt = now;
1958
+ const updatedAt = now;
1959
+ const dataToSave = {
1960
+ ...validatedScore,
1961
+ scorer,
1962
+ preprocessStepResult,
1963
+ analyzeStepResult,
1964
+ input,
1965
+ output,
1966
+ requestContext,
1967
+ entity,
1968
+ createdAt,
1969
+ updatedAt
1923
1970
  };
1924
1971
  const collection = await this.operations.getCollection(storage.TABLE_SCORERS);
1925
- await collection.insertOne(scoreData);
1972
+ await collection.insertOne(dataToSave);
1926
1973
  const savedScore = {
1927
1974
  ...score,
1928
1975
  id: scoreId,