@mastra/mongodb 1.21.0 → 1.22.0-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.js CHANGED
@@ -8,7 +8,7 @@ import { MessageList } from "@mastra/core/agent";
8
8
  import { saveScorePayloadSchema } from "@mastra/core/evals";
9
9
  import { skillSnapshotFieldValuesEqual } from "@mastra/core/storage/domains/skills";
10
10
  //#region package.json
11
- var version = "1.21.0";
11
+ var version = "1.22.0-alpha.0";
12
12
  //#endregion
13
13
  //#region src/vector/filter.ts
14
14
  /**
@@ -84,11 +84,22 @@ var MongoDBFilterTranslator = class extends BaseFilterTranslator {
84
84
  function describeEmbedding(config) {
85
85
  return config ? `autoEmbed (path "${config.path}", model "${config.model}")` : "client-side vectors";
86
86
  }
87
+ /**
88
+ * Whether Atlas refused a `$vectorSearch` because the index is still in its initial sync. The
89
+ * server reports it as a generic `UnknownError`, so the state named in the message is the only
90
+ * thing that tells it apart from other failures with the same code.
91
+ */
92
+ function isInitialSyncError(error) {
93
+ const message = error?.message;
94
+ return typeof message === "string" && message.includes("while in state INITIAL_SYNC");
95
+ }
87
96
  var MongoDBVector = class MongoDBVector extends MastraVector {
88
97
  client;
89
98
  db;
90
99
  collections;
91
100
  embeddingFieldName;
101
+ /** Automated Embedding defaults applied to indexes created without their own config. */
102
+ defaultAutoEmbed;
92
103
  metadataFieldName = "metadata";
93
104
  documentFieldName = "document";
94
105
  /**
@@ -124,6 +135,19 @@ var MongoDBVector = class MongoDBVector extends MastraVector {
124
135
  */
125
136
  static REGISTRY_COLLECTION = "__mastra_vector_indexes__";
126
137
  /**
138
+ * Waits between attempts while a queried index is in INITIAL_SYNC, about six seconds in all.
139
+ * On a live Atlas cluster the window lasted around two seconds for both a regular and an
140
+ * autoEmbed index; the budget leaves room for a slower build without holding a failing query
141
+ * for long.
142
+ */
143
+ static INITIAL_SYNC_RETRY_DELAYS_MS = [
144
+ 250,
145
+ 500,
146
+ 1e3,
147
+ 2e3,
148
+ 2e3
149
+ ];
150
+ /**
127
151
  * MongoDB query operators supported inside `$vectorSearch.filter`. Intentionally
128
152
  * conservative: filters using any operator outside this set fall back to the
129
153
  * `$match` pre-filter, which supports the full query language. Widening this set
@@ -146,7 +170,7 @@ var MongoDBVector = class MongoDBVector extends MastraVector {
146
170
  euclidean: "euclidean",
147
171
  dotproduct: "dotProduct"
148
172
  };
149
- constructor({ id, uri, dbName, options, embeddingFieldPath }) {
173
+ constructor({ id, uri, dbName, options, embeddingFieldPath, autoEmbed }) {
150
174
  super({ id });
151
175
  if (!uri) throw new Error("MongoDBVector requires a connection string. Provide \"uri\" in the constructor options.");
152
176
  const client = new MongoClient(uri, {
@@ -160,6 +184,11 @@ var MongoDBVector = class MongoDBVector extends MastraVector {
160
184
  this.db = this.client.db(dbName);
161
185
  this.collections = /* @__PURE__ */ new Map();
162
186
  this.embeddingFieldName = embeddingFieldPath ?? "embedding";
187
+ this.defaultAutoEmbed = autoEmbed;
188
+ }
189
+ /** True once the store is configured with Automated Embedding defaults. */
190
+ get isSelfEmbedding() {
191
+ return this.defaultAutoEmbed !== void 0;
163
192
  }
164
193
  /**
165
194
  * Resolve the collection + vector-index names for an index, honoring BYO overrides.
@@ -441,7 +470,8 @@ var MongoDBVector = class MongoDBVector extends MastraVector {
441
470
  * "index not found" or "index not ready" errors on subsequent operations.
442
471
  */
