@mastra/mongodb 1.11.1 → 1.12.0-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.
Files changed (33) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/docs/SKILL.md +1 -1
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/docs-memory-working-memory.md +2 -0
  5. package/dist/docs/references/docs-rag-retrieval.md +2 -0
  6. package/dist/docs/references/docs-rag-vector-databases.md +2 -0
  7. package/dist/docs/references/reference-storage-mongodb.md +2 -0
  8. package/dist/docs/references/reference-vectors-mongodb.md +2 -0
  9. package/dist/index.cjs +302 -2
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +303 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/storage/domains/background-tasks/index.d.ts +13 -0
  14. package/dist/storage/domains/background-tasks/index.d.ts.map +1 -1
  15. package/dist/storage/domains/experiments/index.d.ts +22 -1
  16. package/dist/storage/domains/experiments/index.d.ts.map +1 -1
  17. package/dist/storage/domains/memory/index.d.ts +14 -1
  18. package/dist/storage/domains/memory/index.d.ts.map +1 -1
  19. package/dist/storage/domains/notifications/index.d.ts +5 -1
  20. package/dist/storage/domains/notifications/index.d.ts.map +1 -1
  21. package/dist/storage/domains/observability/index.d.ts +5 -1
  22. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  23. package/dist/storage/domains/schedules/index.d.ts +11 -1
  24. package/dist/storage/domains/schedules/index.d.ts.map +1 -1
  25. package/dist/storage/domains/scores/index.d.ts +5 -1
  26. package/dist/storage/domains/scores/index.d.ts.map +1 -1
  27. package/dist/storage/domains/workflows/index.d.ts +8 -1
  28. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  29. package/dist/storage/retention.d.ts +121 -0
  30. package/dist/storage/retention.d.ts.map +1 -0
  31. package/dist/storage/types.d.ts +21 -0
  32. package/dist/storage/types.d.ts.map +1 -1
  33. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { v4 } from '@lukeed/uuid';
2
2
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
3
- import { createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, BlobStore, TABLE_SKILL_BLOBS, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, ensureDate, safelyParseJSON, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, ExperimentsStorage, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, NotificationsStorage, TABLE_NOTIFICATIONS, ObservabilityStorage, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, SchedulesStorage, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, ScorerDefinitionsStorage, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, TABLE_SCORERS, SkillsStorage, TABLE_SKILLS, TABLE_SKILL_VERSIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, WorkspacesStorage, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, MastraCompositeStore, TraceStatus, transformScoreRow as transformScoreRow$1 } from '@mastra/core/storage';
3
+ import { createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, BlobStore, TABLE_SKILL_BLOBS, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, ensureDate, safelyParseJSON, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, ExperimentsStorage, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, NotificationsStorage, TABLE_NOTIFICATIONS, ObservabilityStorage, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, SchedulesStorage, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, ScorerDefinitionsStorage, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, TABLE_SCORERS, SkillsStorage, TABLE_SKILLS, TABLE_SKILL_VERSIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, WorkspacesStorage, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, MastraCompositeStore, TraceStatus, parseDuration, transformScoreRow as transformScoreRow$1 } from '@mastra/core/storage';
4
4
  import { MastraVector, validateUpsertInput, validateVectorValues } from '@mastra/core/vector';
5
5
  import { MongoClient, MongoBulkWriteError } from 'mongodb';
6
6
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
@@ -13,7 +13,7 @@ import { skillSnapshotFieldValuesEqual } from '@mastra/core/storage/domains/skil
13
13
 
14
14
  // package.json
