@mastra/mongodb 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -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 +29 -2
- package/dist/docs/references/docs-rag-retrieval.md +15 -12
- package/dist/docs/references/reference-storage-mongodb.md +4 -1
- package/dist/docs/references/reference-vectors-mongodb.md +1 -1
- package/dist/index.cjs +292 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +293 -3
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/notifications/index.d.ts +24 -0
- package/dist/storage/domains/notifications/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @mastra/mongodb
|
|
2
2
|
|
|
3
|
+
## 1.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added notification inbox storage support for MongoDB stores. ([#17241](https://github.com/mastra-ai/mastra/pull/17241))
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { MongoDBStore } from '@mastra/mongodb';
|
|
11
|
+
|
|
12
|
+
const storage = new MongoDBStore({ url: process.env.MONGODB_URI!, dbName: 'mastra' });
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Agents using this store can persist thread-scoped notification inbox records for notification signals.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`c973db4`](https://github.com/mastra-ai/mastra/commit/c973db428df1b564ff0c35d4b2a90e8f4f1e13fd), [`552285e`](https://github.com/mastra-ai/mastra/commit/552285e5af43cfc680a0972032cab8de8776c6a0), [`77e686c`](https://github.com/mastra-ai/mastra/commit/77e686c264e493e99ae5024e4dfe3ea5d5a09718), [`ece8dba`](https://github.com/mastra-ai/mastra/commit/ece8dba7ec1a5089eee8c33167cd762bfa91e509), [`e751af2`](https://github.com/mastra-ai/mastra/commit/e751af219433fbf4c7035b2d771b4c9ec8813b05), [`e2a8380`](https://github.com/mastra-ai/mastra/commit/e2a838017a7657850404c1e94c70d79ffdc6f14a), [`be3f1cd`](https://github.com/mastra-ai/mastra/commit/be3f1cd81f0e2a649e8eac15a024d542d814aef8), [`a34d9db`](https://github.com/mastra-ai/mastra/commit/a34d9dbc39fedb722f271318e9355ecee70489ab)]:
|
|
18
|
+
- @mastra/core@1.39.0
|
|
19
|
+
|
|
20
|
+
## 1.9.1-alpha.0
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Added notification inbox storage support for MongoDB stores. ([#17241](https://github.com/mastra-ai/mastra/pull/17241))
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { MongoDBStore } from '@mastra/mongodb';
|
|
28
|
+
|
|
29
|
+
const storage = new MongoDBStore({ url: process.env.MONGODB_URI!, dbName: 'mastra' });
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Agents using this store can persist thread-scoped notification inbox records for notification signals.
|
|
33
|
+
|
|
34
|
+
- Updated dependencies [[`c973db4`](https://github.com/mastra-ai/mastra/commit/c973db428df1b564ff0c35d4b2a90e8f4f1e13fd), [`552285e`](https://github.com/mastra-ai/mastra/commit/552285e5af43cfc680a0972032cab8de8776c6a0), [`77e686c`](https://github.com/mastra-ai/mastra/commit/77e686c264e493e99ae5024e4dfe3ea5d5a09718), [`ece8dba`](https://github.com/mastra-ai/mastra/commit/ece8dba7ec1a5089eee8c33167cd762bfa91e509), [`e751af2`](https://github.com/mastra-ai/mastra/commit/e751af219433fbf4c7035b2d771b4c9ec8813b05), [`e2a8380`](https://github.com/mastra-ai/mastra/commit/e2a838017a7657850404c1e94c70d79ffdc6f14a), [`be3f1cd`](https://github.com/mastra-ai/mastra/commit/be3f1cd81f0e2a649e8eac15a024d542d814aef8), [`a34d9db`](https://github.com/mastra-ai/mastra/commit/a34d9dbc39fedb722f271318e9355ecee70489ab)]:
|
|
35
|
+
- @mastra/core@1.39.0-alpha.0
|
|
36
|
+
|
|
3
37
|
## 1.9.0
|
|
4
38
|
|
|
5
39
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -26,7 +26,7 @@ const agent = new Agent({
|
|
|
26
26
|
id: 'personal-assistant',
|
|
27
27
|
name: 'PersonalAssistant',
|
|
28
28
|
instructions: 'You are a helpful personal assistant.',
|
|
29
|
-
model: 'openai/gpt-5.
|
|
29
|
+
model: 'openai/gpt-5.5',
|
|
30
30
|
memory: new Memory({
|
|
31
31
|
options: {
|
|
32
32
|
workingMemory: {
|
|
@@ -130,7 +130,7 @@ Resource-scoped working memory requires specific storage adapters that support t
|
|
|
130
130
|
|
|
131
131
|
## Custom templates
|
|
132
132
|
|
|
133
|
-
Templates guide the agent on what information to track and update in working memory. While a default template is used if none is provided, you'll typically want to define a custom template tailored to your agent's specific use case to ensure it remembers the most relevant information.
|
|
133
|
+
Templates guide the agent on what information to track and update in working memory. While a default template is used if none is provided, you'll typically want to define a custom template tailored to your agent's specific use case to ensure it remembers the most relevant information. For threads shared by multiple users, see [Multi-user threads](https://mastra.ai/docs/memory/multi-user-threads).
|
|
134
134
|
|
|
135
135
|
Here's an example of a custom template. In this example the agent will store the users name, location, timezone, etc as soon as the user sends a message containing any of the info:
|
|
136
136
|
|
|
@@ -393,6 +393,33 @@ const response = await agent.generate('What do you know about me?', {
|
|
|
393
393
|
})
|
|
394
394
|
```
|
|
395
395
|
|
|
396
|
+
## Opt in to state signals (experimental)
|
|
397
|
+
|
|
398
|
+
By default, working memory reaches the model as part of the system message. You can opt into delivering it as a [state signal](https://mastra.ai/docs/agents/signals) instead by setting `useStateSignals: true`:
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
const memory = new Memory({
|
|
402
|
+
storage: new LibSQLStore({ url: 'file:./mastra.db' }),
|
|
403
|
+
options: {
|
|
404
|
+
workingMemory: {
|
|
405
|
+
enabled: true,
|
|
406
|
+
template: '# User\n- name:\n- location:',
|
|
407
|
+
useStateSignals: true, // experimental: deliver as state signal
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
})
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
What changes:
|
|
414
|
+
|
|
415
|
+
- **Storage is identical.** The same resource/thread `workingMemory` field is read and written.
|
|
416
|
+
- **The tool is the same shape, exposed under a new name.** Writes still flow through the same underlying tool; on this path it is registered as `setWorkingMemory` (instead of `updateWorkingMemory`). The rename keeps legacy strip filters from removing tool-call parts so they persist as a normal audit trail and the next model step picks the new value up automatically.
|
|
417
|
+
- **Delivery only.** Instead of folding into the system prompt, `Memory` auto-attaches a `WorkingMemoryStateProcessor` that emits the current working memory as a `state` signal with `stateId: 'working-memory'`.
|
|
418
|
+
|
|
419
|
+
You inherit the standard state-signal benefits: thread-scoped tracking metadata, `cacheKey` dedup so identical snapshots are only emitted once, and `contextWindow.hasSnapshot` re-injection when an older snapshot rolls out of the window.
|
|
420
|
+
|
|
421
|
+
The default (`useStateSignals: false`) keeps the existing system-message behavior unchanged. `useStateSignals` is not supported with template working memory `version: 'vnext'`.
|
|
422
|
+
|
|
396
423
|
## Examples
|
|
397
424
|
|
|
398
425
|
- [Working memory with template](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-template)
|
|
@@ -272,7 +272,7 @@ import { PGVECTOR_PROMPT } from '@mastra/pg'
|
|
|
272
272
|
export const ragAgent = new Agent({
|
|
273
273
|
id: 'rag-agent',
|
|
274
274
|
name: 'RAG Agent',
|
|
275
|
-
model: 'openai/gpt-5.
|
|
275
|
+
model: 'openai/gpt-5.5',
|
|
276
276
|
instructions: `
|
|
277
277
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
278
278
|
${PGVECTOR_PROMPT}
|
|
@@ -289,7 +289,7 @@ import { PINECONE_PROMPT } from '@mastra/pinecone'
|
|
|
289
289
|
export const ragAgent = new Agent({
|
|
290
290
|
id: 'rag-agent',
|
|
291
291
|
name: 'RAG Agent',
|
|
292
|
-
model: 'openai/gpt-5.
|
|
292
|
+
model: 'openai/gpt-5.5',
|
|
293
293
|
instructions: `
|
|
294
294
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
295
295
|
${PINECONE_PROMPT}
|
|
@@ -306,7 +306,7 @@ import { QDRANT_PROMPT } from '@mastra/qdrant'
|
|
|
306
306
|
export const ragAgent = new Agent({
|
|
307
307
|
id: 'rag-agent',
|
|
308
308
|
name: 'RAG Agent',
|
|
309
|
-
model: 'openai/gpt-5.
|
|
309
|
+
model: 'openai/gpt-5.5',
|
|
310
310
|
instructions: `
|
|
311
311
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
312
312
|
${QDRANT_PROMPT}
|
|
@@ -323,7 +323,7 @@ import { CHROMA_PROMPT } from '@mastra/chroma'
|
|
|
323
323
|
export const ragAgent = new Agent({
|
|
324
324
|
id: 'rag-agent',
|
|
325
325
|
name: 'RAG Agent',
|
|
326
|
-
model: 'openai/gpt-5.
|
|
326
|
+
model: 'openai/gpt-5.5',
|
|
327
327
|
instructions: `
|
|
328
328
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
329
329
|
${CHROMA_PROMPT}
|
|
@@ -340,7 +340,7 @@ import { ASTRA_PROMPT } from '@mastra/astra'
|
|
|
340
340
|
export const ragAgent = new Agent({
|
|
341
341
|
id: 'rag-agent',
|
|
342
342
|
name: 'RAG Agent',
|
|
343
|
-
model: 'openai/gpt-5.
|
|
343
|
+
model: 'openai/gpt-5.5',
|
|
344
344
|
instructions: `
|
|
345
345
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
346
346
|
${ASTRA_PROMPT}
|
|
@@ -357,7 +357,7 @@ import { LIBSQL_PROMPT } from '@mastra/libsql'
|
|
|
357
357
|
export const ragAgent = new Agent({
|
|
358
358
|
id: 'rag-agent',
|
|
359
359
|
name: 'RAG Agent',
|
|
360
|
-
model: 'openai/gpt-5.
|
|
360
|
+
model: 'openai/gpt-5.5',
|
|
361
361
|
instructions: `
|
|
362
362
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
363
363
|
${LIBSQL_PROMPT}
|
|
@@ -374,7 +374,7 @@ import { UPSTASH_PROMPT } from '@mastra/upstash'
|
|
|
374
374
|
export const ragAgent = new Agent({
|
|
375
375
|
id: 'rag-agent',
|
|
376
376
|
name: 'RAG Agent',
|
|
377
|
-
model: 'openai/gpt-5.
|
|
377
|
+
model: 'openai/gpt-5.5',
|
|
378
378
|
instructions: `
|
|
379
379
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
380
380
|
${UPSTASH_PROMPT}
|
|
@@ -391,7 +391,7 @@ import { VECTORIZE_PROMPT } from '@mastra/vectorize'
|
|
|
391
391
|
export const ragAgent = new Agent({
|
|
392
392
|
id: 'rag-agent',
|
|
393
393
|
name: 'RAG Agent',
|
|
394
|
-
model: 'openai/gpt-5.
|
|
394
|
+
model: 'openai/gpt-5.5',
|
|
395
395
|
instructions: `
|
|
396
396
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
397
397
|
${VECTORIZE_PROMPT}
|
|
@@ -408,7 +408,7 @@ import { MONGODB_PROMPT } from '@mastra/mongodb'
|
|
|
408
408
|
export const ragAgent = new Agent({
|
|
409
409
|
id: 'rag-agent',
|
|
410
410
|
name: 'RAG Agent',
|
|
411
|
-
model: 'openai/gpt-5.
|
|
411
|
+
model: 'openai/gpt-5.5',
|
|
412
412
|
instructions: `
|
|
413
413
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
414
414
|
${MONGODB_PROMPT}
|
|
@@ -425,7 +425,7 @@ import { OPENSEARCH_PROMPT } from '@mastra/opensearch'
|
|
|
425
425
|
export const ragAgent = new Agent({
|
|
426
426
|
id: 'rag-agent',
|
|
427
427
|
name: 'RAG Agent',
|
|
428
|
-
model: 'openai/gpt-5.
|
|
428
|
+
model: 'openai/gpt-5.5',
|
|
429
429
|
instructions: `
|
|
430
430
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
431
431
|
${OPENSEARCH_PROMPT}
|
|
@@ -442,7 +442,7 @@ import { S3VECTORS_PROMPT } from '@mastra/s3vectors'
|
|
|
442
442
|
export const ragAgent = new Agent({
|
|
443
443
|
id: 'rag-agent',
|
|
444
444
|
name: 'RAG Agent',
|
|
445
|
-
model: 'openai/gpt-5.
|
|
445
|
+
model: 'openai/gpt-5.5',
|
|
446
446
|
instructions: `
|
|
447
447
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
448
448
|
${S3VECTORS_PROMPT}
|
|
@@ -472,7 +472,10 @@ const initialResults = await pgVector.query({
|
|
|
472
472
|
})
|
|
473
473
|
|
|
474
474
|
// Create a relevance scorer
|
|
475
|
-
const relevanceProvider = new MastraAgentRelevanceScorer(
|
|
475
|
+
const relevanceProvider = new MastraAgentRelevanceScorer(
|
|
476
|
+
'relevance-scorer',
|
|
477
|
+
'openai/gpt-5.5',
|
|
478
|
+
)
|
|
476
479
|
|
|
477
480
|
// Re-rank the results
|
|
478
481
|
const rerankedResults = await rerank({
|
|
@@ -97,6 +97,9 @@ The storage implementation handles collection creation and management automatica
|
|
|
97
97
|
- `mastra_traces`: Stores telemetry and tracing data
|
|
98
98
|
- `mastra_scorers`: Stores scoring and evaluation data
|
|
99
99
|
- `mastra_resources`: Stores resource working memory data
|
|
100
|
+
- `mastra_notifications`: Stores notification inbox records and delivery metadata
|
|
101
|
+
|
|
102
|
+
`MongoDBStore` exposes notification storage through `getStore('notifications')`.
|
|
100
103
|
|
|
101
104
|
### Initialization
|
|
102
105
|
|
|
@@ -206,7 +209,7 @@ export const mongodbAgent = new Agent({
|
|
|
206
209
|
name: 'mongodb-agent',
|
|
207
210
|
instructions:
|
|
208
211
|
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
209
|
-
model: 'openai/gpt-5.
|
|
212
|
+
model: 'openai/gpt-5.5',
|
|
210
213
|
memory: new Memory({
|
|
211
214
|
storage: new MongoDBStore({
|
|
212
215
|
uri: process.env.MONGODB_URI!,
|
|
@@ -263,7 +263,7 @@ export const mongodbAgent = new Agent({
|
|
|
263
263
|
name: 'mongodb-agent',
|
|
264
264
|
instructions:
|
|
265
265
|
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
266
|
-
model: 'openai/gpt-5.
|
|
266
|
+
model: 'openai/gpt-5.5',
|
|
267
267
|
memory: new Memory({
|
|
268
268
|
storage: new MongoDBStore({
|
|
269
269
|
id: 'mongodb-storage',
|
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.9.
|
|
17
|
+
version: "1.9.1"};
|
|
18
18
|
var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
19
19
|
getSupportedOperators() {
|
|
20
20
|
return {
|
|
@@ -6287,6 +6287,294 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
6287
6287
|
}
|
|
6288
6288
|
}
|
|
6289
6289
|
};
|
|
6290
|
+
var statusTimestamp = (status, now) => {
|
|
6291
|
+
if (status === "delivered") return { deliveredAt: now };
|
|
6292
|
+
if (status === "seen") return { seenAt: now };
|
|
6293
|
+
if (status === "dismissed") return { dismissedAt: now };
|
|
6294
|
+
if (status === "archived") return { archivedAt: now };
|
|
6295
|
+
if (status === "discarded") return { discardedAt: now };
|
|
6296
|
+
return {};
|
|
6297
|
+
};
|
|
6298
|
+
var cloneDate = (value) => value ? new Date(value) : void 0;
|
|
6299
|
+
var cloneValue = (value) => value === void 0 ? void 0 : structuredClone(value);
|
|
6300
|
+
var cloneRecord = (record) => ({
|
|
6301
|
+
...record,
|
|
6302
|
+
createdAt: new Date(record.createdAt),
|
|
6303
|
+
updatedAt: new Date(record.updatedAt),
|
|
6304
|
+
deliveredAt: cloneDate(record.deliveredAt),
|
|
6305
|
+
seenAt: cloneDate(record.seenAt),
|
|
6306
|
+
dismissedAt: cloneDate(record.dismissedAt),
|
|
6307
|
+
archivedAt: cloneDate(record.archivedAt),
|
|
6308
|
+
discardedAt: cloneDate(record.discardedAt),
|
|
6309
|
+
deliverAt: cloneDate(record.deliverAt),
|
|
6310
|
+
summaryAt: cloneDate(record.summaryAt),
|
|
6311
|
+
lastDeliveryAttemptAt: cloneDate(record.lastDeliveryAttemptAt),
|
|
6312
|
+
payload: cloneValue(record.payload),
|
|
6313
|
+
attributes: cloneValue(record.attributes),
|
|
6314
|
+
metadata: cloneValue(record.metadata)
|
|
6315
|
+
});
|
|
6316
|
+
function rowToNotification(row) {
|
|
6317
|
+
return {
|
|
6318
|
+
id: row.id,
|
|
6319
|
+
threadId: row.threadId,
|
|
6320
|
+
source: row.source,
|
|
6321
|
+
kind: row.kind,
|
|
6322
|
+
priority: row.priority,
|
|
6323
|
+
status: row.status,
|
|
6324
|
+
summary: row.summary,
|
|
6325
|
+
payload: row.payload ?? void 0,
|
|
6326
|
+
resourceId: row.resourceId ?? void 0,
|
|
6327
|
+
agentId: row.agentId ?? void 0,
|
|
6328
|
+
sourceId: row.sourceId ?? void 0,
|
|
6329
|
+
dedupeKey: row.dedupeKey ?? void 0,
|
|
6330
|
+
coalesceKey: row.coalesceKey ?? void 0,
|
|
6331
|
+
coalescedCount: Number(row.coalescedCount ?? 1),
|
|
6332
|
+
attributes: row.attributes,
|
|
6333
|
+
createdAt: row.createdAt instanceof Date ? row.createdAt : new Date(row.createdAt),
|
|
6334
|
+
updatedAt: row.updatedAt instanceof Date ? row.updatedAt : new Date(row.updatedAt),
|
|
6335
|
+
deliveredAt: row.deliveredAt ? row.deliveredAt instanceof Date ? row.deliveredAt : new Date(row.deliveredAt) : void 0,
|
|
6336
|
+
seenAt: row.seenAt ? row.seenAt instanceof Date ? row.seenAt : new Date(row.seenAt) : void 0,
|
|
6337
|
+
dismissedAt: row.dismissedAt ? row.dismissedAt instanceof Date ? row.dismissedAt : new Date(row.dismissedAt) : void 0,
|
|
6338
|
+
archivedAt: row.archivedAt ? row.archivedAt instanceof Date ? row.archivedAt : new Date(row.archivedAt) : void 0,
|
|
6339
|
+
discardedAt: row.discardedAt ? row.discardedAt instanceof Date ? row.discardedAt : new Date(row.discardedAt) : void 0,
|
|
6340
|
+
deliverAt: row.deliverAt ? row.deliverAt instanceof Date ? row.deliverAt : new Date(row.deliverAt) : void 0,
|
|
6341
|
+
summaryAt: row.summaryAt ? row.summaryAt instanceof Date ? row.summaryAt : new Date(row.summaryAt) : void 0,
|
|
6342
|
+
deliveryReason: row.deliveryReason ?? void 0,
|
|
6343
|
+
deliveryAttempts: Number(row.deliveryAttempts ?? 0),
|
|
6344
|
+
lastDeliveryAttemptAt: row.lastDeliveryAttemptAt ? row.lastDeliveryAttemptAt instanceof Date ? row.lastDeliveryAttemptAt : new Date(row.lastDeliveryAttemptAt) : void 0,
|
|
6345
|
+
lastDeliveryError: row.lastDeliveryError ?? void 0,
|
|
6346
|
+
deliveredSignalId: row.deliveredSignalId ?? void 0,
|
|
6347
|
+
summarySignalId: row.summarySignalId ?? void 0,
|
|
6348
|
+
metadata: row.metadata ?? void 0
|
|
6349
|
+
};
|
|
6350
|
+
}
|
|
6351
|
+
function recordToDocument(record) {
|
|
6352
|
+
return {
|
|
6353
|
+
...record,
|
|
6354
|
+
payload: record.payload ?? null,
|
|
6355
|
+
resourceId: record.resourceId ?? null,
|
|
6356
|
+
agentId: record.agentId ?? null,
|
|
6357
|
+
sourceId: record.sourceId ?? null,
|
|
6358
|
+
dedupeKey: record.dedupeKey ?? null,
|
|
6359
|
+
coalesceKey: record.coalesceKey ?? null,
|
|
6360
|
+
attributes: record.attributes ?? null,
|
|
6361
|
+
deliveredAt: record.deliveredAt ?? null,
|
|
6362
|
+
seenAt: record.seenAt ?? null,
|
|
6363
|
+
dismissedAt: record.dismissedAt ?? null,
|
|
6364
|
+
archivedAt: record.archivedAt ?? null,
|
|
6365
|
+
discardedAt: record.discardedAt ?? null,
|
|
6366
|
+
deliverAt: record.deliverAt ?? null,
|
|
6367
|
+
summaryAt: record.summaryAt ?? null,
|
|
6368
|
+
deliveryReason: record.deliveryReason ?? null,
|
|
6369
|
+
lastDeliveryAttemptAt: record.lastDeliveryAttemptAt ?? null,
|
|
6370
|
+
lastDeliveryError: record.lastDeliveryError ?? null,
|
|
6371
|
+
deliveredSignalId: record.deliveredSignalId ?? null,
|
|
6372
|
+
summarySignalId: record.summarySignalId ?? null,
|
|
6373
|
+
metadata: record.metadata ?? null
|
|
6374
|
+
};
|
|
6375
|
+
}
|
|
6376
|
+
var NotificationsMongoDB = class _NotificationsMongoDB extends storage.NotificationsStorage {
|
|
6377
|
+
#connector;
|
|
6378
|
+
#skipDefaultIndexes;
|
|
6379
|
+
#indexes;
|
|
6380
|
+
static MANAGED_COLLECTIONS = [storage.TABLE_NOTIFICATIONS];
|
|
6381
|
+
constructor(config) {
|
|
6382
|
+
super();
|
|
6383
|
+
this.#connector = resolveMongoDBConfig(config);
|
|
6384
|
+
this.#skipDefaultIndexes = config.skipDefaultIndexes;
|
|
6385
|
+
this.#indexes = config.indexes?.filter(
|
|
6386
|
+
(idx) => _NotificationsMongoDB.MANAGED_COLLECTIONS.includes(idx.collection)
|
|
6387
|
+
);
|
|
6388
|
+
}
|
|
6389
|
+
async getCollection() {
|
|
6390
|
+
return this.#connector.getCollection(storage.TABLE_NOTIFICATIONS);
|
|
6391
|
+
}
|
|
6392
|
+
async init() {
|
|
6393
|
+
await this.createDefaultIndexes();
|
|
6394
|
+
await this.createCustomIndexes();
|
|
6395
|
+
}
|
|
6396
|
+
getDefaultIndexDefinitions() {
|
|
6397
|
+
return [
|
|
6398
|
+
{ collection: storage.TABLE_NOTIFICATIONS, keys: { threadId: 1, id: 1 }, options: { unique: true } },
|
|
6399
|
+
{ collection: storage.TABLE_NOTIFICATIONS, keys: { threadId: 1, status: 1, updatedAt: -1 } },
|
|
6400
|
+
{
|
|
6401
|
+
collection: storage.TABLE_NOTIFICATIONS,
|
|
6402
|
+
keys: { threadId: 1, source: 1, kind: 1, status: 1, agentId: 1, resourceId: 1, dedupeKey: 1, coalesceKey: 1 }
|
|
6403
|
+
},
|
|
6404
|
+
{ collection: storage.TABLE_NOTIFICATIONS, keys: { status: 1, deliverAt: 1, summaryAt: 1 } }
|
|
6405
|
+
];
|
|
6406
|
+
}
|
|
6407
|
+
async createDefaultIndexes() {
|
|
6408
|
+
if (this.#skipDefaultIndexes) return;
|
|
6409
|
+
for (const indexDef of this.getDefaultIndexDefinitions()) {
|
|
6410
|
+
try {
|
|
6411
|
+
const collection = await this.#connector.getCollection(indexDef.collection);
|
|
6412
|
+
await collection.createIndex(indexDef.keys, indexDef.options);
|
|
6413
|
+
} catch (error) {
|
|
6414
|
+
this.logger?.warn?.(`Failed to create index on ${indexDef.collection}:`, error);
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
}
|
|
6418
|
+
async createCustomIndexes() {
|
|
6419
|
+
if (!this.#indexes || this.#indexes.length === 0) return;
|
|
6420
|
+
for (const indexDef of this.#indexes) {
|
|
6421
|
+
try {
|
|
6422
|
+
const collection = await this.#connector.getCollection(indexDef.collection);
|
|
6423
|
+
await collection.createIndex(indexDef.keys, indexDef.options);
|
|
6424
|
+
} catch (error) {
|
|
6425
|
+
this.logger?.warn?.(`Failed to create custom index on ${indexDef.collection}:`, error);
|
|
6426
|
+
}
|
|
6427
|
+
}
|
|
6428
|
+
}
|
|
6429
|
+
async dangerouslyClearAll() {
|
|
6430
|
+
const collection = await this.getCollection();
|
|
6431
|
+
await collection.deleteMany({});
|
|
6432
|
+
}
|
|
6433
|
+
async createNotification(input) {
|
|
6434
|
+
const existing = await this.findCoalescable(input);
|
|
6435
|
+
const collection = await this.getCollection();
|
|
6436
|
+
if (existing) {
|
|
6437
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
6438
|
+
const attributes = input.attributes ? { ...cloneValue(existing.attributes), ...cloneValue(input.attributes) } : cloneValue(existing.attributes);
|
|
6439
|
+
const metadata = input.metadata ? { ...cloneValue(existing.metadata), ...cloneValue(input.metadata) } : cloneValue(existing.metadata);
|
|
6440
|
+
await collection.updateOne(
|
|
6441
|
+
{ threadId: existing.threadId, id: existing.id },
|
|
6442
|
+
{
|
|
6443
|
+
$set: {
|
|
6444
|
+
summary: input.summary,
|
|
6445
|
+
payload: cloneValue(input.payload ?? existing.payload) ?? null,
|
|
6446
|
+
priority: input.priority ?? existing.priority,
|
|
6447
|
+
attributes: attributes ?? null,
|
|
6448
|
+
updatedAt: now2,
|
|
6449
|
+
deliverAt: input.deliverAt ?? existing.deliverAt ?? null,
|
|
6450
|
+
summaryAt: input.summaryAt ?? existing.summaryAt ?? null,
|
|
6451
|
+
deliveryReason: input.deliveryReason ?? existing.deliveryReason ?? null,
|
|
6452
|
+
metadata: metadata ?? null
|
|
6453
|
+
},
|
|
6454
|
+
$inc: { coalescedCount: 1 }
|
|
6455
|
+
}
|
|
6456
|
+
);
|
|
6457
|
+
const updated = await this.getNotification({ threadId: existing.threadId, id: existing.id });
|
|
6458
|
+
if (!updated) throw new Error(`Notification ${existing.id} was not found for thread ${existing.threadId}`);
|
|
6459
|
+
return updated;
|
|
6460
|
+
}
|
|
6461
|
+
const now = input.createdAt ?? /* @__PURE__ */ new Date();
|
|
6462
|
+
const record = {
|
|
6463
|
+
id: input.id ?? crypto$1.randomUUID(),
|
|
6464
|
+
threadId: input.threadId,
|
|
6465
|
+
source: input.source,
|
|
6466
|
+
kind: input.kind,
|
|
6467
|
+
priority: input.priority ?? "medium",
|
|
6468
|
+
status: "pending",
|
|
6469
|
+
summary: input.summary,
|
|
6470
|
+
payload: cloneValue(input.payload),
|
|
6471
|
+
resourceId: input.resourceId,
|
|
6472
|
+
agentId: input.agentId,
|
|
6473
|
+
sourceId: input.sourceId,
|
|
6474
|
+
dedupeKey: input.dedupeKey,
|
|
6475
|
+
coalesceKey: input.coalesceKey,
|
|
6476
|
+
coalescedCount: 1,
|
|
6477
|
+
attributes: cloneValue(input.attributes),
|
|
6478
|
+
createdAt: now,
|
|
6479
|
+
updatedAt: now,
|
|
6480
|
+
deliverAt: input.deliverAt,
|
|
6481
|
+
summaryAt: input.summaryAt,
|
|
6482
|
+
deliveryReason: input.deliveryReason,
|
|
6483
|
+
deliveryAttempts: 0,
|
|
6484
|
+
metadata: cloneValue(input.metadata)
|
|
6485
|
+
};
|
|
6486
|
+
await collection.insertOne(recordToDocument(record));
|
|
6487
|
+
return cloneRecord(record);
|
|
6488
|
+
}
|
|
6489
|
+
async listNotifications(input) {
|
|
6490
|
+
const filter = { threadId: input.threadId };
|
|
6491
|
+
if (input.status) filter.status = Array.isArray(input.status) ? { $in: input.status } : input.status;
|
|
6492
|
+
if (input.priority) filter.priority = Array.isArray(input.priority) ? { $in: input.priority } : input.priority;
|
|
6493
|
+
if (input.source) filter.source = input.source;
|
|
6494
|
+
if (input.resourceId) filter.resourceId = input.resourceId;
|
|
6495
|
+
if (input.agentId) filter.agentId = input.agentId;
|
|
6496
|
+
if (input.search) {
|
|
6497
|
+
const search = input.search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6498
|
+
filter.$or = [{ summary: { $regex: search, $options: "i" } }, { kind: { $regex: search, $options: "i" } }];
|
|
6499
|
+
}
|
|
6500
|
+
const collection = await this.getCollection();
|
|
6501
|
+
const cursor = collection.find(filter).sort({ updatedAt: -1 });
|
|
6502
|
+
if (input.limit) cursor.limit(input.limit);
|
|
6503
|
+
const rows = await cursor.toArray();
|
|
6504
|
+
return rows.map((row) => rowToNotification(row));
|
|
6505
|
+
}
|
|
6506
|
+
async listDueNotifications(input) {
|
|
6507
|
+
const filter = {
|
|
6508
|
+
status: "pending",
|
|
6509
|
+
$or: [{ deliverAt: { $ne: null, $lte: input.now } }, { summaryAt: { $ne: null, $lte: input.now } }]
|
|
6510
|
+
};
|
|
6511
|
+
if (input.agentId) filter.agentId = input.agentId;
|
|
6512
|
+
if (input.resourceId) filter.resourceId = input.resourceId;
|
|
6513
|
+
const collection = await this.getCollection();
|
|
6514
|
+
const rows = await collection.find(filter).sort({ updatedAt: 1 }).toArray();
|
|
6515
|
+
const due = rows.map((row) => rowToNotification(row)).sort((a, b) => dueTime(a) - dueTime(b) || a.updatedAt.getTime() - b.updatedAt.getTime());
|
|
6516
|
+
return due.slice(0, input.limit ?? due.length).map(cloneRecord);
|
|
6517
|
+
}
|
|
6518
|
+
async getNotification(input) {
|
|
6519
|
+
const collection = await this.getCollection();
|
|
6520
|
+
const row = await collection.findOne({ threadId: input.threadId, id: input.id });
|
|
6521
|
+
return row ? rowToNotification(row) : null;
|
|
6522
|
+
}
|
|
6523
|
+
async updateNotification(input) {
|
|
6524
|
+
const existing = await this.getNotification({ threadId: input.threadId, id: input.id });
|
|
6525
|
+
if (!existing) {
|
|
6526
|
+
throw new Error(`Notification ${input.id} was not found for thread ${input.threadId}`);
|
|
6527
|
+
}
|
|
6528
|
+
const now = /* @__PURE__ */ new Date();
|
|
6529
|
+
const set = {
|
|
6530
|
+
...input.status ? { status: input.status, ...statusTimestamp(input.status, now) } : {},
|
|
6531
|
+
...input.summary !== void 0 ? { summary: input.summary } : {},
|
|
6532
|
+
...input.payload !== void 0 ? { payload: cloneValue(input.payload) } : {},
|
|
6533
|
+
...input.attributes !== void 0 ? { attributes: cloneValue(input.attributes) } : {},
|
|
6534
|
+
...input.metadata !== void 0 ? { metadata: cloneValue(input.metadata) } : {},
|
|
6535
|
+
...input.deliverAt !== void 0 ? { deliverAt: input.deliverAt } : {},
|
|
6536
|
+
...input.summaryAt !== void 0 ? { summaryAt: input.summaryAt } : {},
|
|
6537
|
+
...input.deliveryReason !== void 0 ? { deliveryReason: input.deliveryReason } : {},
|
|
6538
|
+
...input.deliveryAttempts !== void 0 ? { deliveryAttempts: input.deliveryAttempts } : {},
|
|
6539
|
+
...input.lastDeliveryAttemptAt !== void 0 ? { lastDeliveryAttemptAt: input.lastDeliveryAttemptAt } : {},
|
|
6540
|
+
...input.lastDeliveryError !== void 0 ? { lastDeliveryError: input.lastDeliveryError } : {},
|
|
6541
|
+
...input.deliveredSignalId !== void 0 ? { deliveredSignalId: input.deliveredSignalId } : {},
|
|
6542
|
+
...input.summarySignalId !== void 0 ? { summarySignalId: input.summarySignalId } : {},
|
|
6543
|
+
updatedAt: now
|
|
6544
|
+
};
|
|
6545
|
+
const collection = await this.getCollection();
|
|
6546
|
+
await collection.updateOne({ threadId: input.threadId, id: input.id }, { $set: set });
|
|
6547
|
+
const updated = await this.getNotification({ threadId: input.threadId, id: input.id });
|
|
6548
|
+
if (!updated) throw new Error(`Notification ${input.id} was not found for thread ${input.threadId}`);
|
|
6549
|
+
return updated;
|
|
6550
|
+
}
|
|
6551
|
+
async findCoalescable(input) {
|
|
6552
|
+
if (!input.dedupeKey && !input.coalesceKey) return void 0;
|
|
6553
|
+
const collection = await this.getCollection();
|
|
6554
|
+
const row = await collection.findOne(
|
|
6555
|
+
{
|
|
6556
|
+
threadId: input.threadId,
|
|
6557
|
+
source: input.source,
|
|
6558
|
+
kind: input.kind,
|
|
6559
|
+
status: "pending",
|
|
6560
|
+
agentId: input.agentId ?? null,
|
|
6561
|
+
resourceId: input.resourceId ?? null,
|
|
6562
|
+
$or: [
|
|
6563
|
+
...input.dedupeKey ? [{ dedupeKey: input.dedupeKey }] : [],
|
|
6564
|
+
...input.coalesceKey ? [{ coalesceKey: input.coalesceKey }] : []
|
|
6565
|
+
]
|
|
6566
|
+
},
|
|
6567
|
+
{ sort: { updatedAt: -1 } }
|
|
6568
|
+
);
|
|
6569
|
+
return row ? rowToNotification(row) : void 0;
|
|
6570
|
+
}
|
|
6571
|
+
};
|
|
6572
|
+
var dueTime = (record) => {
|
|
6573
|
+
const deliverAt = record.deliverAt?.getTime();
|
|
6574
|
+
const summaryAt = record.summaryAt?.getTime();
|
|
6575
|
+
if (deliverAt !== void 0 && summaryAt !== void 0) return Math.min(deliverAt, summaryAt);
|
|
6576
|
+
return deliverAt ?? summaryAt ?? Number.POSITIVE_INFINITY;
|
|
6577
|
+
};
|
|
6290
6578
|
var ObservabilityMongoDB = class _ObservabilityMongoDB extends storage.ObservabilityStorage {
|
|
6291
6579
|
#connector;
|
|
6292
6580
|
#skipDefaultIndexes;
|
|
@@ -10351,6 +10639,7 @@ var MongoDBStore = class extends storage.MastraCompositeStore {
|
|
|
10351
10639
|
indexes: config.indexes
|
|
10352
10640
|
};
|
|
10353
10641
|
const memory = new MemoryStorageMongoDB(domainConfig);
|
|
10642
|
+
const notifications = new NotificationsMongoDB(domainConfig);
|
|
10354
10643
|
const scores = new ScoresStorageMongoDB(domainConfig);
|
|
10355
10644
|
const workflows = new WorkflowsStorageMongoDB(domainConfig);
|
|
10356
10645
|
const observability = new ObservabilityMongoDB(domainConfig);
|
|
@@ -10368,6 +10657,7 @@ var MongoDBStore = class extends storage.MastraCompositeStore {
|
|
|
10368
10657
|
const schedules = new SchedulesMongoDB(domainConfig);
|
|
10369
10658
|
this.stores = {
|
|
10370
10659
|
memory,
|
|
10660
|
+
notifications,
|
|
10371
10661
|
scores,
|
|
10372
10662
|
workflows,
|
|
10373
10663
|
observability,
|
|
@@ -10516,6 +10806,7 @@ exports.MongoDBSkillsStorage = MongoDBSkillsStorage;
|
|
|
10516
10806
|
exports.MongoDBStore = MongoDBStore;
|
|
10517
10807
|
exports.MongoDBVector = MongoDBVector;
|
|
10518
10808
|
exports.MongoDBWorkspacesStorage = MongoDBWorkspacesStorage;
|
|
10809
|
+
exports.NotificationsMongoDB = NotificationsMongoDB;
|
|
10519
10810
|
exports.ObservabilityMongoDB = ObservabilityMongoDB;
|
|
10520
10811
|
exports.SchedulesMongoDB = SchedulesMongoDB;
|
|
10521
10812
|
exports.ScoresStorageMongoDB = ScoresStorageMongoDB;
|