@mastra/mongodb 0.0.0-vnextAgentNetwork-20250602084555 → 0.0.0-workflow-deno-20250616115451

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.
@@ -0,0 +1,23 @@
1
+
2
+ > @mastra/mongodb@0.11.0-alpha.1 build /home/runner/work/mastra/mastra/stores/mongodb
3
+ > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
+
5
+ CLI Building entry: src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.5.0
8
+ TSC Build start
9
+ TSC ⚡️ Build success in 9462ms
10
+ DTS Build start
11
+ CLI Target: es2022
12
+ Analysis will use the bundled TypeScript version 5.8.3
13
+ Writing package typings: /home/runner/work/mastra/mastra/stores/mongodb/dist/_tsup-dts-rollup.d.ts
14
+ Analysis will use the bundled TypeScript version 5.8.3
15
+ Writing package typings: /home/runner/work/mastra/mastra/stores/mongodb/dist/_tsup-dts-rollup.d.cts
16
+ DTS ⚡️ Build success in 11575ms
17
+ CLI Cleaning output folder
18
+ ESM Build start
19
+ CJS Build start
20
+ ESM dist/index.js 33.93 KB
21
+ ESM ⚡️ Build success in 1213ms
22
+ CJS dist/index.cjs 34.07 KB
23
+ CJS ⚡️ Build success in 1213ms
package/CHANGELOG.md CHANGED
@@ -1,11 +1,157 @@
1
1
  # @mastra/mongodb
2
2
 
