@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.
- package/.turbo/turbo-build.log +23 -0
- package/CHANGELOG.md +162 -2
- package/dist/_tsup-dts-rollup.d.cts +44 -5
- package/dist/_tsup-dts-rollup.d.ts +44 -5
- package/dist/index.cjs +40 -6
- package/dist/index.js +40 -6
- package/package.json +13 -12
- package/src/storage/index.test.ts +262 -16
- package/src/storage/index.ts +82 -13
|
@@ -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
|
+
[34mCLI[39m Building entry: src/index.ts
|
|
6
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
+
[34mCLI[39m tsup v8.5.0
|
|
8
|
+
[34mTSC[39m Build start
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 9462ms
|
|
10
|
+
[34mDTS[39m Build start
|
|
11
|
+
[34mCLI[39m Target: es2022
|
|
12
|
+
Analysis will use the bundled TypeScript version 5.8.3
|
|
13
|
+
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/mongodb/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
|
+
Analysis will use the bundled TypeScript version 5.8.3
|
|
15
|
+
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/mongodb/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 11575ms
|
|
17
|
+
[34mCLI[39m Cleaning output folder
|
|
18
|
+
[34mESM[39m Build start
|
|
19
|
+
[34mCJS[39m Build start
|
|
20
|
+
[32mESM[39m [1mdist/index.js [22m[32m33.93 KB[39m
|
|
21
|
+
[32mESM[39m ⚡️ Build success in 1213ms
|
|
22
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m34.07 KB[39m
|
|
23
|
+
[32mCJS[39m ⚡️ Build success in 1213ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,157 @@
|
|
|
1
1
|
# @mastra/mongodb
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
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
|
-
|
|
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
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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({
|
|
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
|
-
|
|
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({
|
|
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
|
|
655
|
-
|
|
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({
|
|
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
|
-
|
|
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({
|
|
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
|
|
653
|
-
|
|
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-
|
|
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.
|
|
24
|
-
"mongodb": "^6.
|
|
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.
|
|
29
|
-
"@types/node": "^20.
|
|
30
|
-
"eslint": "^9.
|
|
31
|
-
"tsup": "^8.
|
|
32
|
-
"typescript": "^5.8.
|
|
33
|
-
"vitest": "^3.
|
|
34
|
-
"@internal/lint": "0.0.0-
|
|
35
|
-
"@
|
|
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": "
|
|
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 {
|
|
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
|
-
|
|
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:
|
|
58
|
+
content: [{ type: 'text', text: content }],
|
|
50
59
|
createdAt: new Date(),
|
|
51
|
-
resourceId
|
|
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 = [
|
|
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 = [
|
|
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.
|
|
277
|
-
content: [{ type: 'text', text: 'First' }] as MessageType['content'],
|
|
337
|
+
...test.generateSampleMessageV2({ threadId: thread.id, content: 'First' }),
|
|
278
338
|
},
|
|
279
339
|
{
|
|
280
|
-
...test.
|
|
281
|
-
content: [{ type: 'text', text: 'Second' }] as MessageType['content'],
|
|
340
|
+
...test.generateSampleMessageV2({ threadId: thread.id, content: 'Second' }),
|
|
282
341
|
},
|
|
283
342
|
{
|
|
284
|
-
...test.
|
|
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((
|
|
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();
|
package/src/storage/index.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { MessageList } from '@mastra/core/agent';
|
|
1
2
|
import type { MetricResult, TestInfo } from '@mastra/core/eval';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
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
|
|
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:
|
|
239
|
-
let allMessages:
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
363
|
+
// Execute message inserts and thread update in parallel for better performance
|
|
322
364
|
const collection = await this.getCollection(TABLE_MESSAGES);
|
|
323
|
-
await
|
|
324
|
-
|
|
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):
|
|
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
|
-
|
|
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
|
}
|