443
472
  async createIndex(params) {
444
- const { indexName, dimension, metric = "cosine", filterFields, collectionName, searchIndexName, allowWrites, autoEmbed } = params;
473
+ const { indexName, dimension, metric = "cosine", filterFields, collectionName, searchIndexName, allowWrites, autoEmbed: autoEmbedParam } = params;
474
+ const autoEmbed = autoEmbedParam ?? (dimension === void 0 ? this.defaultAutoEmbed : void 0);
445
475
  let mongoMetric;
446
476
  try {
447
477
  if (autoEmbed) {
@@ -1029,7 +1059,7 @@ var MongoDBVector = class MongoDBVector extends MastraVector {
1029
1059
  vectorSearch.filter = pushed.length > 1 ? { $and: pushed } : pushed[0];
1030
1060
  }
1031
1061
  const pipeline = [{ $vectorSearch: vectorSearch }, ...this.buildProjection(metadataMode, includeVector, "vectorSearchScore", autoEmbed?.path)];
1032
- return (await collection.aggregate(pipeline).toArray()).map((result) => ({
1062
+ return (await this.aggregateVectorSearch(collection, pipeline)).map((result) => ({
1033
1063
  id: this.idToString(result._id),
1034
1064
  score: result.score,
1035
1065
  metadata: result.metadata,
@@ -1046,6 +1076,24 @@ var MongoDBVector = class MongoDBVector extends MastraVector {
1046
1076
  }
1047
1077
  }
1048
1078
  /**
1079
+ * Runs a `$vectorSearch` pipeline, retrying while the index is in INITIAL_SYNC.
1080
+ *
1081
+ * While Atlas first builds a vector search index it usually answers with an empty result, but
1082
+ * for a few seconds it fails with "cannot query vector index ... while in state INITIAL_SYNC"
1083
+ * instead. A caller that creates an index and queries it straight away, as `Memory` does on a
1084
+ * fresh database, can land in that window. Any other error, and an INITIAL_SYNC that outlasts
1085
+ * the retry budget, is thrown unchanged.
1086
+ */
1087
+ async aggregateVectorSearch(collection, pipeline) {
1088
+ for (const delayMs of MongoDBVector.INITIAL_SYNC_RETRY_DELAYS_MS) try {
1089
+ return await collection.aggregate(pipeline).toArray();
1090
+ } catch (error) {
1091
+ if (!isInitialSyncError(error)) throw error;
1092
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
1093
+ }
1094
+ return collection.aggregate(pipeline).toArray();
1095
+ }
1096
+ /**
1049
1097
  * Lists LOGICAL Mastra index names, not physical collection names.
1050
1098
  *
1051
1099
  * Returns the union of:
@@ -6700,8 +6748,11 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends MemoryStorage {
6700
6748
  if (!target) continue;
6701
6749
  const prevMessages = await collection.find({
6702
6750
  thread_id: target.threadId,
6703
- createdAt: { $lte: target.createdAt },
6704
- ...resourceFilter
6751
+ ...resourceFilter,
6752
+ $or: [{ createdAt: { $lt: target.createdAt } }, {
6753
+ createdAt: target.createdAt,
6754
+ id: { $lte: id }
6755
+ }]
6705
6756
  }).sort({
6706
6757
  createdAt: -1,
6707
6758
  id: -1
@@ -6710,8 +6761,11 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends MemoryStorage {
6710
6761
  if (withNextMessages > 0) {
6711
6762
  const nextMessages = await collection.find({
6712
6763
  thread_id: target.threadId,
6713
- createdAt: { $gt: target.createdAt },
6714
- ...resourceFilter
6764
+ ...resourceFilter,
6765
+ $or: [{ createdAt: { $gt: target.createdAt } }, {
6766
+ createdAt: target.createdAt,
6767
+ id: { $gt: id }
6768
+ }]
6715
6769
  }).sort({
6716
6770
  createdAt: 1,
6717
6771
  id: 1