@mastra/mongodb 1.16.1 → 1.17.0-alpha.1

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,59 @@
1
1
  # @mastra/mongodb
2
2
 
3
+ ## 1.17.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed resource-scoped message includes across storage adapters so included context cannot cross resource boundaries. ([#20984](https://github.com/mastra-ai/mastra/pull/20984))
8
+
9
+ - Updated dependencies [[`6445eba`](https://github.com/mastra-ai/mastra/commit/6445eba6020abac681aba1cc9289f446cb400cbe), [`df31eb0`](https://github.com/mastra-ai/mastra/commit/df31eb0c7087d782a0d9346e467f9a4af4b0eef6), [`fcd0667`](https://github.com/mastra-ai/mastra/commit/fcd0667a4e378be35c9a1b1eb19cce78fbfd7282), [`bab06b1`](https://github.com/mastra-ai/mastra/commit/bab06b18923873a584bdfc71a6b4ec7fb4727fb7)]:
10
+ - @mastra/core@1.58.0-alpha.5
11
+
12
+ ## 1.17.0-alpha.0
13
+
14
+ ### Minor Changes
15
+
16
+ - Added experiment provenance and grouping support to the LibSQL, MongoDB, MySQL, PostgreSQL, and Spanner storage adapters. These fields remain available for later grouping and filtering. ([#20645](https://github.com/mastra-ai/mastra/pull/20645))
17
+
18
+ ```ts
19
+ import { PostgresStore } from '@mastra/pg';
20
+
21
+ const storage = new PostgresStore({
22
+ id: 'postgres-storage',
23
+ connectionString: process.env.DATABASE_URL!,
24
+ });
25
+
26
+ await dataset.startExperiment({
27
+ task,
28
+ scorers,
29
+ provenance: { source: 'github', sourceVersion: 'abc123' },
30
+ grouping: { experimentSetId: 'benchmark-1', variantId: 'candidate', trialIndex: 0 },
31
+ });
32
+ ```
33
+
34
+ - Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
35
+
36
+ Previously, the paginated memory reads (`listThreads`, `listMessages`, `listMessagesByResourceId`, and `listMessagesById`) caught backend failures, logged them, and returned an empty payload like `{ threads: [], total: 0, hasMore: false }`. A transient outage (locked table, dropped connection) was therefore indistinguishable from a genuinely empty result, so an agent reading conversation history during a brief failure would treat it as "no history" and could overwrite real state. These methods now re-throw the failure as a `MastraError`. Validation (USER) errors and genuinely empty results are unchanged.
37
+
38
+ **Behavior change**
39
+
40
+ Callers that previously received an empty result on a backend failure will now receive a thrown `MastraError`. If you call these read methods directly (rather than through an agent, which already surfaces errors), wrap them so a transient outage doesn't crash the caller:
41
+
42
+ ```ts
43
+ try {
44
+ const { threads } = await storage.listThreads({ resourceId });
45
+ // ...use threads
46
+ } catch (error) {
47
+ // a real backend failure. Decide whether to retry, surface, or degrade.
48
+ // An empty thread list no longer hides here; it only means "no threads".
49
+ }
50
+ ```
51
+
52
+ ### Patch Changes
53
+
54
+ - Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
55
+ - @mastra/core@1.58.0-alpha.1
56
+
3
57
  ## 1.16.1
4
58
 
5
59
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-mongodb
3
3
  description: Documentation for @mastra/mongodb. Use when working with @mastra/mongodb APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/mongodb"
6
- version: "1.16.1"
6
+ version: "1.17.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.16.1",
2
+ "version": "1.17.0-alpha.1",
3
3
  "package": "@mastra/mongodb",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -251,6 +251,64 @@ const memoryStore = await storage.getStore('memory')
251
251
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
252
252
  ```
253
253
 
254
+ ## Closing connections
255
+
256
+ `close()` releases the connections of the stores a composite was built from: the `default` and `editor` stores, plus any domain that owns its own client. Each store is closed once, even when it backs several domains. When passed to the Mastra class, `close()` is called by `shutdown()`:
257
+
258
+ ```typescript
259
+ import { MastraCompositeStore } from '@mastra/core/storage'
260
+ import { PostgresStore } from '@mastra/pg'
261
+ import { Mastra } from '@mastra/core'
262
+
263
+ const pgStore = new PostgresStore({
264
+ id: 'pg-storage',
265
+ connectionString: process.env.DATABASE_URL,
266
+ })
267
+
268
+ export const mastra = new Mastra({
269
+ storage: new MastraCompositeStore({ id: 'composite', default: pgStore }),
270
+ })
271
+
272
+ process.on('SIGTERM', async () => {
273
+ // Releases the Postgres pool, so the process can exit
274
+ await mastra.shutdown()
275
+ })
276
+ ```
277
+
278
+ A store you construct only to supply a domain isn't reachable through the composite. Keep a reference to it and close it yourself:
279
+
280
+ ```typescript
281
+ import { MastraCompositeStore } from '@mastra/core/storage'
282
+ import { ClickhouseStore } from '@mastra/clickhouse'
283
+ import { PostgresStore } from '@mastra/pg'
284
+ import { Mastra } from '@mastra/core'
285
+
286
+ const pgStore = new PostgresStore({
287
+ id: 'pg-storage',
288
+ connectionString: process.env.DATABASE_URL,
289
+ })
290
+
291
+ const clickhouseStore = new ClickhouseStore({
292
+ id: 'clickhouse-storage',
293
+ url: process.env.CLICKHOUSE_URL,
294
+ username: process.env.CLICKHOUSE_USERNAME,
295
+ password: process.env.CLICKHOUSE_PASSWORD,
296
+ })
297
+
298
+ export const mastra = new Mastra({
299
+ storage: new MastraCompositeStore({
300
+ id: 'composite',
301
+ default: pgStore,
302
+ domains: { observability: clickhouseStore.stores?.observability },
303
+ }),
304
+ })
305
+
306
+ process.on('SIGTERM', async () => {
307
+ await mastra.shutdown()
308
+ await clickhouseStore.close()
309
+ })
310
+ ```
311
+
254
312
  ## Use cases
255
313
 
256
314
  ### Separate databases for different workloads
package/dist/index.cjs CHANGED
@@ -10,7 +10,7 @@ let _mastra_core_agent = require("@mastra/core/agent");
10
10
  let _mastra_core_evals = require("@mastra/core/evals");
11
11
  let _mastra_core_storage_domains_skills = require("@mastra/core/storage/domains/skills");
12
12
  //#region package.json
13
- var version = "1.16.1";
13
+ var version = "1.17.0-alpha.1";
14
14
  //#endregion
15
15
  //#region src/vector/filter.ts
16
16
  /**
@@ -3667,6 +3667,12 @@ function transformExperimentRow(row) {
3667
3667
  name: row.name ?? void 0,
3668
3668
  description: row.description ?? void 0,
3669
3669
  metadata: parseJsonField(row.metadata) ?? void 0,
3670
+ provenance: parseJsonField(row.provenance) ?? null,
3671
+ runnerAttestation: parseJsonField(row.runnerAttestation) ?? null,
3672
+ experimentSetId: row.experimentSetId ?? null,
3673
+ comparisonId: row.comparisonId ?? null,
3674
+ variantId: row.variantId ?? null,
3675
+ trialIndex: row.trialIndex != null ? Number(row.trialIndex) : null,
3670
3676
  datasetId: row.datasetId ?? null,
3671
3677
  datasetVersion: row.datasetVersion != null ? Number(row.datasetVersion) : null,
3672
3678
  organizationId: row.organizationId ?? null,
@@ -3813,6 +3819,15 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
3813
3819
  id: 1
3814
3820
  }
3815
3821
  },
3822
+ {
3823
+ collection: _mastra_core_storage.TABLE_EXPERIMENTS,
3824
+ keys: {
3825
+ experimentSetId: 1,
3826
+ comparisonId: 1,
3827
+ variantId: 1,
3828
+ trialIndex: 1
3829
+ }
3830
+ },
3816
3831
  {
3817
3832
  collection: _mastra_core_storage.TABLE_EXPERIMENTS,
3818
3833
  keys: {
@@ -3886,6 +3901,12 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
3886
3901
  name: input.name ?? null,
3887
3902
  description: input.description ?? null,
3888
3903
  metadata: input.metadata ?? null,
3904
+ provenance: input.provenance ?? null,
3905
+ runnerAttestation: input.runnerAttestation ?? null,
3906
+ experimentSetId: input.experimentSetId ?? null,
3907
+ comparisonId: input.comparisonId ?? null,
3908
+ variantId: input.variantId ?? null,
3909
+ trialIndex: input.trialIndex ?? null,
3889
3910
  datasetId: input.datasetId ?? null,
3890
3911
  datasetVersion: input.datasetVersion ?? null,
3891
3912
  organizationId: input.organizationId ?? null,
@@ -3905,28 +3926,7 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
3905
3926
  };
3906
3927
  try {
3907
3928
  await (await this.getCollection(_mastra_core_storage.TABLE_EXPERIMENTS)).insertOne(doc);
3908
- return {
3909
- id,
3910
- name: input.name,
3911
- description: input.description,
3912
- metadata: input.metadata,
3913
- datasetId: input.datasetId ?? null,
3914
- datasetVersion: input.datasetVersion ?? null,
3915
- organizationId: input.organizationId ?? null,
3916
- projectId: input.projectId ?? null,
3917
- targetType: input.targetType,
3918
- targetId: input.targetId,
3919
- status: "pending",
3920
- totalItems: input.totalItems,
3921
- succeededCount: 0,
3922
- failedCount: 0,
3923
- skippedCount: 0,
3924
- agentVersion: input.agentVersion ?? null,
3925
- startedAt: null,
3926
- completedAt: null,
3927
- createdAt: now,
3928
- updatedAt: now
3929
- };
3929
+ return transformExperimentRow(structuredClone(doc));
3930
3930
  } catch (error) {
3931
3931
  throw new _mastra_core_error.MastraError({
3932
3932
  id: (0, _mastra_core_storage.createStorageErrorId)("MONGODB", "CREATE_EXPERIMENT", "FAILED"),
@@ -3993,6 +3993,10 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
3993
3993
  if (args.targetId) filter.targetId = args.targetId;
3994
3994
  if (args.agentVersion) filter.agentVersion = args.agentVersion;
3995
3995
  if (args.status) filter.status = args.status;
3996
+ if (args.experimentSetId !== void 0) filter.experimentSetId = args.experimentSetId;
3997
+ if (args.comparisonId !== void 0) filter.comparisonId = args.comparisonId;
3998
+ if (args.variantId !== void 0) filter.variantId = args.variantId;
3999
+ if (args.trialIndex !== void 0) filter.trialIndex = args.trialIndex;
3996
4000
  if (args.filters) {
3997
4001
  const { organizationId, projectId } = args.filters;
3998
4002
  if (organizationId !== void 0) filter.organizationId = organizationId;
@@ -5401,12 +5405,23 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5401
5405
  return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
5402
5406
  });
5403
5407
  }
5404
- async _getIncludedMessages({ include }) {
5408
+ /**
5409
+ * Fetches the messages named by `include` together with their surrounding context.
5410
+ *
5411
+ * @param include - Message ids to pin, each with an optional before/after window.
5412
+ * @param resourceId - When set, restricts both the pinned messages and their context
5413
+ * to that resource so an id from another resource returns nothing.
5414
+ */
5415
+ async _getIncludedMessages({ include, resourceId }) {
5405
5416
  if (!include || include.length === 0) return null;
5406
5417
  const collection = await this.getCollection(_mastra_core_storage.TABLE_MESSAGES);
5418
+ const resourceFilter = resourceId ? { resourceId } : {};
5407
5419
  const targetIds = include.map((inc) => inc.id).filter(Boolean);
5408
5420
  if (targetIds.length === 0) return null;
5409
- const targetDocs = await collection.find({ id: { $in: targetIds } }, { projection: {
5421
+ const targetDocs = await collection.find({
5422
+ id: { $in: targetIds },
5423
+ ...resourceFilter
5424
+ }, { projection: {
5410
5425
  id: 1,
5411
5426
  thread_id: 1,
5412
5427
  createdAt: 1
@@ -5423,7 +5438,8 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5423
5438
  if (!target) continue;
5424
5439
  const prevMessages = await collection.find({
5425
5440
  thread_id: target.threadId,
5426
- createdAt: { $lte: target.createdAt }
5441
+ createdAt: { $lte: target.createdAt },
5442
+ ...resourceFilter
5427
5443
  }).sort({
5428
5444
  createdAt: -1,
5429
5445
  id: -1
@@ -5432,7 +5448,8 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5432
5448
  if (withNextMessages > 0) {
5433
5449
  const nextMessages = await collection.find({
5434
5450
  thread_id: target.threadId,
5435
- createdAt: { $gt: target.createdAt }
5451
+ createdAt: { $gt: target.createdAt },
5452
+ ...resourceFilter
5436
5453
  }).sort({
5437
5454
  createdAt: 1,
5438
5455
  id: 1
@@ -5507,7 +5524,10 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5507
5524
  hasMore: false
5508
5525
  };
5509
5526
  if (perPage === 0 && include && include.length > 0) {
5510
- const includeMessages = await this._getIncludedMessages({ include });
5527
+ const includeMessages = await this._getIncludedMessages({
5528
+ include,
5529
+ resourceId
5530
+ });
5511
5531
  const list = new _mastra_core_agent.MessageList().add(includeMessages ?? [], "memory");
5512
5532
  return {
5513
5533
  messages: this._sortMessages(list.get.all.db(), field, direction),
@@ -5543,7 +5563,10 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5543
5563
  };
5544
5564
  const messageIds = new Set(messages.map((m) => m.id));
5545
5565
  if (include && include.length > 0) {
5546
- const includeMessages = await this._getIncludedMessages({ include });
5566
+ const includeMessages = await this._getIncludedMessages({
5567
+ include,
5568
+ resourceId
5569
+ });
5547
5570
  if (includeMessages) {
5548
5571
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
5549
5572
  messages.push(includeMsg);
@@ -5564,6 +5587,7 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5564
5587
  hasMore
5565
5588
  };
5566
5589
  } catch (error) {
5590
+ if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
5567
5591
  const mastraError = new _mastra_core_error.MastraError({
5568
5592
  id: (0, _mastra_core_storage.createStorageErrorId)("MONGODB", "LIST_MESSAGES", "FAILED"),
5569
5593
  domain: _mastra_core_error.ErrorDomain.STORAGE,
@@ -5575,13 +5599,7 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5575
5599
  }, error);
5576
5600
  this.logger?.error?.(mastraError.toString());
5577
5601
  this.logger?.trackException?.(mastraError);
5578
- return {
5579
- messages: [],
5580
- total: 0,
5581
- page,
5582
- perPage: perPageForResponse,
5583
- hasMore: false
5584
- };
5602
+ throw mastraError;
5585
5603
  }
5586
5604
  }
5587
5605
  async listMessagesByResourceId(args) {
@@ -5629,7 +5647,10 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5629
5647
  hasMore: false
5630
5648
  };
5631
5649
  if (perPage === 0 && include && include.length > 0) {
5632
- const includeMessages = await this._getIncludedMessages({ include });
5650
+ const includeMessages = await this._getIncludedMessages({
5651
+ include,
5652
+ resourceId
5653
+ });
5633
5654
  if (!includeMessages || includeMessages.length === 0) return {
5634
5655
  messages: [],
5635
5656
  total: 0,
@@ -5672,7 +5693,10 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5672
5693
  };
5673
5694
  const messageIds = new Set(messages.map((m) => m.id));
5674
5695
  if (include && include.length > 0) {
5675
- const includeMessages = await this._getIncludedMessages({ include });
5696
+ const includeMessages = await this._getIncludedMessages({
5697
+ include,
5698
+ resourceId
5699
+ });
5676
5700
  if (includeMessages) {
5677
5701
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
5678
5702
  messages.push(includeMsg);
@@ -5691,6 +5715,7 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5691
5715
  hasMore
5692
5716
  };
5693
5717
  } catch (error) {
5718
+ if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
5694
5719
  const mastraError = new _mastra_core_error.MastraError({
5695
5720
  id: (0, _mastra_core_storage.createStorageErrorId)("MONGODB", "LIST_MESSAGES_BY_RESOURCE_ID", "FAILED"),
5696
5721
  domain: _mastra_core_error.ErrorDomain.STORAGE,
@@ -5699,13 +5724,7 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5699
5724
  }, error);
5700
5725
  this.logger?.error?.(mastraError.toString());
5701
5726
  this.logger?.trackException?.(mastraError);
5702
- return {
5703
- messages: [],
5704
- total: 0,
5705
- page,
5706
- perPage: perPageForResponse,
5707
- hasMore: false
5708
- };
5727
+ throw mastraError;
5709
5728
  }
5710
5729
  }
5711
5730
  async saveMessages({ messages }) {
@@ -5939,7 +5958,8 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5939
5958
  hasMore: perPageInput === false ? false : offset + perPage < total
5940
5959
  };
5941
5960
  } catch (error) {
5942
- throw new _mastra_core_error.MastraError({
5961
+ if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
5962
+ const mastraError = new _mastra_core_error.MastraError({
5943
5963
  id: (0, _mastra_core_storage.createStorageErrorId)("MONGODB", "LIST_THREADS", "FAILED"),
5944
5964
  domain: _mastra_core_error.ErrorDomain.STORAGE,
5945
5965
  category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
@@ -5948,6 +5968,9 @@ var MemoryStorageMongoDB = class MemoryStorageMongoDB extends _mastra_core_stora
5948
5968
  hasMetadataFilter: !!filter?.metadata
5949
5969
  }
5950
5970
  }, error);
5971
+ this.logger?.error?.(mastraError.toString());
5972
+ this.logger?.trackException?.(mastraError);
5973
+ throw mastraError;
5951
5974
  }
5952
5975
  }
5953
5976
  async saveThread({ thread }) {