@mastra/mongodb 1.5.4 → 1.5.5-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-working-memory.md +6 -6
- package/dist/docs/references/docs-rag-vector-databases.md +2 -2
- package/dist/docs/references/reference-storage-mongodb.md +1 -1
- package/dist/index.cjs +63 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +63 -34
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +1 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @mastra/mongodb
|
|
2
2
|
|
|
3
|
+
## 1.5.5-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed slow semantic recall on large threads in the MongoDB and DynamoDB memory stores. Included message lookups now avoid unnecessary work when semantic recall only needs specific messages and nearby context. (Fixes #11702) ([#14022](https://github.com/mastra-ai/mastra/pull/14022))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`4f71b43`](https://github.com/mastra-ai/mastra/commit/4f71b436a4a6b8839842d8da47b57b84509af56c), [`a070277`](https://github.com/mastra-ai/mastra/commit/a07027766ce195ba74d0783116d894cbab25d44c), [`b628b91`](https://github.com/mastra-ai/mastra/commit/b628b9128b372c0f54214d902b07279f03443900), [`332c014`](https://github.com/mastra-ai/mastra/commit/332c014e076b81edf7fe45b58205882726415e90), [`6b63153`](https://github.com/mastra-ai/mastra/commit/6b63153878ea841c0f4ce632ba66bb33e57e9c1b), [`4246e34`](https://github.com/mastra-ai/mastra/commit/4246e34cec9c26636d0965942268e6d07c346671), [`b8837ee`](https://github.com/mastra-ai/mastra/commit/b8837ee77e2e84197609762bfabd8b3da326d30c), [`5d950f7`](https://github.com/mastra-ai/mastra/commit/5d950f7bf426a215a1808f0abef7de5c8336ba1c), [`28c85b1`](https://github.com/mastra-ai/mastra/commit/28c85b184fc32b40f7f160483c982da6d388ecbd), [`e9a08fb`](https://github.com/mastra-ai/mastra/commit/e9a08fbef1ada7e50e961e2f54f55e8c10b4a45c), [`631ffd8`](https://github.com/mastra-ai/mastra/commit/631ffd82fed108648b448b28e6a90e38c5f53bf5), [`aae2295`](https://github.com/mastra-ai/mastra/commit/aae2295838a2d329ad6640829e87934790ffe5b8), [`aa61f29`](https://github.com/mastra-ai/mastra/commit/aa61f29ff8095ce46a4ae16e46c4d8c79b2b685b), [`7ff3714`](https://github.com/mastra-ai/mastra/commit/7ff37148515439bb3be009a60e02c3e363299760), [`41d79a1`](https://github.com/mastra-ai/mastra/commit/41d79a14bd8cb6de1e2565fd0a04786bae2f211b), [`e673376`](https://github.com/mastra-ai/mastra/commit/e6733763ad1321aa7e5ae15096b9c2104f93b1f3), [`b2204c9`](https://github.com/mastra-ai/mastra/commit/b2204c98a42848bbfb6f0440f005dc2b6354f1cd), [`a1bf1e3`](https://github.com/mastra-ai/mastra/commit/a1bf1e385ed4c0ef6f11b56c5887442970d127f2), [`b6f647a`](https://github.com/mastra-ai/mastra/commit/b6f647ae2388e091f366581595feb957e37d5b40), [`0c57b8b`](https://github.com/mastra-ai/mastra/commit/0c57b8b0a69a97b5a4ae3f79be6c610f29f3cf7b), [`b081f27`](https://github.com/mastra-ai/mastra/commit/b081f272cf411716e1d6bd72ceac4bcee2657b19), [`0c09eac`](https://github.com/mastra-ai/mastra/commit/0c09eacb1926f64cfdc9ae5c6d63385cf8c9f72c), [`6b9b93d`](https://github.com/mastra-ai/mastra/commit/6b9b93d6f459d1ba6e36f163abf62a085ddb3d64), [`31b6067`](https://github.com/mastra-ai/mastra/commit/31b6067d0cc3ab10e1b29c36147f3b5266bc714a), [`797ac42`](https://github.com/mastra-ai/mastra/commit/797ac4276de231ad2d694d9aeca75980f6cd0419), [`0bc289e`](https://github.com/mastra-ai/mastra/commit/0bc289e2d476bf46c5b91c21969e8d0c6864691c), [`9b75a06`](https://github.com/mastra-ai/mastra/commit/9b75a06e53ebb0b950ba7c1e83a0142047185f46), [`4c3a1b1`](https://github.com/mastra-ai/mastra/commit/4c3a1b122ea083e003d71092f30f3b31680b01c0), [`85cc3b3`](https://github.com/mastra-ai/mastra/commit/85cc3b3b6f32ae4b083c26498f50d5b250ba944b), [`97ea28c`](https://github.com/mastra-ai/mastra/commit/97ea28c746e9e4147d56047bbb1c4a92417a3fec), [`d567299`](https://github.com/mastra-ai/mastra/commit/d567299cf81e02bd9d5221d4bc05967d6c224161), [`716ffe6`](https://github.com/mastra-ai/mastra/commit/716ffe68bed81f7c2690bc8581b9e140f7bf1c3d), [`8296332`](https://github.com/mastra-ai/mastra/commit/8296332de21c16e3dfc3d0b2d615720a6dc88f2f), [`4df2116`](https://github.com/mastra-ai/mastra/commit/4df211619dd922c047d396ca41cd7027c8c4c8e7), [`2219c1a`](https://github.com/mastra-ai/mastra/commit/2219c1acbd21da116da877f0036ffb985a9dd5a3), [`17c4145`](https://github.com/mastra-ai/mastra/commit/17c4145166099354545582335b5252bdfdfd908b)]:
|
|
10
|
+
- @mastra/core@1.11.0-alpha.0
|
|
11
|
+
|
|
3
12
|
## 1.5.4
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -170,11 +170,11 @@ const memory = new Memory({
|
|
|
170
170
|
|
|
171
171
|
## Designing Effective Templates
|
|
172
172
|
|
|
173
|
-
A well-structured template keeps the information
|
|
173
|
+
A well-structured template keeps the information straightforward for the agent to parse and update. Treat the template as a short form that you want the assistant to keep up to date.
|
|
174
174
|
|
|
175
|
-
- **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example `## Personal Info` or `- Name:`) so updates are
|
|
175
|
+
- **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example `## Personal Info` or `- Name:`) so updates are readable and less likely to be truncated.
|
|
176
176
|
- **Use consistent casing.** Inconsistent capitalization (`Timezone:` vs `timezone:`) can cause messy updates. Stick to Title Case or lower case for headings and bullet labels.
|
|
177
|
-
- **Keep placeholder text
|
|
177
|
+
- **Keep placeholder text minimal.** Use hints such as `[e.g., Formal]` or `[Date]` to help the LLM fill in the correct spots.
|
|
178
178
|
- **Abbreviate very long values.** If you only need a short form, include guidance like `- Name: [First name or nickname]` or `- Address (short):` rather than the full legal text.
|
|
179
179
|
- **Mention update rules in `instructions`.** You can instruct how and when to fill or clear parts of the template directly in the agent's `instructions` field.
|
|
180
180
|
|
|
@@ -263,13 +263,13 @@ Schema-based working memory uses **merge semantics**, meaning the agent only nee
|
|
|
263
263
|
|
|
264
264
|
- **Object fields are deep merged:** Only provided fields are updated; others remain unchanged
|
|
265
265
|
- **Set a field to `null` to delete it:** This explicitly removes the field from memory
|
|
266
|
-
- **Arrays are replaced entirely:** When an array field is provided, it replaces the existing array (arrays
|
|
266
|
+
- **Arrays are replaced entirely:** When an array field is provided, it replaces the existing array (arrays aren't merged element-by-element)
|
|
267
267
|
|
|
268
268
|
## Choosing Between Template and Schema
|
|
269
269
|
|
|
270
270
|
- Use a **template** (Markdown) if you want the agent to maintain memory as a free-form text block, such as a user profile or scratchpad. Templates use **replace semantics** — the agent must provide the complete memory content on each update.
|
|
271
271
|
- Use a **schema** if you need structured, type-safe data that can be validated and programmatically accessed as JSON. Schemas use **merge semantics** — the agent only provides fields to update, and existing fields are preserved.
|
|
272
|
-
- Only one mode can be active at a time: setting both `template` and `schema`
|
|
272
|
+
- Only one mode can be active at a time: setting both `template` and `schema` isn't supported.
|
|
273
273
|
|
|
274
274
|
## Example: Multi-step Retention
|
|
275
275
|
|
|
@@ -301,7 +301,7 @@ Below is a simplified view of how the `User Profile` template updates across a s
|
|
|
301
301
|
|
|
302
302
|
The agent can now refer to `Sam` or `Berlin` in later responses without requesting the information again because it has been stored in working memory.
|
|
303
303
|
|
|
304
|
-
If your agent
|
|
304
|
+
If your agent isn't properly updating working memory when you expect it to, you can add system instructions on _how_ and _when_ to use this template in your agent's `instructions` setting.
|
|
305
305
|
|
|
306
306
|
## Setting Initial Working Memory
|
|
307
307
|
|
|
@@ -359,7 +359,7 @@ The dimension size must match the output dimension of your chosen embedding mode
|
|
|
359
359
|
- Cohere embed-multilingual-v3: 1024 dimensions
|
|
360
360
|
- Google gemini-embedding-001: 768 dimensions (or custom)
|
|
361
361
|
|
|
362
|
-
> **Warning:** Index dimensions
|
|
362
|
+
> **Warning:** Index dimensions can't be changed after creation. To use a different model, delete and recreate the index with the new dimension size.
|
|
363
363
|
|
|
364
364
|
### Naming Rules for Databases
|
|
365
365
|
|
|
@@ -583,7 +583,7 @@ Key metadata considerations:
|
|
|
583
583
|
|
|
584
584
|
## Deleting Vectors
|
|
585
585
|
|
|
586
|
-
When building RAG applications, you often need to clean up stale vectors when documents are deleted or updated. Mastra provides the `deleteVectors` method that supports deleting vectors by metadata filters, making it
|
|
586
|
+
When building RAG applications, you often need to clean up stale vectors when documents are deleted or updated. Mastra provides the `deleteVectors` method that supports deleting vectors by metadata filters, making it straightforward to remove all embeddings associated with a specific document.
|
|
587
587
|
|
|
588
588
|
### Delete by Metadata Filter
|
|
589
589
|
|
|
@@ -136,7 +136,7 @@ const memoryStore = await storage.getStore('memory')
|
|
|
136
136
|
const thread = await memoryStore?.getThreadById({ threadId: '...' })
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
> **Warning:** If `init()`
|
|
139
|
+
> **Warning:** If `init()` isn't called, collections won't be created and storage operations will fail silently or throw errors.
|
|
140
140
|
|
|
141
141
|
## Vector Search Capabilities
|
|
142
142
|
|
package/dist/index.cjs
CHANGED
|
@@ -14,7 +14,7 @@ var evals = require('@mastra/core/evals');
|
|
|
14
14
|
|
|
15
15
|
// package.json
|
|
16
16
|
var package_default = {
|
|
17
|
-
version: "1.5.
|
|
17
|
+
version: "1.5.5-alpha.0"};
|
|
18
18
|
var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
19
19
|
getSupportedOperators() {
|
|
20
20
|
return {
|
|
@@ -2907,22 +2907,37 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemorySto
|
|
|
2907
2907
|
if (row.type && row.type !== "v2") result.type = row.type;
|
|
2908
2908
|
return result;
|
|
2909
2909
|
}
|
|
2910
|
+
_sortMessages(messages, field, direction) {
|
|
2911
|
+
return messages.sort((a, b) => {
|
|
2912
|
+
const isDateField = field === "createdAt" || field === "updatedAt";
|
|
2913
|
+
const aValue = isDateField ? new Date(a[field]).getTime() : a[field];
|
|
2914
|
+
const bValue = isDateField ? new Date(b[field]).getTime() : b[field];
|
|
2915
|
+
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
2916
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
2917
|
+
}
|
|
2918
|
+
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2910
2921
|
async _getIncludedMessages({ include }) {
|
|
2911
2922
|
if (!include || include.length === 0) return null;
|
|
2912
2923
|
const collection = await this.getCollection(storage.TABLE_MESSAGES);
|
|
2924
|
+
const targetIds = include.map((inc) => inc.id).filter(Boolean);
|
|
2925
|
+
if (targetIds.length === 0) return null;
|
|
2926
|
+
const targetDocs = await collection.find({ id: { $in: targetIds } }, { projection: { id: 1, thread_id: 1, createdAt: 1 } }).toArray();
|
|
2927
|
+
if (targetDocs.length === 0) return null;
|
|
2928
|
+
const targetMap = new Map(
|
|
2929
|
+
targetDocs.map((doc) => [doc.id, { threadId: doc.thread_id, createdAt: doc.createdAt }])
|
|
2930
|
+
);
|
|
2913
2931
|
const includedMessages = [];
|
|
2914
2932
|
for (const inc of include) {
|
|
2915
2933
|
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
2916
|
-
const
|
|
2917
|
-
if (!
|
|
2918
|
-
const
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
const endIndex = Math.min(allMessages.length - 1, targetIndex + withNextMessages);
|
|
2924
|
-
for (let i = startIndex; i <= endIndex; i++) {
|
|
2925
|
-
includedMessages.push(allMessages[i]);
|
|
2934
|
+
const target = targetMap.get(id);
|
|
2935
|
+
if (!target) continue;
|
|
2936
|
+
const prevMessages = await collection.find({ thread_id: target.threadId, createdAt: { $lte: target.createdAt } }).sort({ createdAt: -1, id: -1 }).limit(withPreviousMessages + 1).toArray();
|
|
2937
|
+
includedMessages.push(...prevMessages);
|
|
2938
|
+
if (withNextMessages > 0) {
|
|
2939
|
+
const nextMessages = await collection.find({ thread_id: target.threadId, createdAt: { $gt: target.createdAt } }).sort({ createdAt: 1, id: 1 }).limit(withNextMessages).toArray();
|
|
2940
|
+
includedMessages.push(...nextMessages);
|
|
2926
2941
|
}
|
|
2927
2942
|
}
|
|
2928
2943
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2998,6 +3013,20 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemorySto
|
|
|
2998
3013
|
const endOp = filter.dateRange.endExclusive ? "$lt" : "$lte";
|
|
2999
3014
|
query.createdAt = { ...query.createdAt, [endOp]: formatDateForMongoDB(filter.dateRange.end) };
|
|
3000
3015
|
}
|
|
3016
|
+
if (perPage === 0 && (!include || include.length === 0)) {
|
|
3017
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
3018
|
+
}
|
|
3019
|
+
if (perPage === 0 && include && include.length > 0) {
|
|
3020
|
+
const includeMessages = await this._getIncludedMessages({ include });
|
|
3021
|
+
const list2 = new agent.MessageList().add(includeMessages ?? [], "memory");
|
|
3022
|
+
return {
|
|
3023
|
+
messages: this._sortMessages(list2.get.all.db(), field, direction),
|
|
3024
|
+
total: 0,
|
|
3025
|
+
page,
|
|
3026
|
+
perPage: perPageForResponse,
|
|
3027
|
+
hasMore: false
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3001
3030
|
const total = await collection.countDocuments(query);
|
|
3002
3031
|
const messages = [];
|
|
3003
3032
|
if (perPage !== 0) {
|
|
@@ -3031,16 +3060,7 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemorySto
|
|
|
3031
3060
|
}
|
|
3032
3061
|
}
|
|
3033
3062
|
const list = new agent.MessageList().add(messages, "memory");
|
|
3034
|
-
|
|
3035
|
-
finalMessages = finalMessages.sort((a, b) => {
|
|
3036
|
-
const isDateField = field === "createdAt" || field === "updatedAt";
|
|
3037
|
-
const aValue = isDateField ? new Date(a[field]).getTime() : a[field];
|
|
3038
|
-
const bValue = isDateField ? new Date(b[field]).getTime() : b[field];
|
|
3039
|
-
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
3040
|
-
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
3041
|
-
}
|
|
3042
|
-
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
3043
|
-
});
|
|
3063
|
+
const finalMessages = this._sortMessages(list.get.all.db(), field, direction);
|
|
3044
3064
|
const threadIdSet = new Set(threadIds);
|
|
3045
3065
|
const returnedThreadMessageIds = new Set(
|
|
3046
3066
|
finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
|
|
@@ -3118,6 +3138,23 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemorySto
|
|
|
3118
3138
|
const endOp = filter.dateRange.endExclusive ? "$lt" : "$lte";
|
|
3119
3139
|
query.createdAt = { ...query.createdAt, [endOp]: formatDateForMongoDB(filter.dateRange.end) };
|
|
3120
3140
|
}
|
|
3141
|
+
if (perPage === 0 && (!include || include.length === 0)) {
|
|
3142
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
3143
|
+
}
|
|
3144
|
+
if (perPage === 0 && include && include.length > 0) {
|
|
3145
|
+
const includeMessages = await this._getIncludedMessages({ include });
|
|
3146
|
+
if (!includeMessages || includeMessages.length === 0) {
|
|
3147
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
3148
|
+
}
|
|
3149
|
+
const list2 = new agent.MessageList().add(includeMessages, "memory");
|
|
3150
|
+
return {
|
|
3151
|
+
messages: this._sortMessages(list2.get.all.db(), field, direction),
|
|
3152
|
+
total: 0,
|
|
3153
|
+
page,
|
|
3154
|
+
perPage: perPageForResponse,
|
|
3155
|
+
hasMore: false
|
|
3156
|
+
};
|
|
3157
|
+
}
|
|
3121
3158
|
const total = await collection.countDocuments(query);
|
|
3122
3159
|
const messages = [];
|
|
3123
3160
|
if (perPage !== 0) {
|
|
@@ -3151,16 +3188,7 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends storage.MemorySto
|
|
|
3151
3188
|
}
|
|
3152
3189
|
}
|
|
3153
3190
|
const list = new agent.MessageList().add(messages, "memory");
|
|
3154
|
-
|
|
3155
|
-
finalMessages = finalMessages.sort((a, b) => {
|
|
3156
|
-
const isDateField = field === "createdAt" || field === "updatedAt";
|
|
3157
|
-
const aValue = isDateField ? new Date(a[field]).getTime() : a[field];
|
|
3158
|
-
const bValue = isDateField ? new Date(b[field]).getTime() : b[field];
|
|
3159
|
-
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
3160
|
-
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
3161
|
-
}
|
|
3162
|
-
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
3163
|
-
});
|
|
3191
|
+
const finalMessages = this._sortMessages(list.get.all.db(), field, direction);
|
|
3164
3192
|
const hasMore = perPageInput !== false && offset + perPage < total;
|
|
3165
3193
|
return {
|
|
3166
3194
|
messages: finalMessages,
|
|
@@ -4995,7 +5023,8 @@ Note: This migration may take some time for large collections.
|
|
|
4995
5023
|
}
|
|
4996
5024
|
async listTraces(args) {
|
|
4997
5025
|
const { filters, pagination, orderBy } = storage.listTracesArgsSchema.parse(args);
|
|
4998
|
-
const
|
|
5026
|
+
const page = pagination?.page ?? 0;
|
|
5027
|
+
const perPage = pagination?.perPage ?? 10;
|
|
4999
5028
|
try {
|
|
5000
5029
|
const collection = await this.getCollection(storage.TABLE_SPANS);
|
|
5001
5030
|
const mongoFilter = {
|
|
@@ -5100,8 +5129,8 @@ Note: This migration may take some time for large collections.
|
|
|
5100
5129
|
if (andConditions.length) {
|
|
5101
5130
|
mongoFilter.$and = andConditions;
|
|
5102
5131
|
}
|
|
5103
|
-
const sortField = orderBy
|
|
5104
|
-
const sortDirection = orderBy
|
|
5132
|
+
const sortField = orderBy?.field ?? "startedAt";
|
|
5133
|
+
const sortDirection = (orderBy?.direction ?? "DESC") === "ASC" ? 1 : -1;
|
|
5105
5134
|
if (filters?.hasChildError !== void 0) {
|
|
5106
5135
|
const pipeline = [
|
|
5107
5136
|
{ $match: mongoFilter },
|