15
15
  var package_default = {
16
- version: "1.11.1"};
16
+ version: "1.12.0-alpha.0"};
17
17
  var MongoDBFilterTranslator = class extends BaseFilterTranslator {
18
18
  getSupportedOperators() {
19
19
  return {
@@ -1619,6 +1619,126 @@ var MongoDBAgentsStorage = class _MongoDBAgentsStorage extends AgentsStorage {
1619
1619
  return result;
1620
1620
  }
1621
1621
  };
1622
+ var DEFAULT_PRUNE_BATCH_SIZE = 1e3;
1623
+ async function ensureAnchorIndex(connector, target, logger) {
1624
+ if (!target.indexed) return;
1625
+ try {
1626
+ const collection = await connector.getCollection(target.table);
1627
+ await collection.createIndex({ [target.column]: -1 });
1628
+ } catch (error) {
1629
+ logger?.warn?.(`Failed to ensure retention index on ${target.table}(${target.column}):`, error);
1630
+ }
1631
+ }
1632
+ async function sleep(ms, signal) {
1633
+ if (ms <= 0 || signal?.aborted) return;
1634
+ await new Promise((resolve) => {
1635
+ const timer = setTimeout(() => {
1636
+ signal?.removeEventListener("abort", onAbort);
1637
+ resolve();
1638
+ }, ms);
1639
+ const onAbort = () => {
1640
+ clearTimeout(timer);
1641
+ resolve();
1642
+ };
1643
+ signal?.addEventListener("abort", onAbort, { once: true });
1644
+ });
1645
+ }
1646
+ function cutoffFor(policy, encoding, now = Date.now()) {
1647
+ const cutoffMs = now - parseDuration(policy.maxAge);
1648
+ if (encoding === "epoch-ms") return cutoffMs;
1649
+ if (encoding === "iso") return new Date(cutoffMs).toISOString();
1650
+ return new Date(cutoffMs);
1651
+ }
1652
+ async function pruneCollectionBatch({
1653
+ connector,
1654
+ table,
1655
+ column,
1656
+ cutoff,
1657
+ limit
1658
+ }) {
1659
+ const collection = await connector.getCollection(table);
1660
+ const docs = await collection.find({ [column]: { $lt: cutoff } }).project({ _id: 1 }).limit(limit).toArray();
1661
+ if (docs.length === 0) return 0;
1662
+ const result = await collection.deleteMany({ _id: { $in: docs.map((doc) => doc._id) } });
1663
+ return result.deletedCount;
1664
+ }
1665
+ async function runBatchedDelete({
1666
+ deleteBatch,
1667
+ batchSize,
1668
+ options
1669
+ }) {
1670
+ if (!Number.isSafeInteger(batchSize) || batchSize <= 0) {
1671
+ throw new Error(`retention batchSize must be a positive integer; received ${batchSize}`);
1672
+ }
1673
+ let deleted = 0;
1674
+ let batches = 0;
1675
+ while (true) {
1676
+ if (options?.signal?.aborted) return { deleted, done: false };
1677
+ if (options?.maxBatches !== void 0 && batches >= options.maxBatches) return { deleted, done: false };
1678
+ let limit = batchSize;
1679
+ if (options?.maxRows !== void 0) {
1680
+ const remaining = options.maxRows - deleted;
1681
+ if (remaining <= 0) return { deleted, done: false };
1682
+ limit = Math.min(limit, remaining);
1683
+ }
1684
+ const affected = await deleteBatch(limit);
1685
+ deleted += affected;
1686
+ batches += 1;
1687
+ if (affected < limit) return { deleted, done: true };
1688
+ if (options?.pauseMs) {
1689
+ await sleep(options.pauseMs, options.signal);
1690
+ }
1691
+ }
1692
+ }
1693
+ async function runPrune({
1694
+ connector,
1695
+ domain,
1696
+ targets,
1697
+ options,
1698
+ logger
1699
+ }) {
1700
+ const results = [];
1701
+ const now = Date.now();
1702
+ for (const target of targets) {
1703
+ if (options?.signal?.aborted) {
1704
+ results.push({ domain, table: target.table, deleted: 0, done: false });
1705
+ continue;
1706
+ }
1707
+ await ensureAnchorIndex(connector, target, logger);
1708
+ const cutoff = cutoffFor(target.policy, target.encoding, now);
1709
+ const batchSize = target.policy.batchSize ?? DEFAULT_PRUNE_BATCH_SIZE;
1710
+ const { deleted, done } = await runBatchedDelete({
1711
+ deleteBatch: (limit) => pruneCollectionBatch({ connector, table: target.table, column: target.column, cutoff, limit }),
1712
+ batchSize,
1713
+ options
1714
+ });
1715
+ results.push({ domain, table: target.table, deleted, done });
1716
+ }
1717
+ return results;
1718
+ }
1719
+ function resolveTargets({
1720
+ policies,
1721
+ descriptor,
1722
+ order,
1723
+ encodings
1724
+ }) {
1725
+ const targets = [];
1726
+ for (const key of order) {
1727
+ const policy = policies[key];
1728
+ const entry = descriptor[key];
1729
+ if (!policy || !entry) continue;
1730
+ targets.push({
1731
+ table: entry.table,
1732
+ column: entry.column,
1733
+ encoding: encodings?.[key] ?? (entry.anchorType === "epoch-ms" ? "epoch-ms" : "date"),
1734
+ indexed: entry.indexed ?? true,
1735
+ policy
1736
+ });
1737
+ }
1738
+ return targets;
1739
+ }
1740
+
1741
+ // src/storage/domains/background-tasks/index.ts
1622
1742
  function toDoc(task) {
1623
1743
  return {
1624
1744
  id: task.id,
@@ -1670,6 +1790,14 @@ var BackgroundTasksStorageMongoDB = class _BackgroundTasksStorageMongoDB extends
1670
1790
  #skipDefaultIndexes;
1671
1791
  #indexes;
1672
1792
  static MANAGED_COLLECTIONS = [TABLE_BACKGROUND_TASKS];
1793
+ /**
1794
+ * Anchor is `completedAt`, so age is measured from task completion; it stays
1795
+ * `null` while a task is in-flight, and `null $lt cutoff` never matches, so
1796
+ * pending/running tasks are never pruned regardless of age.
1797
+ */
1798
+ static retentionTables = {
1799
+ backgroundTasks: { table: TABLE_BACKGROUND_TASKS, column: "completedAt", indexed: true }
1800
+ };
1673
1801
  constructor(config) {
1674
1802
  super();
1675
1803
  this.#connector = resolveMongoDBConfig(config);
@@ -1681,6 +1809,20 @@ var BackgroundTasksStorageMongoDB = class _BackgroundTasksStorageMongoDB extends
1681
1809
  async getCollection() {
1682
1810
  return this.#connector.getCollection(TABLE_BACKGROUND_TASKS);
1683
1811
  }
1812
+ /**
1813
+ * Delete tasks completed longer ago than the policy's `maxAge`, batched.
1814
+ * `completedAt` is stored as an ISO-8601 string (see `toDoc`), so the cutoff
1815
+ * uses the `iso` encoding — lexicographic `$lt` on ISO strings is time-ordered.
1816
+ */
1817
+ async prune(policies, options) {
1818
+ const targets = resolveTargets({
1819
+ policies,
1820
+ descriptor: _BackgroundTasksStorageMongoDB.retentionTables,
1821
+ order: ["backgroundTasks"],
1822
+ encodings: { backgroundTasks: "iso" }
1823
+ });
1824
+ return runPrune({ connector: this.#connector, domain: "backgroundTasks", targets, options, logger: this.logger });
1825
+ }
1684
1826
  getDefaultIndexDefinitions() {
1685
1827
  return [
1686
1828
  { collection: TABLE_BACKGROUND_TASKS, keys: { id: 1 }, options: { unique: true } },
@@ -3081,6 +3223,15 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends Experim
3081
3223
  #skipDefaultIndexes;
3082
3224
  #indexes;
3083
3225
  static MANAGED_COLLECTIONS = [TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS];
3226
+ /**
3227
+ * Experiments prune as whole units: an experiment and its results are only
3228
+ * deleted together, once the experiment itself is old (anchored on the
3229
+ * parent's `completedAt`, a BSON date that stays `null` while running).
3230
+ * `results` is intentionally not an independent retention key.
3231
+ */
3232
+ static retentionTables = {
3233
+ experiments: { table: TABLE_EXPERIMENTS, column: "completedAt", indexed: true }
3234
+ };
3084
3235
  constructor(config) {
3085
3236
  super();
3086
3237
  this.#connector = resolveMongoDBConfig(config);
@@ -3092,6 +3243,57 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends Experim
3092
3243
  async getCollection(name) {
3093
3244
  return this.#connector.getCollection(name);
3094
3245
  }
3246
+ /**
3247
+ * Prune whole experiments older than the `experiments` policy's `maxAge`.
3248
+ *
3249
+ * Each batch collects up to `batchSize` aged experiment ids
3250
+ * (`completedAt < cutoff`; BSON type bracketing means `null` — still
3251
+ * running — never matches), then deletes their `experiment_results` rows and
3252
+ * the experiment rows for exactly that id set inside
3253
+ * `connector.withTransaction()` — atomic on replica sets, sequential
3254
+ * children-first on standalone — mirroring `deleteExperiment`. Hitting
3255
+ * `maxBatches`/`maxRows` or the abort signal between batches therefore never
3256
+ * leaves a run hollow (parent kept, results gone). Bounds count whole
3257
+ * experiments, not rows.
3258
+ */
3259
+ async prune(policies, options) {
3260
+ const policy = policies["experiments"];
3261
+ if (!policy || options?.signal?.aborted) {
3262
+ return policy ? [
3263
+ { domain: "experiments", table: TABLE_EXPERIMENT_RESULTS, deleted: 0, done: false },
3264
+ { domain: "experiments", table: TABLE_EXPERIMENTS, deleted: 0, done: false }
3265
+ ] : [];
3266
+ }
3267
+ await ensureAnchorIndex(
3268
+ this.#connector,
3269
+ { table: TABLE_EXPERIMENTS, column: "completedAt", indexed: true },
3270
+ this.logger
3271
+ );
3272
+ const cutoff = cutoffFor(policy, "date");
3273
+ const batchSize = policy.batchSize ?? DEFAULT_PRUNE_BATCH_SIZE;
3274
+ const experimentsCollection = await this.getCollection(TABLE_EXPERIMENTS);
3275
+ const resultsCollection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
3276
+ let childDeleted = 0;
3277
+ const parent = await runBatchedDelete({
3278
+ deleteBatch: async (limit) => {
3279
+ const docs = await experimentsCollection.find({ completedAt: { $lt: cutoff } }).project({ id: 1 }).limit(limit).toArray();
3280
+ if (docs.length === 0) return 0;
3281
+ const ids = docs.map((doc) => doc.id);
3282
+ return this.#connector.withTransaction(async (session) => {
3283
+ const children = await resultsCollection.deleteMany({ experimentId: { $in: ids } }, { session });
3284
+ childDeleted += children.deletedCount;
3285
+ const parents = await experimentsCollection.deleteMany({ id: { $in: ids } }, { session });
3286
+ return parents.deletedCount;
3287
+ });
3288
+ },
3289
+ batchSize,
3290
+ options
3291
+ });
3292
+ return [
3293
+ { domain: "experiments", table: TABLE_EXPERIMENT_RESULTS, deleted: childDeleted, done: parent.done },
3294
+ { domain: "experiments", table: TABLE_EXPERIMENTS, deleted: parent.deleted, done: parent.done }
3295
+ ];
3296
+ }
3095
3297
  // -------------------------------------------------------------------------
3096
3298
  // Index Management
3097
3299
  // -------------------------------------------------------------------------
@@ -4689,6 +4891,15 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends MemoryStorage {
4689
4891
  #indexes;
4690
4892
  /** Collections managed by this domain */
4691
4893
  static MANAGED_COLLECTIONS = [TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, OM_TABLE];
4894
+ /**
4895
+ * Retention-eligible collections. The observational-memory collection is
4896
+ * excluded: it has no timestamp anchor to age on. All anchors are BSON dates.
4897
+ */
4898
+ static retentionTables = {
4899
+ messages: { table: TABLE_MESSAGES, column: "createdAt", indexed: true },
4900
+ resources: { table: TABLE_RESOURCES, column: "createdAt", indexed: true },
4901
+ threads: { table: TABLE_THREADS, column: "createdAt", indexed: true }
4902
+ };
4692
4903
  constructor(config) {
4693
4904
  super();
4694
4905
  this.#connector = resolveMongoDBConfig(config);
@@ -4704,6 +4915,21 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends MemoryStorage {
4704
4915
  await this.createDefaultIndexes();
4705
4916
  await this.createCustomIndexes();
4706
4917
  }
4918
+ /**
4919
+ * Delete memory rows older than each table's `maxAge`, batched. Order is
4920
+ * messages → resources → threads so child rows never outlive the delete of
4921
+ * their thread. Like `deleteThread()`, this does not sweep vector-store
4922
+ * embeddings — semantic-recall vectors live in a separate vector store the
4923
+ * memory domain cannot reach; cleaning those up is the operator's concern.
4924
+ */
4925
+ async prune(policies, options) {
4926
+ const targets = resolveTargets({
4927
+ policies,
4928
+ descriptor: _MemoryStorageMongoDB.retentionTables,
4929
+ order: ["messages", "resources", "threads"]
4930
+ });
4931
+ return runPrune({ connector: this.#connector, domain: "memory", targets, options, logger: this.logger });
4932
+ }
4707
4933
  /**
4708
4934
  * Returns default index definitions for the memory domain collections.
4709
4935
  */
@@ -6657,6 +6883,10 @@ var NotificationsMongoDB = class _NotificationsMongoDB extends NotificationsStor
6657
6883
  #skipDefaultIndexes;
6658
6884
  #indexes;
6659
6885
  static MANAGED_COLLECTIONS = [TABLE_NOTIFICATIONS];
6886
+ /** Anchor is the notification's creation time, stored as a BSON date. */
6887
+ static retentionTables = {
6888
+ notifications: { table: TABLE_NOTIFICATIONS, column: "createdAt", indexed: true }
6889
+ };
6660
6890
  constructor(config) {
6661
6891
  super();
6662
6892
  this.#connector = resolveMongoDBConfig(config);
@@ -6668,6 +6898,15 @@ var NotificationsMongoDB = class _NotificationsMongoDB extends NotificationsStor
6668
6898
  async getCollection() {
6669
6899
  return this.#connector.getCollection(TABLE_NOTIFICATIONS);
6670
6900
  }
6901
+ /** Delete notifications older than the policy's `maxAge`, batched. */
6902
+ async prune(policies, options) {
6903
+ const targets = resolveTargets({
6904
+ policies,
6905
+ descriptor: _NotificationsMongoDB.retentionTables,
6906
+ order: ["notifications"]
6907
+ });
6908
+ return runPrune({ connector: this.#connector, domain: "notifications", targets, options, logger: this.logger });
6909
+ }
6671
6910
  async init() {
6672
6911
  await this.createDefaultIndexes();
6673
6912
  await this.createCustomIndexes();
@@ -6860,6 +7099,10 @@ var ObservabilityMongoDB = class _ObservabilityMongoDB extends ObservabilityStor
6860
7099
  #indexes;
6861
7100
  /** Collections managed by this domain */
6862
7101
  static MANAGED_COLLECTIONS = [TABLE_SPANS];
7102
+ /** Anchor is the span's start time, stored as a BSON date. */
7103
+ static retentionTables = {
7104
+ spans: { table: TABLE_SPANS, column: "startedAt", indexed: true }
7105
+ };
6863
7106
  constructor(config) {
6864
7107
  super();
6865
7108
  this.#connector = resolveMongoDBConfig(config);
@@ -6871,6 +7114,15 @@ var ObservabilityMongoDB = class _ObservabilityMongoDB extends ObservabilityStor
6871
7114
  async getCollection(name) {
6872
7115
  return this.#connector.getCollection(name);
6873
7116
  }
7117
+ /** Delete spans older than the `spans` policy's `maxAge`, batched. */
7118
+ async prune(policies, options) {
7119
+ const targets = resolveTargets({
7120
+ policies,
7121
+ descriptor: _ObservabilityMongoDB.retentionTables,
7122
+ order: ["spans"]
7123
+ });
7124
+ return runPrune({ connector: this.#connector, domain: "observability", targets, options, logger: this.logger });
7125
+ }
6874
7126
  /**
6875
7127
  * Returns default index definitions for the observability domain collections.
6876
7128
  * These indexes optimize common query patterns for span and trace lookups.
@@ -8285,6 +8537,16 @@ var SchedulesMongoDB = class _SchedulesMongoDB extends SchedulesStorage {
8285
8537
  #skipDefaultIndexes;
8286
8538
  #indexes;
8287
8539
  static MANAGED_COLLECTIONS = [TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS];
8540
+ /**
8541
+ * Only trigger (fire-history) rows are retention-eligible — schedule
8542
+ * definitions are config, not growth. Anchor `actual_fire_at` is stored as a
8543
+ * raw epoch-ms number, so `anchorType: 'epoch-ms'` keeps the cutoff numeric.
8544
+ * The default composite index `(schedule_id, actual_fire_at)` can't serve a
8545
+ * bare `actual_fire_at` range scan, hence the lazy single-field anchor index.
8546
+ */
8547
+ static retentionTables = {
8548
+ triggers: { table: TABLE_SCHEDULE_TRIGGERS, column: "actual_fire_at", anchorType: "epoch-ms", indexed: true }
8549
+ };
8288
8550
  constructor(config) {
8289
8551
  super();
8290
8552
  this.#connector = resolveMongoDBConfig(config);
@@ -8299,6 +8561,15 @@ var SchedulesMongoDB = class _SchedulesMongoDB extends SchedulesStorage {
8299
8561
  getTriggersCollection() {
8300
8562
  return this.#connector.getCollection(TABLE_SCHEDULE_TRIGGERS);
8301
8563
  }
8564
+ /** Delete trigger (fire-history) rows older than the `triggers` policy's `maxAge`, batched. */
8565
+ async prune(policies, options) {
8566
+ const targets = resolveTargets({
8567
+ policies,
8568
+ descriptor: _SchedulesMongoDB.retentionTables,
8569
+ order: ["triggers"]
8570
+ });
8571
+ return runPrune({ connector: this.#connector, domain: "schedules", targets, options, logger: this.logger });
8572
+ }
8302
8573
  getDefaultIndexDefinitions() {
8303
8574
  return [
8304
8575
  { collection: TABLE_SCHEDULES, keys: { id: 1 }, options: { unique: true } },
@@ -9002,6 +9273,10 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends ScoresStorage {
9002
9273
  #indexes;
9003
9274
  /** Collections managed by this domain */
9004
9275
  static MANAGED_COLLECTIONS = [TABLE_SCORERS];
9276
+ /** Anchor is the score row's creation time, stored as a BSON date. */
9277
+ static retentionTables = {
9278
+ scorers: { table: TABLE_SCORERS, column: "createdAt", indexed: true }
9279
+ };
9005
9280
  constructor(config) {
9006
9281
  super();
9007
9282
  this.#connector = resolveMongoDBConfig(config);
@@ -9013,6 +9288,15 @@ var ScoresStorageMongoDB = class _ScoresStorageMongoDB extends ScoresStorage {
9013
9288
  async getCollection(name) {
9014
9289
  return this.#connector.getCollection(name);
9015
9290
  }
9291
+ /** Delete scorer results older than the `scorers` policy's `maxAge`, batched. */
9292
+ async prune(policies, options) {
9293
+ const targets = resolveTargets({
9294
+ policies,
9295
+ descriptor: _ScoresStorageMongoDB.retentionTables,
9296
+ order: ["scorers"]
9297
+ });
9298
+ return runPrune({ connector: this.#connector, domain: "scores", targets, options, logger: this.logger });
9299
+ }
9016
9300
  /**
9017
9301
  * Returns default index definitions for the scores domain collections.
9018
9302
  * These indexes optimize common query patterns for score lookups.
@@ -9980,6 +10264,13 @@ var WorkflowsStorageMongoDB = class _WorkflowsStorageMongoDB extends WorkflowsSt
9980
10264
  #indexes;
9981
10265
  /** Collections managed by this domain */
9982
10266
  static MANAGED_COLLECTIONS = [TABLE_WORKFLOW_SNAPSHOT];
10267
+ /**
10268
+ * Anchor is `updatedAt` (BSON date), so the policy reads as inactivity:
10269
+ * a run is pruned only after its snapshot has not been touched for `maxAge`.
10270
+ */
10271
+ static retentionTables = {
10272
+ workflowSnapshot: { table: TABLE_WORKFLOW_SNAPSHOT, column: "updatedAt", indexed: true }
10273
+ };
9983
10274
  constructor(config) {
9984
10275
  super();
9985
10276
  this.#connector = resolveMongoDBConfig(config);
@@ -9988,6 +10279,15 @@ var WorkflowsStorageMongoDB = class _WorkflowsStorageMongoDB extends WorkflowsSt
9988
10279
  (idx) => _WorkflowsStorageMongoDB.MANAGED_COLLECTIONS.includes(idx.collection)
9989
10280
  );
9990
10281
  }
10282
+ /** Delete workflow snapshots idle for longer than the policy's `maxAge`, batched. */
10283
+ async prune(policies, options) {
10284
+ const targets = resolveTargets({
10285
+ policies,
10286
+ descriptor: _WorkflowsStorageMongoDB.retentionTables,
10287
+ order: ["workflowSnapshot"]
10288
+ });
10289
+ return runPrune({ connector: this.#connector, domain: "workflows", targets, options, logger: this.logger });
10290
+ }
9991
10291
  supportsConcurrentUpdates() {
9992
10292
  return true;
9993
10293
  }
@@ -10995,7 +11295,7 @@ var MongoDBStore = class extends MastraCompositeStore {
10995
11295
  #connector;
10996
11296
  stores;
10997
11297
  constructor(config) {
10998
- super({ id: config.id, name: "MongoDBStore", disableInit: config.disableInit });
11298
+ super({ id: config.id, name: "MongoDBStore", disableInit: config.disableInit, retention: config.retention });
10999
11299
  this.#connector = resolveMongoDBConfig(config);
11000
11300
  const domainConfig = {
11001
11301
  connector: this.#connector,