3
- ## 0.0.0-vnextAgentNetwork-20250602084555
3
+ ## 0.0.0-workflow-deno-20250616115451
4
+
5
+ ### Minor Changes
6
+
7
+ - 704d1ca: Thread Timestamp Auto-Update Enhancement
8
+ Added automatic thread updatedAt timestamp updates when messages are saved across all storage providers
9
+ Enhanced user experience: Threads now accurately reflect their latest activity with automatic timestamp updates when new messages are added
10
+ Universal implementation: Consistent behavior across all 7 storage backends (ClickHouse, Cloudflare D1, DynamoDB, MongoDB, PostgreSQL, Upstash, LibSQL)
11
+ Performance optimized: Updates execute in parallel with message saving operations for minimal performance impact
12
+ Backwards compatible: No breaking changes - existing code continues to work unchanged
13
+ Improved conversation ordering: Chat interfaces can now properly sort threads by actual last activity
14
+ This enhancement resolves the issue where active conversations appeared stale due to outdated thread timestamps, providing better conversation management and user experience in chat applications.
15
+
16
+ ### Patch Changes
17
+
18
+ - 63f6b7d: dependencies updates:
19
+ - Updated dependency [`cloudflare@^4.3.0` ↗︎](https://www.npmjs.com/package/cloudflare/v/4.3.0) (from `^4.1.0`, in `dependencies`)
20
+ - Updated dependency [`mongodb@^6.17.0` ↗︎](https://www.npmjs.com/package/mongodb/v/6.17.0) (from `^6.15.0`, in `dependencies`)
21
+ - Updated dependencies [63f6b7d]
22
+ - Updated dependencies [ee9af57]
23
+ - Updated dependencies [36f1c36]
24
+ - Updated dependencies [10d352e]
25
+ - Updated dependencies [3ca9a67]
26
+ - Updated dependencies [53d3c37]
27
+ - Updated dependencies [577ce3a]
28
+ - Updated dependencies [9260b3a]
29
+ - @mastra/core@0.0.0-workflow-deno-20250616115451
30
+
31
+ ## 0.11.0-alpha.1
32
+
33
+ ### Minor Changes
34
+
35
+ - 704d1ca: Thread Timestamp Auto-Update Enhancement
36
+ Added automatic thread updatedAt timestamp updates when messages are saved across all storage providers
37
+ Enhanced user experience: Threads now accurately reflect their latest activity with automatic timestamp updates when new messages are added
38
+ Universal implementation: Consistent behavior across all 7 storage backends (ClickHouse, Cloudflare D1, DynamoDB, MongoDB, PostgreSQL, Upstash, LibSQL)
39
+ Performance optimized: Updates execute in parallel with message saving operations for minimal performance impact
40
+ Backwards compatible: No breaking changes - existing code continues to work unchanged
41
+ Improved conversation ordering: Chat interfaces can now properly sort threads by actual last activity
42
+ This enhancement resolves the issue where active conversations appeared stale due to outdated thread timestamps, providing better conversation management and user experience in chat applications.
43
+
44
+ ## 0.10.4-alpha.0
45
+
46
+ ### Patch Changes
47
+
48
+ - 63f6b7d: dependencies updates:
49
+ - Updated dependency [`cloudflare@^4.3.0` ↗︎](https://www.npmjs.com/package/cloudflare/v/4.3.0) (from `^4.1.0`, in `dependencies`)
50
+ - Updated dependency [`mongodb@^6.17.0` ↗︎](https://www.npmjs.com/package/mongodb/v/6.17.0) (from `^6.15.0`, in `dependencies`)
51
+ - Updated dependencies [63f6b7d]
52
+ - Updated dependencies [36f1c36]
53
+ - Updated dependencies [10d352e]
54
+ - Updated dependencies [53d3c37]
55
+ - @mastra/core@0.10.6-alpha.0
56
+
57
+ ## 0.10.3
58
+
59
+ ### Patch Changes
60
+
61
+ - dffb67b: updated stores to add alter table and change tests
62
+ - 925ab94: added paginated functions to base class and added boilerplate and updated imports
63
+ - e030ea3: Added missing format compatibility to MongoDB getMessages() method
64
+ - 66f4424: Update peerdeps
65
+ - Updated dependencies [d1ed912]
66
+ - Updated dependencies [f6fd25f]
67
+ - Updated dependencies [dffb67b]
68
+ - Updated dependencies [f1f1f1b]
69
+ - Updated dependencies [925ab94]
70
+ - Updated dependencies [f9816ae]
71
+ - Updated dependencies [82090c1]
72
+ - Updated dependencies [1b443fd]
73
+ - Updated dependencies [ce97900]
74
+ - Updated dependencies [f1309d3]
75
+ - Updated dependencies [14a2566]
76
+ - Updated dependencies [f7f8293]
77
+ - Updated dependencies [48eddb9]
78
+ - @mastra/core@0.10.4
79
+
80
+ ## 0.10.3-alpha.2
81
+
82
+ ### Patch Changes
83
+
84
+ - 66f4424: Update peerdeps
85
+
86
+ ## 0.10.3-alpha.1
87
+
88
+ ### Patch Changes
89
+
90
+ - 925ab94: added paginated functions to base class and added boilerplate and updated imports
91
+ - Updated dependencies [925ab94]
92
+ - @mastra/core@0.10.4-alpha.3
93
+
94
+ ## 0.10.3-alpha.0
95
+
96
+ ### Patch Changes
97
+
98
+ - dffb67b: updated stores to add alter table and change tests
99
+ - e030ea3: Added missing format compatibility to MongoDB getMessages() method
100
+ - Updated dependencies [f6fd25f]
101
+ - Updated dependencies [dffb67b]
102
+ - Updated dependencies [f1309d3]
103
+ - Updated dependencies [f7f8293]
104
+ - @mastra/core@0.10.4-alpha.1
105
+
106
+ ## 0.10.2
107
+
108
+ ### Patch Changes
109
+
110
+ - c5bf1ce: Add backwards compat code for new MessageList in storage
111
+ - f0d559f: Fix peerdeps for alpha channel
112
+ - Updated dependencies [ee77e78]
113
+ - Updated dependencies [592a2db]
114
+ - Updated dependencies [e5dc18d]
115
+ - Updated dependencies [ab5adbe]
116
+ - Updated dependencies [1e8bb40]
117
+ - Updated dependencies [1b5fc55]
118
+ - Updated dependencies [195c428]
119
+ - Updated dependencies [f73e11b]
120
+ - Updated dependencies [37643b8]
121
+ - Updated dependencies [99fd6cf]
122
+ - Updated dependencies [c5bf1ce]
123
+ - Updated dependencies [add596e]
124
+ - Updated dependencies [8dc94d8]
125
+ - Updated dependencies [ecebbeb]
126
+ - Updated dependencies [79d5145]
127
+ - Updated dependencies [12b7002]
128
+ - Updated dependencies [2901125]
129
+ - @mastra/core@0.10.2
130
+
131
+ ## 0.10.2-alpha.1
132
+
133
+ ### Patch Changes
134
+
135
+ - c5bf1ce: Add backwards compat code for new MessageList in storage
136
+ - Updated dependencies [c5bf1ce]
137
+ - Updated dependencies [12b7002]
138
+ - @mastra/core@0.10.2-alpha.4
139
+
140
+ ## 0.10.2-alpha.0
141
+
142
+ ### Patch Changes
143
+
144
+ - f0d559f: Fix peerdeps for alpha channel
145
+ - Updated dependencies [1e8bb40]
146
+ - @mastra/core@0.10.2-alpha.2
147
+
148
+ ## 0.10.1
4
149
 
5
150
  ### Patch Changes
6
151
 
7
152
  - 4a8cd1c: MongoDBStore option support
8
153
  - fcc915f: Support MongoDB database as store
154
+ - Updated dependencies [d70b807]
9
155
  - Updated dependencies [6d16390]
10
156
  - Updated dependencies [1e4a421]
11
157
  - Updated dependencies [200d0da]
@@ -14,7 +160,21 @@
14
160
  - Updated dependencies [38aee50]
15
161
  - Updated dependencies [5c41100]
16
162
  - Updated dependencies [d6a759b]
17
- - @mastra/core@0.0.0-vnextAgentNetwork-20250602084555
163
+ - Updated dependencies [6015bdf]
164
+ - @mastra/core@0.10.1
165
+
166
+ ## 0.10.1-alpha.1
167
+
168
+ ### Patch Changes
169
+
170
+ - 4a8cd1c: MongoDBStore option support
171
+ - Updated dependencies [200d0da]
172
+ - Updated dependencies [bf5f17b]
173
+ - Updated dependencies [5343f93]
174
+ - Updated dependencies [38aee50]
175
+ - Updated dependencies [5c41100]
176
+ - Updated dependencies [d6a759b]
177
+ - @mastra/core@0.10.1-alpha.1
18
178
 
19
179
  ## 0.10.1-alpha.0
20
180
 
@@ -5,16 +5,21 @@ import type { DeleteVectorParams } from '@mastra/core/vector';
5
5
  import type { DescribeIndexParams } from '@mastra/core/vector';
6
6
  import type { EvalRow } from '@mastra/core/storage';
7
7
  import type { IndexStats } from '@mastra/core/vector';
8
+ import type { MastraMessageV1 } from '@mastra/core/memory';
9
+ import type { MastraMessageV2 } from '@mastra/core/memory';
8
10
  import { MastraStorage } from '@mastra/core/storage';
9
11
  import { MastraVector } from '@mastra/core/vector';
10
- import type { MessageType } from '@mastra/core/memory';
11
12
  import type { MongoClientOptions } from 'mongodb';
12
13
  import type { OperatorSupport } from '@mastra/core/vector/filter';
14
+ import type { PaginationInfo } from '@mastra/core/storage';
13
15
  import type { QueryResult } from '@mastra/core/vector';
14
16
  import type { QueryVectorParams } from '@mastra/core/vector';
17
+ import type { StorageColumn } from '@mastra/core/storage';
15
18
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
19
+ import type { StorageGetTracesArg } from '@mastra/core/storage';
16
20
  import type { StorageThreadType } from '@mastra/core/memory';
17
21
  import type { TABLE_NAMES } from '@mastra/core/storage';
22
+ import type { Trace } from '@mastra/core/telemetry';
18
23
  import type { UpdateVectorParams } from '@mastra/core/vector';
19
24
  import type { UpsertVectorParams } from '@mastra/core/vector';
20
25
  import type { VectorFilter } from '@mastra/core/vector/filter';
@@ -70,6 +75,17 @@ declare class MongoDBStore extends MastraStorage {
70
75
  private getConnection;
71
76
  private getCollection;
72
77
  createTable(): Promise<void>;
78
+ /**
79
+ * No-op: This backend is schemaless and does not require schema changes.
80
+ * @param tableName Name of the table
81
+ * @param schema Schema of the table
82
+ * @param ifNotExists Array of column names to add if they don't exist
83
+ */
84
+ alterTable(_args: {
85
+ tableName: TABLE_NAMES;
86
+ schema: Record<string, StorageColumn>;
87
+ ifNotExists: string[];
88
+ }): Promise<void>;
73
89
  clearTable({ tableName }: {
74
90
  tableName: TABLE_NAMES;
75
91
  }): Promise<void>;
@@ -102,10 +118,20 @@ declare class MongoDBStore extends MastraStorage {
102
118
  deleteThread({ threadId }: {
103
119
  threadId: string;
104
120
  }): Promise<void>;
105
- getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]>;
106
- saveMessages({ messages }: {
107
- messages: MessageType[];
108
- }): Promise<MessageType[]>;
121
+ getMessages(args: StorageGetMessagesArg & {
122
+ format?: 'v1';
123
+ }): Promise<MastraMessageV1[]>;
124
+ getMessages(args: StorageGetMessagesArg & {
125
+ format: 'v2';
126
+ }): Promise<MastraMessageV2[]>;
127
+ saveMessages(args: {
128
+ messages: MastraMessageV1[];
129
+ format?: undefined | 'v1';
130
+ }): Promise<MastraMessageV1[]>;
131
+ saveMessages(args: {
132
+ messages: MastraMessageV2[];
133
+ format: 'v2';
134
+ }): Promise<MastraMessageV2[]>;
109
135
  getTraces({ name, scope, page, perPage, attributes, filters, }?: {
110
136
  name?: string;
111
137
  scope?: string;
@@ -147,6 +173,19 @@ declare class MongoDBStore extends MastraStorage {
147
173
  private parseWorkflowRun;
148
174
  private parseRow;
149
175
  private transformEvalRow;
176
+ getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & {
177
+ traces: Trace[];
178
+ }>;
179
+ getThreadsByResourceIdPaginated(_args: {
180
+ resourceId: string;
181
+ page?: number;
182
+ perPage?: number;
183
+ }): Promise<PaginationInfo & {
184
+ threads: StorageThreadType[];
185
+ }>;
186
+ getMessagesPaginated(_args: StorageGetMessagesArg): Promise<PaginationInfo & {
187
+ messages: MastraMessageV1[] | MastraMessageV2[];
188
+ }>;
150
189
  close(): Promise<void>;
151
190
  }
152
191
  export { MongoDBStore }
@@ -5,16 +5,21 @@ import type { DeleteVectorParams } from '@mastra/core/vector';
5
5
  import type { DescribeIndexParams } from '@mastra/core/vector';
6
6
  import type { EvalRow } from '@mastra/core/storage';
7
7
  import type { IndexStats } from '@mastra/core/vector';
8
+ import type { MastraMessageV1 } from '@mastra/core/memory';
9
+ import type { MastraMessageV2 } from '@mastra/core/memory';
8
10
  import { MastraStorage } from '@mastra/core/storage';
9
11
  import { MastraVector } from '@mastra/core/vector';
10
- import type { MessageType } from '@mastra/core/memory';
11
12
  import type { MongoClientOptions } from 'mongodb';
12
13
  import type { OperatorSupport } from '@mastra/core/vector/filter';
14
+ import type { PaginationInfo } from '@mastra/core/storage';
13
15
  import type { QueryResult } from '@mastra/core/vector';
14
16
  import type { QueryVectorParams } from '@mastra/core/vector';
17
+ import type { StorageColumn } from '@mastra/core/storage';
15
18
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
19
+ import type { StorageGetTracesArg } from '@mastra/core/storage';
16
20
  import type { StorageThreadType } from '@mastra/core/memory';
17
21
  import type { TABLE_NAMES } from '@mastra/core/storage';
22
+ import type { Trace } from '@mastra/core/telemetry';
18
23
  import type { UpdateVectorParams } from '@mastra/core/vector';
19
24
  import type { UpsertVectorParams } from '@mastra/core/vector';
20
25
  import type { VectorFilter } from '@mastra/core/vector/filter';
@@ -70,6 +75,17 @@ declare class MongoDBStore extends MastraStorage {
70
75
  private getConnection;
71
76
  private getCollection;
72
77
  createTable(): Promise<void>;
78
+ /**
79
+ * No-op: This backend is schemaless and does not require schema changes.
80
+ * @param tableName Name of the table
81
+ * @param schema Schema of the table
82
+ * @param ifNotExists Array of column names to add if they don't exist
83
+ */
84
+ alterTable(_args: {
85
+ tableName: TABLE_NAMES;
86
+ schema: Record<string, StorageColumn>;
87
+ ifNotExists: string[];
88
+ }): Promise<void>;
73
89
  clearTable({ tableName }: {
74
90
  tableName: TABLE_NAMES;
75
91
  }): Promise<void>;
@@ -102,10 +118,20 @@ declare class MongoDBStore extends MastraStorage {
102
118
  deleteThread({ threadId }: {
103
119
  threadId: string;
104
120
  }): Promise<void>;
105
- getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]>;
106
- saveMessages({ messages }: {
107
- messages: MessageType[];
108
- }): Promise<MessageType[]>;
121
+ getMessages(args: StorageGetMessagesArg & {
122
+ format?: 'v1';
123
+ }): Promise<MastraMessageV1[]>;
124
+ getMessages(args: StorageGetMessagesArg & {
125
+ format: 'v2';
126
+ }): Promise<MastraMessageV2[]>;
127
+ saveMessages(args: {
128
+ messages: MastraMessageV1[];
129
+ format?: undefined | 'v1';
130
+ }): Promise<MastraMessageV1[]>;
131
+ saveMessages(args: {
132
+ messages: MastraMessageV2[];
133
+ format: 'v2';
134
+ }): Promise<MastraMessageV2[]>;
109
135
  getTraces({ name, scope, page, perPage, attributes, filters, }?: {
110
136
  name?: string;
111
137
  scope?: string;
@@ -147,6 +173,19 @@ declare class MongoDBStore extends MastraStorage {
147
173
  private parseWorkflowRun;
148
174
  private parseRow;
149
175
  private transformEvalRow;
176
+ getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & {
177
+ traces: Trace[];
178
+ }>;
179
+ getThreadsByResourceIdPaginated(_args: {
180
+ resourceId: string;
181
+ page?: number;
182
+ perPage?: number;
183
+ }): Promise<PaginationInfo & {
184
+ threads: StorageThreadType[];
185
+ }>;
186
+ getMessagesPaginated(_args: StorageGetMessagesArg): Promise<PaginationInfo & {
187
+ messages: MastraMessageV1[] | MastraMessageV2[];
188
+ }>;
150
189
  close(): Promise<void>;
151
190
  }
152
191
  export { MongoDBStore }
package/dist/index.cjs CHANGED
@@ -4,6 +4,7 @@ var vector = require('@mastra/core/vector');
4
4
  var mongodb = require('mongodb');
5
5
  var uuid = require('uuid');
6
6
  var filter = require('@mastra/core/vector/filter');
7
+ var agent = require('@mastra/core/agent');
7
8
  var storage = require('@mastra/core/storage');
8
9
 
9
10
  // src/vector/index.ts
@@ -446,6 +447,14 @@ var MongoDBStore = class extends storage.MastraStorage {
446
447
  }
447
448
  async createTable() {
448
449
  }
450
+ /**
451
+ * No-op: This backend is schemaless and does not require schema changes.
452
+ * @param tableName Name of the table
453
+ * @param schema Schema of the table
454
+ * @param ifNotExists Array of column names to add if they don't exist
455
+ */
456
+ async alterTable(_args) {
457
+ }
449
458
  async clearTable({ tableName }) {
450
459
  try {
451
460
  const collection = await this.getCollection(tableName);
@@ -583,7 +592,11 @@ var MongoDBStore = class extends storage.MastraStorage {
583
592
  throw error;
584
593
  }
585
594
  }
586
- async getMessages({ threadId, selectBy }) {
595
+ async getMessages({
596
+ threadId,
597
+ selectBy,
598
+ format
599
+ }) {
587
600
  try {
588
601
  const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
589
602
  const include = selectBy?.include || [];
@@ -622,13 +635,18 @@ var MongoDBStore = class extends storage.MastraStorage {
622
635
  }
623
636
  }
624
637
  messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
625
- return messages.slice(0, limit);
638
+ const list = new agent.MessageList().add(messages.slice(0, limit), "memory");
639
+ if (format === `v2`) return list.get.all.v2();
640
+ return list.get.all.v1();
626
641
  } catch (error) {
627
642
  this.logger.error("Error getting messages:", error);
628
643
  throw error;
629
644
  }
630
645
  }
631
- async saveMessages({ messages }) {
646
+ async saveMessages({
647
+ messages,
648
+ format
649
+ }) {
632
650
  if (!messages.length) {
633
651
  return messages;
634
652
  }
@@ -651,8 +669,14 @@ var MongoDBStore = class extends storage.MastraStorage {
651
669
  };
652
670
  });
653
671
  const collection = await this.getCollection(storage.TABLE_MESSAGES);
654
- await collection.insertMany(messagesToInsert);
655
- return messages;
672
+ const threadsCollection = await this.getCollection(storage.TABLE_THREADS);
673
+ await Promise.all([
674
+ collection.insertMany(messagesToInsert),
675
+ threadsCollection.updateOne({ id: threadId }, { $set: { updatedAt: /* @__PURE__ */ new Date() } })
676
+ ]);
677
+ const list = new agent.MessageList().add(messages, "memory");
678
+ if (format === `v2`) return list.get.all.v2();
679
+ return list.get.all.v1();
656
680
  } catch (error) {
657
681
  this.logger.error("Failed to save messages in database: " + error?.message);
658
682
  throw error;
@@ -892,7 +916,8 @@ var MongoDBStore = class extends storage.MastraStorage {
892
916
  role: row.role,
893
917
  type: row.type,
894
918
  createdAt: new Date(row.createdAt),
895
- threadId: row.thread_id
919
+ threadId: row.thread_id,
920
+ resourceId: row.resourceId
896
921
  };
897
922
  }
898
923
  transformEvalRow(row) {
@@ -917,6 +942,15 @@ var MongoDBStore = class extends storage.MastraStorage {
917
942
  createdAt: row.created_at
918
943
  };
919
944
  }
945
+ async getTracesPaginated(_args) {
946
+ throw new Error("Method not implemented.");
947
+ }
948
+ async getThreadsByResourceIdPaginated(_args) {
949
+ throw new Error("Method not implemented.");
950
+ }
951
+ async getMessagesPaginated(_args) {
952
+ throw new Error("Method not implemented.");
953
+ }
920
954
  async close() {
921
955
  await this.#client.close();
922
956
  }
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ import { MastraVector } from '@mastra/core/vector';
2
2
  import { MongoClient } from 'mongodb';
3
3
  import { v4 } from 'uuid';
4
4
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
5
+ import { MessageList } from '@mastra/core/agent';
5
6
  import { MastraStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_TRACES, TABLE_WORKFLOW_SNAPSHOT, TABLE_EVALS } from '@mastra/core/storage';
6
7
 
7
8
  // src/vector/index.ts
@@ -444,6 +445,14 @@ var MongoDBStore = class extends MastraStorage {
444
445
  }
445
446
  async createTable() {
446
447
  }
448
+ /**
449
+ * No-op: This backend is schemaless and does not require schema changes.
450
+ * @param tableName Name of the table
451
+ * @param schema Schema of the table
452
+ * @param ifNotExists Array of column names to add if they don't exist
453
+ */
454
+ async alterTable(_args) {
455
+ }
447
456
  async clearTable({ tableName }) {
448
457
  try {
449
458
  const collection = await this.getCollection(tableName);
@@ -581,7 +590,11 @@ var MongoDBStore = class extends MastraStorage {
581
590
  throw error;
582
591
  }
583
592
  }
584
- async getMessages({ threadId, selectBy }) {
593
+ async getMessages({
594
+ threadId,
595
+ selectBy,
596
+ format
597
+ }) {
585
598
  try {
586
599
  const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
587
600
  const include = selectBy?.include || [];
@@ -620,13 +633,18 @@ var MongoDBStore = class extends MastraStorage {
620
633
  }
621
634
  }
622
635
  messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
623
- return messages.slice(0, limit);
636
+ const list = new MessageList().add(messages.slice(0, limit), "memory");
637
+ if (format === `v2`) return list.get.all.v2();
638
+ return list.get.all.v1();
624
639
  } catch (error) {
625
640
  this.logger.error("Error getting messages:", error);
626
641
  throw error;
627
642
  }
628
643
  }
629
- async saveMessages({ messages }) {
644
+ async saveMessages({
645
+ messages,
646
+ format
647
+ }) {
630
648
  if (!messages.length) {
631
649
  return messages;
632
650
  }
@@ -649,8 +667,14 @@ var MongoDBStore = class extends MastraStorage {
649
667
  };
650
668
  });
651
669
  const collection = await this.getCollection(TABLE_MESSAGES);
652
- await collection.insertMany(messagesToInsert);
653
- return messages;
670
+ const threadsCollection = await this.getCollection(TABLE_THREADS);
671
+ await Promise.all([
672
+ collection.insertMany(messagesToInsert),
673
+ threadsCollection.updateOne({ id: threadId }, { $set: { updatedAt: /* @__PURE__ */ new Date() } })
674
+ ]);
675
+ const list = new MessageList().add(messages, "memory");
676
+ if (format === `v2`) return list.get.all.v2();
677
+ return list.get.all.v1();
654
678
  } catch (error) {
655
679
  this.logger.error("Failed to save messages in database: " + error?.message);
656
680
  throw error;
@@ -890,7 +914,8 @@ var MongoDBStore = class extends MastraStorage {
890
914
  role: row.role,
891
915
  type: row.type,
892
916
  createdAt: new Date(row.createdAt),
893
- threadId: row.thread_id
917
+ threadId: row.thread_id,
918
+ resourceId: row.resourceId
894
919
  };
895
920
  }
896
921
  transformEvalRow(row) {
@@ -915,6 +940,15 @@ var MongoDBStore = class extends MastraStorage {
915
940
  createdAt: row.created_at
916
941
  };
917
942
  }
943
+ async getTracesPaginated(_args) {
944
+ throw new Error("Method not implemented.");
945
+ }
946
+ async getThreadsByResourceIdPaginated(_args) {
947
+ throw new Error("Method not implemented.");
948
+ }
949
+ async getMessagesPaginated(_args) {
950
+ throw new Error("Method not implemented.");
951
+ }
918
952
  async close() {
919
953
  await this.#client.close();
920
954
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/mongodb",
3
- "version": "0.0.0-vnextAgentNetwork-20250602084555",
3
+ "version": "0.0.0-workflow-deno-20250616115451",
4
4
  "description": "MongoDB provider for Mastra - includes vector store capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,22 +20,23 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@types/mongodb": "^4.0.7",
23
- "cloudflare": "^4.1.0",
24
- "mongodb": "^6.15.0",
23
+ "cloudflare": "^4.3.0",
24
+ "mongodb": "^6.17.0",
25
25
  "uuid": "^11.1.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@microsoft/api-extractor": "^7.52.5",
29
- "@types/node": "^20.17.27",
30
- "eslint": "^9.23.0",
31
- "tsup": "^8.4.0",
32
- "typescript": "^5.8.2",
33
- "vitest": "^3.1.2",
34
- "@internal/lint": "0.0.0-vnextAgentNetwork-20250602084555",
35
- "@mastra/core": "0.0.0-vnextAgentNetwork-20250602084555"
28
+ "@microsoft/api-extractor": "^7.52.8",
29
+ "@types/node": "^20.19.0",
30
+ "eslint": "^9.28.0",
31
+ "tsup": "^8.5.0",
32
+ "typescript": "^5.8.3",
33
+ "vitest": "^3.2.3",
34
+ "@internal/lint": "0.0.0-workflow-deno-20250616115451",
35
+ "@internal/storage-test-utils": "0.0.0-workflow-deno-20250616115451",
36
+ "@mastra/core": "0.0.0-workflow-deno-20250616115451"
36
37
  },
37
38
  "peerDependencies": {
38
- "@mastra/core": "^0.10.0"
39
+ "@mastra/core": ">=0.10.4-0 <0.11.0"
39
40
  },
40
41
  "scripts": {
41
42
  "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
@@ -1,7 +1,8 @@
1
1
  import { randomUUID } from 'crypto';
2
- import type { MessageType, MetricResult, WorkflowRunState } from '@mastra/core';
2
+ import type { MastraMessageV1, MastraMessageV2, MetricResult, WorkflowRunState } from '@mastra/core';
3
+ import type { TABLE_NAMES } from '@mastra/core/storage';
3
4
  import { TABLE_EVALS, TABLE_MESSAGES, TABLE_THREADS, TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
4
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
5
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
5
6
  import type { MongoDBConfig } from './index';
6
7
  import { MongoDBStore } from './index';
7
8
 
@@ -40,15 +41,46 @@ class Test {
40
41
  };
41
42
  }
42
43
 
43
- generateSampleMessage(threadId: string): MessageType {
44
+ generateSampleMessageV1({
45
+ threadId,
46
+ resourceId = randomUUID(),
47
+ content = 'Hello',
48
+ }: {
49
+ threadId: string;
50
+ resourceId?: string;
51
+ content?: string;
52
+ }): MastraMessageV1 {
44
53
  return {
45
54
  id: `msg-${randomUUID()}`,
46
55
  role: 'user',
47
56
  type: 'text',
48
57
  threadId,
49
- content: [{ type: 'text', text: 'Hello' }],
58
+ content: [{ type: 'text', text: content }],
50
59
  createdAt: new Date(),
51
- resourceId: randomUUID(),
60
+ resourceId,
61
+ };
62
+ }
63
+
64
+ generateSampleMessageV2({
65
+ threadId,
66
+ resourceId = randomUUID(),
67
+ content = 'Hello',
68
+ }: {
69
+ threadId: string;
70
+ resourceId?: string;
71
+ content?: string;
72
+ }): MastraMessageV2 {
73
+ return {
74
+ id: `msg-${randomUUID()}`,
75
+ role: 'user',
76
+ type: 'text',
77
+ threadId,
78
+ content: {
79
+ format: 2,
80
+ parts: [{ type: 'text', text: content }],
81
+ },
82
+ createdAt: new Date(),
83
+ resourceId,
52
84
  };
53
85
  }
54
86
 
@@ -88,10 +120,12 @@ class Test {
88
120
  },
89
121
  input: {},
90
122
  },
123
+ serializedStepGraph: [],
91
124
  activePaths: [],
92
125
  suspendedPaths: {},
93
126
  runId,
94
127
  timestamp: timestamp.getTime(),
128
+ status: options.status,
95
129
  } as WorkflowRunState;
96
130
  return { snapshot, runId, stepId };
97
131
  }
@@ -200,7 +234,10 @@ describe('MongoDBStore', () => {
200
234
  await store.saveThread({ thread });
201
235
 
202
236
  // Add some messages
203
- const messages = [test.generateSampleMessage(thread.id), test.generateSampleMessage(thread.id)];
237
+ const messages = [
238
+ test.generateSampleMessageV1({ threadId: thread.id }),
239
+ test.generateSampleMessageV1({ threadId: thread.id }),
240
+ ];
204
241
  await store.saveMessages({ messages });
205
242
 
206
243
  await store.deleteThread({ threadId: thread.id });
@@ -235,6 +272,27 @@ describe('MongoDBStore', () => {
235
272
  expect(retrievedThread?.title).toBe('Updated Title');
236
273
  expect(retrievedThread?.metadata).toEqual({ key: 'newValue' });
237
274
  });
275
+
276
+ it('should update thread updatedAt when a message is saved to it', async () => {
277
+ const test = new Test(store).build();
278
+ await test.clearTables();
279
+
280
+ const thread = test.generateSampleThread();
281
+ await store.saveThread({ thread });
282
+
283
+ const initialThread = await store.getThreadById({ threadId: thread.id });
284
+ expect(initialThread).toBeDefined();
285
+ const originalUpdatedAt = initialThread!.updatedAt;
286
+
287
+ await new Promise(resolve => setTimeout(resolve, 10));
288
+
289
+ const message = test.generateSampleMessageV1({ threadId: thread.id });
290
+ await store.saveMessages({ messages: [message] });
291
+
292
+ const updatedThread = await store.getThreadById({ threadId: thread.id });
293
+ expect(updatedThread).toBeDefined();
294
+ expect(updatedThread!.updatedAt.getTime()).toBeGreaterThan(originalUpdatedAt.getTime());
295
+ });
238
296
  });
239
297
 
240
298
  describe('Message Operations', () => {
@@ -244,7 +302,10 @@ describe('MongoDBStore', () => {
244
302
  const thread = test.generateSampleThread();
245
303
  await store.saveThread({ thread });
246
304
 
247
- const messages = [test.generateSampleMessage(thread.id), test.generateSampleMessage(thread.id)];
305
+ const messages = [
306
+ test.generateSampleMessageV1({ threadId: thread.id }),
307
+ { ...test.generateSampleMessageV1({ threadId: thread.id }), role: 'assistant' as const },
308
+ ];
248
309
 
249
310
  // Save messages
250
311
  const savedMessages = await store.saveMessages({ messages });
@@ -273,29 +334,129 @@ describe('MongoDBStore', () => {
273
334
 
274
335
  const messages = [
275
336
  {
276
- ...test.generateSampleMessage(thread.id),
277
- content: [{ type: 'text', text: 'First' }] as MessageType['content'],
337
+ ...test.generateSampleMessageV2({ threadId: thread.id, content: 'First' }),
278
338
  },
279
339
  {
280
- ...test.generateSampleMessage(thread.id),
281
- content: [{ type: 'text', text: 'Second' }] as MessageType['content'],
340
+ ...test.generateSampleMessageV2({ threadId: thread.id, content: 'Second' }),
282
341
  },
283
342
  {
284
- ...test.generateSampleMessage(thread.id),
285
- content: [{ type: 'text', text: 'Third' }] as MessageType['content'],
343
+ ...test.generateSampleMessageV2({ threadId: thread.id, content: 'Third' }),
286
344
  },
287
345
  ];
288
346
 
289
- await store.saveMessages({ messages });
347
+ await store.saveMessages({ messages, format: 'v2' });
290
348
 
291
- const retrievedMessages = await store.getMessages({ threadId: thread.id });
349
+ const retrievedMessages = await store.getMessages({ threadId: thread.id, format: 'v2' });
292
350
  expect(retrievedMessages).toHaveLength(3);
293
351
 
294
352
  // Verify order is maintained
295
353
  retrievedMessages.forEach((msg, idx) => {
296
- expect(((msg as any).content[0] as any).text).toBe((messages[idx]!.content[0] as any).text);
354
+ expect((msg as any).content.parts).toEqual(messages[idx]!.content.parts);
297
355
  });
298
356
  });
357
+
358
+ // it('should retrieve messages w/ next/prev messages by message id + resource id', async () => {
359
+ // const test = new Test(store).build();
360
+ // const messages: MastraMessageV2[] = [
361
+ // test.generateSampleMessageV2({ threadId: 'thread-one', content: 'First', resourceId: 'cross-thread-resource' }),
362
+ // test.generateSampleMessageV2({
363
+ // threadId: 'thread-one',
364
+ // content: 'Second',
365
+ // resourceId: 'cross-thread-resource',
366
+ // }),
367
+ // test.generateSampleMessageV2({ threadId: 'thread-one', content: 'Third', resourceId: 'cross-thread-resource' }),
368
+
369
+ // test.generateSampleMessageV2({
370
+ // threadId: 'thread-two',
371
+ // content: 'Fourth',
372
+ // resourceId: 'cross-thread-resource',
373
+ // }),
374
+ // test.generateSampleMessageV2({ threadId: 'thread-two', content: 'Fifth', resourceId: 'cross-thread-resource' }),
375
+ // test.generateSampleMessageV2({ threadId: 'thread-two', content: 'Sixth', resourceId: 'cross-thread-resource' }),
376
+
377
+ // test.generateSampleMessageV2({ threadId: 'thread-three', content: 'Seventh', resourceId: 'other-resource' }),
378
+ // test.generateSampleMessageV2({ threadId: 'thread-three', content: 'Eighth', resourceId: 'other-resource' }),
379
+ // ];
380
+
381
+ // await store.saveMessages({ messages: messages, format: 'v2' });
382
+
383
+ // const retrievedMessages: MastraMessageV2[] = await store.getMessages({ threadId: 'thread-one', format: 'v2' });
384
+ // expect(retrievedMessages).toHaveLength(3);
385
+ // expect(retrievedMessages.map(m => (m.content.parts[0] as any).text)).toEqual(['First', 'Second', 'Third']);
386
+
387
+ // const retrievedMessages2: MastraMessageV2[] = await store.getMessages({ threadId: 'thread-two', format: 'v2' });
388
+ // expect(retrievedMessages2).toHaveLength(3);
389
+ // expect(retrievedMessages2.map(m => (m.content.parts[0] as any).text)).toEqual(['Fourth', 'Fifth', 'Sixth']);
390
+
391
+ // const retrievedMessages3: MastraMessageV2[] = await store.getMessages({ threadId: 'thread-three', format: 'v2' });
392
+ // expect(retrievedMessages3).toHaveLength(2);
393
+ // expect(retrievedMessages3.map(m => (m.content.parts[0] as any).text)).toEqual(['Seventh', 'Eighth']);
394
+
395
+ // const crossThreadMessages: MastraMessageV2[] = await store.getMessages({
396
+ // threadId: 'thread-doesnt-exist',
397
+ // resourceId: 'cross-thread-resource',
398
+ // format: 'v2',
399
+ // selectBy: {
400
+ // last: 0,
401
+ // include: [
402
+ // {
403
+ // id: messages[1].id,
404
+ // withNextMessages: 2,
405
+ // withPreviousMessages: 2,
406
+ // },
407
+ // {
408
+ // id: messages[4].id,
409
+ // withPreviousMessages: 2,
410
+ // withNextMessages: 2,
411
+ // },
412
+ // ],
413
+ // },
414
+ // });
415
+
416
+ // expect(crossThreadMessages).toHaveLength(6);
417
+ // expect(crossThreadMessages.filter(m => m.threadId === `thread-one`)).toHaveLength(3);
418
+ // expect(crossThreadMessages.filter(m => m.threadId === `thread-two`)).toHaveLength(3);
419
+
420
+ // const crossThreadMessages2: MastraMessageV2[] = await store.getMessages({
421
+ // threadId: 'thread-one',
422
+ // resourceId: 'cross-thread-resource',
423
+ // format: 'v2',
424
+ // selectBy: {
425
+ // last: 0,
426
+ // include: [
427
+ // {
428
+ // id: messages[4].id,
429
+ // withPreviousMessages: 1,
430
+ // withNextMessages: 30,
431
+ // },
432
+ // ],
433
+ // },
434
+ // });
435
+
436
+ // expect(crossThreadMessages2).toHaveLength(3);
437
+ // expect(crossThreadMessages2.filter(m => m.threadId === `thread-one`)).toHaveLength(0);
438
+ // expect(crossThreadMessages2.filter(m => m.threadId === `thread-two`)).toHaveLength(3);
439
+
440
+ // const crossThreadMessages3: MastraMessageV2[] = await store.getMessages({
441
+ // threadId: 'thread-two',
442
+ // resourceId: 'cross-thread-resource',
443
+ // format: 'v2',
444
+ // selectBy: {
445
+ // last: 0,
446
+ // include: [
447
+ // {
448
+ // id: messages[1].id,
449
+ // withNextMessages: 1,
450
+ // withPreviousMessages: 1,
451
+ // },
452
+ // ],
453
+ // },
454
+ // });
455
+
456
+ // expect(crossThreadMessages3).toHaveLength(3);
457
+ // expect(crossThreadMessages3.filter(m => m.threadId === `thread-one`)).toHaveLength(3);
458
+ // expect(crossThreadMessages3.filter(m => m.threadId === `thread-two`)).toHaveLength(0);
459
+ // });
299
460
  });
300
461
 
301
462
  describe('Edge Cases and Error Handling', () => {
@@ -479,7 +640,9 @@ describe('MongoDBStore', () => {
479
640
  status: 'waiting',
480
641
  },
481
642
  ],
643
+ serializedStepGraph: [],
482
644
  runId: runId,
645
+ status: 'running',
483
646
  timestamp: Date.now(),
484
647
  };
485
648
 
@@ -768,6 +931,89 @@ describe('MongoDBStore', () => {
768
931
  });
769
932
  });
770
933
 
934
+ describe('alterTable (no-op/schemaless)', () => {
935
+ const TEST_TABLE = 'test_alter_table'; // Use "table" or "collection" as appropriate
936
+ beforeEach(async () => {
937
+ await store.clearTable({ tableName: TEST_TABLE as TABLE_NAMES });
938
+ });
939
+
940
+ afterEach(async () => {
941
+ await store.clearTable({ tableName: TEST_TABLE as TABLE_NAMES });
942
+ });
943
+
944
+ it('allows inserting records with new fields without alterTable', async () => {
945
+ await store.insert({
946
+ tableName: TEST_TABLE as TABLE_NAMES,
947
+ record: { id: '1', name: 'Alice' },
948
+ });
949
+ await store.insert({
950
+ tableName: TEST_TABLE as TABLE_NAMES,
951
+ record: { id: '2', name: 'Bob', newField: 123 },
952
+ });
953
+
954
+ const row = await store.load<{ id: string; name: string; newField?: number }[]>({
955
+ tableName: TEST_TABLE as TABLE_NAMES,
956
+ keys: { id: '2' },
957
+ });
958
+ expect(row?.[0]?.newField).toBe(123);
959
+ });
960
+
961
+ it('does not throw when calling alterTable (no-op)', async () => {
962
+ await expect(
963
+ store.alterTable({
964
+ tableName: TEST_TABLE as TABLE_NAMES,
965
+ schema: {
966
+ id: { type: 'text', primaryKey: true, nullable: false },
967
+ name: { type: 'text', nullable: true },
968
+ extra: { type: 'integer', nullable: true },
969
+ },
970
+ ifNotExists: ['extra'],
971
+ }),
972
+ ).resolves.not.toThrow();
973
+ });
974
+
975
+ it('can add multiple new fields at write time', async () => {
976
+ await store.insert({
977
+ tableName: TEST_TABLE as TABLE_NAMES,
978
+ record: { id: '3', name: 'Charlie', age: 30, city: 'Paris' },
979
+ });
980
+ const row = await store.load<{ id: string; name: string; age?: number; city?: string }[]>({
981
+ tableName: TEST_TABLE as TABLE_NAMES,
982
+ keys: { id: '3' },
983
+ });
984
+ expect(row?.[0]?.age).toBe(30);
985
+ expect(row?.[0]?.city).toBe('Paris');
986
+ });
987
+
988
+ it('can retrieve all fields, including dynamically added ones', async () => {
989
+ await store.insert({
990
+ tableName: TEST_TABLE as TABLE_NAMES,
991
+ record: { id: '4', name: 'Dana', hobby: 'skiing' },
992
+ });
993
+ const row = await store.load<{ id: string; name: string; hobby?: string }[]>({
994
+ tableName: TEST_TABLE as TABLE_NAMES,
995
+ keys: { id: '4' },
996
+ });
997
+ expect(row?.[0]?.hobby).toBe('skiing');
998
+ });
999
+
1000
+ it('does not restrict or error on arbitrary new fields', async () => {
1001
+ await expect(
1002
+ store.insert({
1003
+ tableName: TEST_TABLE as TABLE_NAMES,
1004
+ record: { id: '5', weirdField: { nested: true }, another: [1, 2, 3] },
1005
+ }),
1006
+ ).resolves.not.toThrow();
1007
+
1008
+ const row = await store.load<{ id: string; weirdField?: any; another?: any }[]>({
1009
+ tableName: TEST_TABLE as TABLE_NAMES,
1010
+ keys: { id: '5' },
1011
+ });
1012
+ expect(row?.[0]?.weirdField).toEqual({ nested: true });
1013
+ expect(row?.[0]?.another).toEqual([1, 2, 3]);
1014
+ });
1015
+ });
1016
+
771
1017
  afterAll(async () => {
772
1018
  try {
773
1019
  await store.close();
@@ -1,6 +1,15 @@
1
+ import { MessageList } from '@mastra/core/agent';
1
2
  import type { MetricResult, TestInfo } from '@mastra/core/eval';
2
- import type { MessageType, StorageThreadType } from '@mastra/core/memory';
3
- import type { EvalRow, StorageGetMessagesArg, TABLE_NAMES, WorkflowRun } from '@mastra/core/storage';
3
+ import type { MastraMessageV1, MastraMessageV2, StorageThreadType } from '@mastra/core/memory';
4
+ import type {
5
+ EvalRow,
6
+ PaginationInfo,
7
+ StorageColumn,
8
+ StorageGetMessagesArg,
9
+ StorageGetTracesArg,
10
+ TABLE_NAMES,
11
+ WorkflowRun,
12
+ } from '@mastra/core/storage';
4
13
  import {
5
14
  MastraStorage,
6
15
  TABLE_EVALS,
@@ -9,6 +18,7 @@ import {
9
18
  TABLE_TRACES,
10
19
  TABLE_WORKFLOW_SNAPSHOT,
11
20
  } from '@mastra/core/storage';
21
+ import type { Trace } from '@mastra/core/telemetry';
12
22
  import type { WorkflowRunState } from '@mastra/core/workflows';
13
23
  import type { Db, MongoClientOptions } from 'mongodb';
14
24
  import { MongoClient } from 'mongodb';
@@ -73,6 +83,20 @@ export class MongoDBStore extends MastraStorage {
73
83
  // Nothing to do here, MongoDB is schemaless
74
84
  }
75
85
 
86
+ /**
87
+ * No-op: This backend is schemaless and does not require schema changes.
88
+ * @param tableName Name of the table
89
+ * @param schema Schema of the table
90
+ * @param ifNotExists Array of column names to add if they don't exist
91
+ */
92
+ async alterTable(_args: {
93
+ tableName: TABLE_NAMES;
94
+ schema: Record<string, StorageColumn>;
95
+ ifNotExists: string[];
96
+ }): Promise<void> {
97
+ // Nothing to do here, MongoDB is schemaless
98
+ }
99
+
76
100
  async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
77
101
  try {
78
102
  const collection = await this.getCollection(tableName);
@@ -231,12 +255,20 @@ export class MongoDBStore extends MastraStorage {
231
255
  }
232
256
  }
233
257
 
234
- async getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]> {
258
+ public async getMessages(args: StorageGetMessagesArg & { format?: 'v1' }): Promise<MastraMessageV1[]>;
259
+ public async getMessages(args: StorageGetMessagesArg & { format: 'v2' }): Promise<MastraMessageV2[]>;
260
+ public async getMessages({
261
+ threadId,
262
+ selectBy,
263
+ format,
264
+ }: StorageGetMessagesArg & {
265
+ format?: 'v1' | 'v2';
266
+ }): Promise<MastraMessageV1[] | MastraMessageV2[]> {
235
267
  try {
236
268
  const limit = typeof selectBy?.last === 'number' ? selectBy.last : 40;
237
269
  const include = selectBy?.include || [];
238
- let messages: MessageType[] = [];
239
- let allMessages: MessageType[] = [];
270
+ let messages: MastraMessageV2[] = [];
271
+ let allMessages: MastraMessageV2[] = [];
240
272
  const collection = await this.getCollection(TABLE_MESSAGES);
241
273
  // Get all messages from the thread ordered by creation date descending
242
274
  allMessages = (await collection.find({ thread_id: threadId }).sort({ createdAt: -1 }).toArray()).map((row: any) =>
@@ -270,7 +302,7 @@ export class MongoDBStore extends MastraStorage {
270
302
  messages.push(
271
303
  ...Array.from(selectedIndexes)
272
304
  .map(i => allMessages[i])
273
- .filter((m): m is MessageType => !!m),
305
+ .filter((m): m is MastraMessageV2 => !!m),
274
306
  );
275
307
  }
276
308
 
@@ -286,14 +318,23 @@ export class MongoDBStore extends MastraStorage {
286
318
  // Sort all messages by creation date ascending
287
319
  messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
288
320
 
289
- return messages.slice(0, limit) as T[];
321
+ const list = new MessageList().add(messages.slice(0, limit), 'memory');
322
+ if (format === `v2`) return list.get.all.v2();
323
+ return list.get.all.v1();
290
324
  } catch (error) {
291
325
  this.logger.error('Error getting messages:', error as Error);
292
326
  throw error;
293
327
  }
294
328
  }
295
329
 
296
- async saveMessages({ messages }: { messages: MessageType[] }): Promise<MessageType[]> {
330
+ async saveMessages(args: { messages: MastraMessageV1[]; format?: undefined | 'v1' }): Promise<MastraMessageV1[]>;
331
+ async saveMessages(args: { messages: MastraMessageV2[]; format: 'v2' }): Promise<MastraMessageV2[]>;
332
+ async saveMessages({
333
+ messages,
334
+ format,
335
+ }:
336
+ | { messages: MastraMessageV1[]; format?: undefined | 'v1' }
337
+ | { messages: MastraMessageV2[]; format: 'v2' }): Promise<MastraMessageV2[] | MastraMessageV1[]> {
297
338
  if (!messages.length) {
298
339
  return messages;
299
340
  }
@@ -303,6 +344,7 @@ export class MongoDBStore extends MastraStorage {
303
344
  this.logger.error('Thread ID is required to save messages');
304
345
  throw new Error('Thread ID is required');
305
346
  }
347
+
306
348
  try {
307
349
  // Prepare batch statements for all messages
308
350
  const messagesToInsert = messages.map(message => {
@@ -318,10 +360,18 @@ export class MongoDBStore extends MastraStorage {
318
360
  };
319
361
  });
320
362
 
321
- // Execute all inserts in a single batch
363
+ // Execute message inserts and thread update in parallel for better performance
322
364
  const collection = await this.getCollection(TABLE_MESSAGES);
323
- await collection.insertMany(messagesToInsert);
324
- return messages;
365
+ const threadsCollection = await this.getCollection(TABLE_THREADS);
366
+
367
+ await Promise.all([
368
+ collection.insertMany(messagesToInsert),
369
+ threadsCollection.updateOne({ id: threadId }, { $set: { updatedAt: new Date() } }),
370
+ ]);
371
+
372
+ const list = new MessageList().add(messages, 'memory');
373
+ if (format === `v2`) return list.get.all.v2();
374
+ return list.get.all.v1();
325
375
  } catch (error) {
326
376
  this.logger.error('Failed to save messages in database: ' + (error as { message: string })?.message);
327
377
  throw error;
@@ -628,7 +678,7 @@ export class MongoDBStore extends MastraStorage {
628
678
  };
629
679
  }
630
680
 
631
- private parseRow(row: any): MessageType {
681
+ private parseRow(row: any): MastraMessageV2 {
632
682
  let content = row.content;
633
683
  try {
634
684
  content = JSON.parse(row.content);
@@ -642,7 +692,8 @@ export class MongoDBStore extends MastraStorage {
642
692
  type: row.type,
643
693
  createdAt: new Date(row.createdAt as string),
644
694
  threadId: row.thread_id,
645
- } as MessageType;
695
+ resourceId: row.resourceId,
696
+ } as MastraMessageV2;
646
697
  }
647
698
 
648
699
  private transformEvalRow(row: Record<string, any>): EvalRow {
@@ -669,6 +720,24 @@ export class MongoDBStore extends MastraStorage {
669
720
  };
670
721
  }
671
722
 
723
+ async getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & { traces: Trace[] }> {
724
+ throw new Error('Method not implemented.');
725
+ }
726
+
727
+ async getThreadsByResourceIdPaginated(_args: {
728
+ resourceId: string;
729
+ page?: number;
730
+ perPage?: number;
731
+ }): Promise<PaginationInfo & { threads: StorageThreadType[] }> {
732
+ throw new Error('Method not implemented.');
733
+ }
734
+
735
+ async getMessagesPaginated(
736
+ _args: StorageGetMessagesArg,
737
+ ): Promise<PaginationInfo & { messages: MastraMessageV1[] | MastraMessageV2[] }> {
738
+ throw new Error('Method not implemented.');
739
+ }
740
+
672
741
  async close(): Promise<void> {
673
742
  await this.#client.close();
674
743
  }