@mastra/mongodb 1.5.6 → 1.6.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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
2
- import { createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, BlobStore, TABLE_SKILL_BLOBS, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, safelyParseJSON, ObservabilityStorage, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, 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';
2
+ import { createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, 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, ObservabilityStorage, TABLE_SPANS, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, 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
3
  import { MastraVector, validateUpsertInput, validateVectorValues } from '@mastra/core/vector';
4
4
  import { MongoClient } from 'mongodb';
5
5
  import { v4 } from 'uuid';
@@ -12,7 +12,7 @@ import { saveScorePayloadSchema } from '@mastra/core/evals';
12
12
 
13
13
  // package.json
14
14
  var package_default = {
15
- version: "1.5.6"};
15
+ version: "1.6.0"};
16
16
  var MongoDBFilterTranslator = class extends BaseFilterTranslator {
17
17
  getSupportedOperators() {
18
18
  return {
@@ -1698,6 +1698,1357 @@ var MongoDBBlobStore = class _MongoDBBlobStore extends BlobStore {
1698
1698
  };
1699
1699
  }
1700
1700
  };
1701
+ var MANAGED_COLLECTIONS = [TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS];
1702
+ var MongoDBDatasetsStorage = class extends DatasetsStorage {
1703
+ #connector;
1704
+ #skipDefaultIndexes;
1705
+ #indexes;
1706
+ constructor(config) {
1707
+ super();
1708
+ this.#connector = resolveMongoDBConfig(config);
1709
+ this.#skipDefaultIndexes = config.skipDefaultIndexes ?? false;
1710
+ this.#indexes = (config.indexes ?? []).filter(
1711
+ (i) => MANAGED_COLLECTIONS.includes(i.collection)
1712
+ );
1713
+ }
1714
+ getCollection(name) {
1715
+ return this.#connector.getCollection(name);
1716
+ }
1717
+ // --- Index management ---
1718
+ getDefaultIndexDefinitions() {
1719
+ return [
1720
+ { collection: TABLE_DATASETS, keys: { id: 1 }, options: { name: "idx_datasets_id", unique: true } },
1721
+ { collection: TABLE_DATASETS, keys: { createdAt: -1, id: 1 }, options: { name: "idx_datasets_createdat_id" } },
1722
+ { collection: TABLE_DATASET_ITEMS, keys: { datasetId: 1 }, options: { name: "idx_dataset_items_datasetid" } },
1723
+ {
1724
+ collection: TABLE_DATASET_ITEMS,
1725
+ keys: { datasetId: 1, validTo: 1 },
1726
+ options: { name: "idx_dataset_items_datasetid_validto" }
1727
+ },
1728
+ {
1729
+ collection: TABLE_DATASET_ITEMS,
1730
+ keys: { datasetId: 1, isDeleted: 1 },
1731
+ options: { name: "idx_dataset_items_datasetid_isdeleted" }
1732
+ },
1733
+ {
1734
+ collection: TABLE_DATASET_ITEMS,
1735
+ keys: { id: 1, validTo: 1 },
1736
+ options: { name: "idx_dataset_items_id_validto" }
1737
+ },
1738
+ {
1739
+ collection: TABLE_DATASET_ITEMS,
1740
+ keys: { datasetId: 1, datasetVersion: 1 },
1741
+ options: { name: "idx_dataset_items_datasetid_version" }
1742
+ },
1743
+ {
1744
+ collection: TABLE_DATASET_ITEMS,
1745
+ keys: { datasetId: 1, validTo: 1, isDeleted: 1, createdAt: -1, id: 1 },
1746
+ options: { name: "idx_dataset_items_list" }
1747
+ },
1748
+ {
1749
+ collection: TABLE_DATASET_VERSIONS,
1750
+ keys: { datasetId: 1 },
1751
+ options: { name: "idx_dataset_versions_datasetid" }
1752
+ },
1753
+ {
1754
+ collection: TABLE_DATASET_VERSIONS,
1755
+ keys: { datasetId: 1, version: 1 },
1756
+ options: { name: "idx_dataset_versions_datasetid_version", unique: true }
1757
+ }
1758
+ ];
1759
+ }
1760
+ async createDefaultIndexes() {
1761
+ if (this.#skipDefaultIndexes) return;
1762
+ for (const indexDef of this.getDefaultIndexDefinitions()) {
1763
+ try {
1764
+ const collection = await this.getCollection(indexDef.collection);
1765
+ await collection.createIndex(indexDef.keys, indexDef.options);
1766
+ } catch (error) {
1767
+ this.logger?.warn?.(`Failed to create index on ${indexDef.collection}:`, error);
1768
+ }
1769
+ }
1770
+ }
1771
+ async createCustomIndexes() {
1772
+ for (const indexDef of this.#indexes) {
1773
+ try {
1774
+ const collection = await this.getCollection(indexDef.collection);
1775
+ await collection.createIndex(indexDef.keys, indexDef.options);
1776
+ } catch (error) {
1777
+ this.logger?.warn?.(`Failed to create custom index on ${indexDef.collection}:`, error);
1778
+ }
1779
+ }
1780
+ }
1781
+ async init() {
1782
+ await this.createDefaultIndexes();
1783
+ await this.createCustomIndexes();
1784
+ }
1785
+ // --- Row transformations ---
1786
+ transformDatasetRow(row) {
1787
+ return {
1788
+ id: row.id,
1789
+ name: row.name,
1790
+ description: row.description ?? void 0,
1791
+ metadata: typeof row.metadata === "string" ? safelyParseJSON(row.metadata) : row.metadata ?? void 0,
1792
+ inputSchema: typeof row.inputSchema === "string" ? safelyParseJSON(row.inputSchema) : row.inputSchema,
1793
+ groundTruthSchema: typeof row.groundTruthSchema === "string" ? safelyParseJSON(row.groundTruthSchema) : row.groundTruthSchema,
1794
+ requestContextSchema: typeof row.requestContextSchema === "string" ? safelyParseJSON(row.requestContextSchema) : row.requestContextSchema,
1795
+ tags: typeof row.tags === "string" ? safelyParseJSON(row.tags) : row.tags ?? void 0,
1796
+ targetType: row.targetType ?? void 0,
1797
+ targetIds: typeof row.targetIds === "string" ? safelyParseJSON(row.targetIds) : row.targetIds ?? void 0,
1798
+ version: row.version ?? 0,
1799
+ createdAt: ensureDate(row.createdAt),
1800
+ updatedAt: ensureDate(row.updatedAt)
1801
+ };
1802
+ }
1803
+ transformItemRow(row) {
1804
+ return {
1805
+ id: row.id,
1806
+ datasetId: row.datasetId,
1807
+ datasetVersion: row.datasetVersion,
1808
+ input: typeof row.input === "string" ? safelyParseJSON(row.input) : row.input,
1809
+ groundTruth: typeof row.groundTruth === "string" ? safelyParseJSON(row.groundTruth) : row.groundTruth,
1810
+ requestContext: typeof row.requestContext === "string" ? safelyParseJSON(row.requestContext) : row.requestContext,
1811
+ metadata: typeof row.metadata === "string" ? safelyParseJSON(row.metadata) : row.metadata,
1812
+ source: typeof row.source === "string" ? safelyParseJSON(row.source) : row.source,
1813
+ createdAt: ensureDate(row.createdAt),
1814
+ updatedAt: ensureDate(row.updatedAt)
1815
+ };
1816
+ }
1817
+ transformItemRowFull(row) {
1818
+ return {
1819
+ ...this.transformItemRow(row),
1820
+ validTo: row.validTo ?? null,
1821
+ isDeleted: row.isDeleted ?? false
1822
+ };
1823
+ }
1824
+ transformDatasetVersionRow(row) {
1825
+ return {
1826
+ id: row.id,
1827
+ datasetId: row.datasetId,
1828
+ version: row.version,
1829
+ createdAt: ensureDate(row.createdAt)
1830
+ };
1831
+ }
1832
+ // --- Dataset CRUD ---
1833
+ async createDataset(input) {
1834
+ try {
1835
+ const id = randomUUID();
1836
+ const now = /* @__PURE__ */ new Date();
1837
+ const collection = await this.getCollection(TABLE_DATASETS);
1838
+ const record = {
1839
+ id,
1840
+ name: input.name,
1841
+ description: input.description ?? null,
1842
+ metadata: input.metadata ?? null,
1843
+ inputSchema: input.inputSchema ?? null,
1844
+ groundTruthSchema: input.groundTruthSchema ?? null,
1845
+ requestContextSchema: input.requestContextSchema ?? null,
1846
+ targetType: input.targetType ?? null,
1847
+ targetIds: input.targetIds ?? null,
1848
+ version: 0,
1849
+ createdAt: now,
1850
+ updatedAt: now
1851
+ };
1852
+ await collection.insertOne(record);
1853
+ return this.transformDatasetRow(record);
1854
+ } catch (error) {
1855
+ if (error instanceof MastraError) throw error;
1856
+ throw new MastraError(
1857
+ {
1858
+ id: createStorageErrorId("MONGODB", "CREATE_DATASET", "FAILED"),
1859
+ domain: ErrorDomain.STORAGE,
1860
+ category: ErrorCategory.THIRD_PARTY
1861
+ },
1862
+ error
1863
+ );
1864
+ }
1865
+ }
1866
+ async getDatasetById({ id }) {
1867
+ try {
1868
+ const collection = await this.getCollection(TABLE_DATASETS);
1869
+ const row = await collection.findOne({ id });
1870
+ return row ? this.transformDatasetRow(row) : null;
1871
+ } catch (error) {
1872
+ throw new MastraError(
1873
+ {
1874
+ id: createStorageErrorId("MONGODB", "GET_DATASET", "FAILED"),
1875
+ domain: ErrorDomain.STORAGE,
1876
+ category: ErrorCategory.THIRD_PARTY
1877
+ },
1878
+ error
1879
+ );
1880
+ }
1881
+ }
1882
+ async _doUpdateDataset(args) {
1883
+ try {
1884
+ const existing = await this.getDatasetById({ id: args.id });
1885
+ if (!existing) {
1886
+ throw new MastraError({
1887
+ id: createStorageErrorId("MONGODB", "UPDATE_DATASET", "NOT_FOUND"),
1888
+ domain: ErrorDomain.STORAGE,
1889
+ category: ErrorCategory.USER,
1890
+ details: { datasetId: args.id }
1891
+ });
1892
+ }
1893
+ const collection = await this.getCollection(TABLE_DATASETS);
1894
+ const now = /* @__PURE__ */ new Date();
1895
+ const updateDoc = { updatedAt: now };
1896
+ if (args.name !== void 0) updateDoc.name = args.name;
1897
+ if (args.description !== void 0) updateDoc.description = args.description;
1898
+ if (args.metadata !== void 0) updateDoc.metadata = args.metadata;
1899
+ if (args.inputSchema !== void 0) updateDoc.inputSchema = args.inputSchema;
1900
+ if (args.groundTruthSchema !== void 0) updateDoc.groundTruthSchema = args.groundTruthSchema;
1901
+ if (args.requestContextSchema !== void 0) updateDoc.requestContextSchema = args.requestContextSchema;
1902
+ if (args.tags !== void 0) updateDoc.tags = args.tags;
1903
+ if (args.targetType !== void 0) updateDoc.targetType = args.targetType;
1904
+ if (args.targetIds !== void 0) updateDoc.targetIds = args.targetIds;
1905
+ await collection.updateOne({ id: args.id }, { $set: updateDoc });
1906
+ const updated = await this.getDatasetById({ id: args.id });
1907
+ return updated;
1908
+ } catch (error) {
1909
+ if (error instanceof MastraError) throw error;
1910
+ throw new MastraError(
1911
+ {
1912
+ id: createStorageErrorId("MONGODB", "UPDATE_DATASET", "FAILED"),
1913
+ domain: ErrorDomain.STORAGE,
1914
+ category: ErrorCategory.THIRD_PARTY
1915
+ },
1916
+ error
1917
+ );
1918
+ }
1919
+ }
1920
+ async deleteDataset({ id }) {
1921
+ try {
1922
+ try {
1923
+ const experimentsCollection = await this.getCollection(TABLE_EXPERIMENTS);
1924
+ const experimentIds = await experimentsCollection.find({ datasetId: id }, { projection: { id: 1 } }).toArray();
1925
+ if (experimentIds.length > 0) {
1926
+ const resultsCollection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
1927
+ await resultsCollection.deleteMany({
1928
+ experimentId: { $in: experimentIds.map((e) => e.id) }
1929
+ });
1930
+ }
1931
+ await experimentsCollection.updateMany({ datasetId: id }, { $set: { datasetId: null, datasetVersion: null } });
1932
+ } catch (e) {
1933
+ const isNamespaceNotFound = e instanceof Error && "code" in e && e.code === 26;
1934
+ if (!isNamespaceNotFound) throw e;
1935
+ }
1936
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
1937
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
1938
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
1939
+ await versionsCollection.deleteMany({ datasetId: id });
1940
+ await itemsCollection.deleteMany({ datasetId: id });
1941
+ await datasetsCollection.deleteOne({ id });
1942
+ } catch (error) {
1943
+ if (error instanceof MastraError) throw error;
1944
+ throw new MastraError(
1945
+ {
1946
+ id: createStorageErrorId("MONGODB", "DELETE_DATASET", "FAILED"),
1947
+ domain: ErrorDomain.STORAGE,
1948
+ category: ErrorCategory.THIRD_PARTY
1949
+ },
1950
+ error
1951
+ );
1952
+ }
1953
+ }
1954
+ async listDatasets(args) {
1955
+ try {
1956
+ const { page, perPage: perPageInput } = args.pagination;
1957
+ const collection = await this.getCollection(TABLE_DATASETS);
1958
+ const total = await collection.countDocuments({});
1959
+ if (total === 0) {
1960
+ return { datasets: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
1961
+ }
1962
+ const perPage = normalizePerPage(perPageInput, 100);
1963
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1964
+ if (perPage === 0) {
1965
+ return { datasets: [], pagination: { total, page, perPage: perPageForResponse, hasMore: total > 0 } };
1966
+ }
1967
+ const limitValue = perPageInput === false ? total : perPage;
1968
+ const rows = await collection.find({}).sort({ createdAt: -1, id: 1 }).skip(offset).limit(limitValue).toArray();
1969
+ return {
1970
+ datasets: rows.map((row) => this.transformDatasetRow(row)),
1971
+ pagination: {
1972
+ total,
1973
+ page,
1974
+ perPage: perPageForResponse,
1975
+ hasMore: perPageInput === false ? false : offset + perPage < total
1976
+ }
1977
+ };
1978
+ } catch (error) {
1979
+ throw new MastraError(
1980
+ {
1981
+ id: createStorageErrorId("MONGODB", "LIST_DATASETS", "FAILED"),
1982
+ domain: ErrorDomain.STORAGE,
1983
+ category: ErrorCategory.THIRD_PARTY
1984
+ },
1985
+ error
1986
+ );
1987
+ }
1988
+ }
1989
+ // --- Item mutations (SCD-2) ---
1990
+ async _doAddItem(args) {
1991
+ try {
1992
+ const id = randomUUID();
1993
+ const versionId = randomUUID();
1994
+ const now = /* @__PURE__ */ new Date();
1995
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
1996
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
1997
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
1998
+ const result = await datasetsCollection.findOneAndUpdate(
1999
+ { id: args.datasetId },
2000
+ { $inc: { version: 1 } },
2001
+ { returnDocument: "after" }
2002
+ );
2003
+ if (!result) {
2004
+ throw new MastraError({
2005
+ id: createStorageErrorId("MONGODB", "ADD_ITEM", "DATASET_NOT_FOUND"),
2006
+ domain: ErrorDomain.STORAGE,
2007
+ category: ErrorCategory.USER,
2008
+ details: { datasetId: args.datasetId }
2009
+ });
2010
+ }
2011
+ const newVersion = result.version;
2012
+ await itemsCollection.insertOne({
2013
+ id,
2014
+ datasetId: args.datasetId,
2015
+ datasetVersion: newVersion,
2016
+ validTo: null,
2017
+ isDeleted: false,
2018
+ input: args.input,
2019
+ groundTruth: args.groundTruth ?? null,
2020
+ requestContext: args.requestContext ?? null,
2021
+ metadata: args.metadata ?? null,
2022
+ source: args.source ?? null,
2023
+ createdAt: now,
2024
+ updatedAt: now
2025
+ });
2026
+ await versionsCollection.insertOne({
2027
+ id: versionId,
2028
+ datasetId: args.datasetId,
2029
+ version: newVersion,
2030
+ createdAt: now
2031
+ });
2032
+ return {
2033
+ id,
2034
+ datasetId: args.datasetId,
2035
+ datasetVersion: newVersion,
2036
+ input: args.input,
2037
+ groundTruth: args.groundTruth,
2038
+ requestContext: args.requestContext,
2039
+ metadata: args.metadata,
2040
+ source: args.source,
2041
+ createdAt: now,
2042
+ updatedAt: now
2043
+ };
2044
+ } catch (error) {
2045
+ if (error instanceof MastraError) throw error;
2046
+ throw new MastraError(
2047
+ {
2048
+ id: createStorageErrorId("MONGODB", "ADD_ITEM", "FAILED"),
2049
+ domain: ErrorDomain.STORAGE,
2050
+ category: ErrorCategory.THIRD_PARTY
2051
+ },
2052
+ error
2053
+ );
2054
+ }
2055
+ }
2056
+ async _doUpdateItem(args) {
2057
+ try {
2058
+ const existing = await this.getItemById({ id: args.id });
2059
+ if (!existing) {
2060
+ throw new MastraError({
2061
+ id: createStorageErrorId("MONGODB", "UPDATE_ITEM", "NOT_FOUND"),
2062
+ domain: ErrorDomain.STORAGE,
2063
+ category: ErrorCategory.USER,
2064
+ details: { itemId: args.id }
2065
+ });
2066
+ }
2067
+ if (existing.datasetId !== args.datasetId) {
2068
+ throw new MastraError({
2069
+ id: createStorageErrorId("MONGODB", "UPDATE_ITEM", "DATASET_MISMATCH"),
2070
+ domain: ErrorDomain.STORAGE,
2071
+ category: ErrorCategory.USER,
2072
+ details: { itemId: args.id, expectedDatasetId: args.datasetId, actualDatasetId: existing.datasetId }
2073
+ });
2074
+ }
2075
+ const hasChanges = args.input !== void 0 || args.groundTruth !== void 0 || args.requestContext !== void 0 || args.metadata !== void 0 || args.source !== void 0;
2076
+ if (!hasChanges) {
2077
+ return existing;
2078
+ }
2079
+ const now = /* @__PURE__ */ new Date();
2080
+ const versionId = randomUUID();
2081
+ const mergedInput = args.input !== void 0 ? args.input : existing.input;
2082
+ const mergedGroundTruth = args.groundTruth !== void 0 ? args.groundTruth : existing.groundTruth;
2083
+ const mergedRequestContext = args.requestContext !== void 0 ? args.requestContext : existing.requestContext;
2084
+ const mergedMetadata = args.metadata !== void 0 ? args.metadata : existing.metadata;
2085
+ const mergedSource = args.source !== void 0 ? args.source : existing.source;
2086
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
2087
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
2088
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
2089
+ const result = await datasetsCollection.findOneAndUpdate(
2090
+ { id: args.datasetId },
2091
+ { $inc: { version: 1 } },
2092
+ { returnDocument: "after" }
2093
+ );
2094
+ if (!result) {
2095
+ throw new MastraError({
2096
+ id: createStorageErrorId("MONGODB", "UPDATE_ITEM", "DATASET_NOT_FOUND"),
2097
+ domain: ErrorDomain.STORAGE,
2098
+ category: ErrorCategory.USER,
2099
+ details: { datasetId: args.datasetId }
2100
+ });
2101
+ }
2102
+ const newVersion = result.version;
2103
+ await itemsCollection.updateOne(
2104
+ { id: args.id, validTo: null, isDeleted: false },
2105
+ { $set: { validTo: newVersion } }
2106
+ );
2107
+ await itemsCollection.insertOne({
2108
+ id: args.id,
2109
+ datasetId: args.datasetId,
2110
+ datasetVersion: newVersion,
2111
+ validTo: null,
2112
+ isDeleted: false,
2113
+ input: mergedInput,
2114
+ groundTruth: mergedGroundTruth,
2115
+ requestContext: mergedRequestContext,
2116
+ metadata: mergedMetadata,
2117
+ source: mergedSource,
2118
+ createdAt: existing.createdAt,
2119
+ updatedAt: now
2120
+ });
2121
+ await versionsCollection.insertOne({
2122
+ id: versionId,
2123
+ datasetId: args.datasetId,
2124
+ version: newVersion,
2125
+ createdAt: now
2126
+ });
2127
+ return {
2128
+ ...existing,
2129
+ datasetVersion: newVersion,
2130
+ input: mergedInput,
2131
+ groundTruth: mergedGroundTruth,
2132
+ requestContext: mergedRequestContext,
2133
+ metadata: mergedMetadata,
2134
+ source: mergedSource,
2135
+ updatedAt: now
2136
+ };
2137
+ } catch (error) {
2138
+ if (error instanceof MastraError) throw error;
2139
+ throw new MastraError(
2140
+ {
2141
+ id: createStorageErrorId("MONGODB", "UPDATE_ITEM", "FAILED"),
2142
+ domain: ErrorDomain.STORAGE,
2143
+ category: ErrorCategory.THIRD_PARTY
2144
+ },
2145
+ error
2146
+ );
2147
+ }
2148
+ }
2149
+ async _doDeleteItem({ id, datasetId }) {
2150
+ try {
2151
+ const existing = await this.getItemById({ id });
2152
+ if (!existing) return;
2153
+ if (existing.datasetId !== datasetId) {
2154
+ throw new MastraError({
2155
+ id: createStorageErrorId("MONGODB", "DELETE_ITEM", "DATASET_MISMATCH"),
2156
+ domain: ErrorDomain.STORAGE,
2157
+ category: ErrorCategory.USER,
2158
+ details: { itemId: id, expectedDatasetId: datasetId, actualDatasetId: existing.datasetId }
2159
+ });
2160
+ }
2161
+ const now = /* @__PURE__ */ new Date();
2162
+ const versionId = randomUUID();
2163
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
2164
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
2165
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
2166
+ const result = await datasetsCollection.findOneAndUpdate(
2167
+ { id: datasetId },
2168
+ { $inc: { version: 1 } },
2169
+ { returnDocument: "after" }
2170
+ );
2171
+ if (!result) {
2172
+ throw new MastraError({
2173
+ id: createStorageErrorId("MONGODB", "DELETE_ITEM", "DATASET_NOT_FOUND"),
2174
+ domain: ErrorDomain.STORAGE,
2175
+ category: ErrorCategory.USER,
2176
+ details: { datasetId }
2177
+ });
2178
+ }
2179
+ const newVersion = result.version;
2180
+ await itemsCollection.updateOne({ id, validTo: null, isDeleted: false }, { $set: { validTo: newVersion } });
2181
+ await itemsCollection.insertOne({
2182
+ id,
2183
+ datasetId,
2184
+ datasetVersion: newVersion,
2185
+ validTo: null,
2186
+ isDeleted: true,
2187
+ input: existing.input,
2188
+ groundTruth: existing.groundTruth,
2189
+ requestContext: existing.requestContext,
2190
+ metadata: existing.metadata,
2191
+ source: existing.source,
2192
+ createdAt: existing.createdAt,
2193
+ updatedAt: now
2194
+ });
2195
+ await versionsCollection.insertOne({
2196
+ id: versionId,
2197
+ datasetId,
2198
+ version: newVersion,
2199
+ createdAt: now
2200
+ });
2201
+ } catch (error) {
2202
+ if (error instanceof MastraError) throw error;
2203
+ throw new MastraError(
2204
+ {
2205
+ id: createStorageErrorId("MONGODB", "DELETE_ITEM", "FAILED"),
2206
+ domain: ErrorDomain.STORAGE,
2207
+ category: ErrorCategory.THIRD_PARTY
2208
+ },
2209
+ error
2210
+ );
2211
+ }
2212
+ }
2213
+ // --- Batch operations ---
2214
+ async _doBatchInsertItems(input) {
2215
+ try {
2216
+ const dataset = await this.getDatasetById({ id: input.datasetId });
2217
+ if (!dataset) {
2218
+ throw new MastraError({
2219
+ id: createStorageErrorId("MONGODB", "BULK_ADD_ITEMS", "DATASET_NOT_FOUND"),
2220
+ domain: ErrorDomain.STORAGE,
2221
+ category: ErrorCategory.USER,
2222
+ details: { datasetId: input.datasetId }
2223
+ });
2224
+ }
2225
+ if (!input.items || input.items.length === 0) {
2226
+ return [];
2227
+ }
2228
+ const now = /* @__PURE__ */ new Date();
2229
+ const versionId = randomUUID();
2230
+ const itemsWithIds = input.items.map((itemInput) => ({
2231
+ generatedId: randomUUID(),
2232
+ itemInput
2233
+ }));
2234
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
2235
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
2236
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
2237
+ const result = await datasetsCollection.findOneAndUpdate(
2238
+ { id: input.datasetId },
2239
+ { $inc: { version: 1 } },
2240
+ { returnDocument: "after" }
2241
+ );
2242
+ if (!result) {
2243
+ throw new MastraError({
2244
+ id: createStorageErrorId("MONGODB", "BULK_ADD_ITEMS", "DATASET_NOT_FOUND"),
2245
+ domain: ErrorDomain.STORAGE,
2246
+ category: ErrorCategory.USER,
2247
+ details: { datasetId: input.datasetId }
2248
+ });
2249
+ }
2250
+ const newVersion = result.version;
2251
+ if (itemsWithIds.length > 0) {
2252
+ const docs = itemsWithIds.map(({ generatedId, itemInput }) => ({
2253
+ id: generatedId,
2254
+ datasetId: input.datasetId,
2255
+ datasetVersion: newVersion,
2256
+ validTo: null,
2257
+ isDeleted: false,
2258
+ input: itemInput.input,
2259
+ groundTruth: itemInput.groundTruth ?? null,
2260
+ requestContext: itemInput.requestContext ?? null,
2261
+ metadata: itemInput.metadata ?? null,
2262
+ source: itemInput.source ?? null,
2263
+ createdAt: now,
2264
+ updatedAt: now
2265
+ }));
2266
+ await itemsCollection.insertMany(docs);
2267
+ }
2268
+ await versionsCollection.insertOne({
2269
+ id: versionId,
2270
+ datasetId: input.datasetId,
2271
+ version: newVersion,
2272
+ createdAt: now
2273
+ });
2274
+ return itemsWithIds.map(({ generatedId, itemInput }) => ({
2275
+ id: generatedId,
2276
+ datasetId: input.datasetId,
2277
+ datasetVersion: newVersion,
2278
+ input: itemInput.input,
2279
+ groundTruth: itemInput.groundTruth,
2280
+ requestContext: itemInput.requestContext,
2281
+ metadata: itemInput.metadata,
2282
+ source: itemInput.source,
2283
+ createdAt: now,
2284
+ updatedAt: now
2285
+ }));
2286
+ } catch (error) {
2287
+ if (error instanceof MastraError) throw error;
2288
+ throw new MastraError(
2289
+ {
2290
+ id: createStorageErrorId("MONGODB", "BULK_ADD_ITEMS", "FAILED"),
2291
+ domain: ErrorDomain.STORAGE,
2292
+ category: ErrorCategory.THIRD_PARTY
2293
+ },
2294
+ error
2295
+ );
2296
+ }
2297
+ }
2298
+ async _doBatchDeleteItems(input) {
2299
+ try {
2300
+ const dataset = await this.getDatasetById({ id: input.datasetId });
2301
+ if (!dataset) {
2302
+ throw new MastraError({
2303
+ id: createStorageErrorId("MONGODB", "BULK_DELETE_ITEMS", "DATASET_NOT_FOUND"),
2304
+ domain: ErrorDomain.STORAGE,
2305
+ category: ErrorCategory.USER,
2306
+ details: { datasetId: input.datasetId }
2307
+ });
2308
+ }
2309
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
2310
+ const currentRows = await itemsCollection.find({
2311
+ id: { $in: input.itemIds },
2312
+ datasetId: input.datasetId,
2313
+ validTo: null,
2314
+ isDeleted: false
2315
+ }).toArray();
2316
+ const currentItems = currentRows.map((row) => this.transformItemRow(row));
2317
+ if (currentItems.length === 0) return;
2318
+ const now = /* @__PURE__ */ new Date();
2319
+ const versionId = randomUUID();
2320
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
2321
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
2322
+ const result = await datasetsCollection.findOneAndUpdate(
2323
+ { id: input.datasetId },
2324
+ { $inc: { version: 1 } },
2325
+ { returnDocument: "after" }
2326
+ );
2327
+ if (!result) {
2328
+ throw new MastraError({
2329
+ id: createStorageErrorId("MONGODB", "BULK_DELETE_ITEMS", "DATASET_NOT_FOUND"),
2330
+ domain: ErrorDomain.STORAGE,
2331
+ category: ErrorCategory.USER,
2332
+ details: { datasetId: input.datasetId }
2333
+ });
2334
+ }
2335
+ const newVersion = result.version;
2336
+ const currentIds = currentItems.map((i) => i.id);
2337
+ await itemsCollection.updateMany(
2338
+ { id: { $in: currentIds }, validTo: null, isDeleted: false },
2339
+ { $set: { validTo: newVersion } }
2340
+ );
2341
+ const tombstones = currentItems.map((item) => ({
2342
+ id: item.id,
2343
+ datasetId: input.datasetId,
2344
+ datasetVersion: newVersion,
2345
+ validTo: null,
2346
+ isDeleted: true,
2347
+ input: item.input,
2348
+ groundTruth: item.groundTruth,
2349
+ requestContext: item.requestContext,
2350
+ metadata: item.metadata,
2351
+ source: item.source,
2352
+ createdAt: item.createdAt,
2353
+ updatedAt: now
2354
+ }));
2355
+ await itemsCollection.insertMany(tombstones);
2356
+ await versionsCollection.insertOne({
2357
+ id: versionId,
2358
+ datasetId: input.datasetId,
2359
+ version: newVersion,
2360
+ createdAt: now
2361
+ });
2362
+ } catch (error) {
2363
+ if (error instanceof MastraError) throw error;
2364
+ throw new MastraError(
2365
+ {
2366
+ id: createStorageErrorId("MONGODB", "BULK_DELETE_ITEMS", "FAILED"),
2367
+ domain: ErrorDomain.STORAGE,
2368
+ category: ErrorCategory.THIRD_PARTY
2369
+ },
2370
+ error
2371
+ );
2372
+ }
2373
+ }
2374
+ // --- SCD-2 queries ---
2375
+ async getItemById(args) {
2376
+ try {
2377
+ const collection = await this.getCollection(TABLE_DATASET_ITEMS);
2378
+ let row;
2379
+ if (args.datasetVersion !== void 0) {
2380
+ row = await collection.findOne(
2381
+ {
2382
+ id: args.id,
2383
+ datasetVersion: { $lte: args.datasetVersion },
2384
+ $or: [{ validTo: null }, { validTo: { $gt: args.datasetVersion } }],
2385
+ isDeleted: false
2386
+ },
2387
+ { sort: { datasetVersion: -1 } }
2388
+ );
2389
+ } else {
2390
+ row = await collection.findOne({
2391
+ id: args.id,
2392
+ validTo: null,
2393
+ isDeleted: false
2394
+ });
2395
+ }
2396
+ return row ? this.transformItemRow(row) : null;
2397
+ } catch (error) {
2398
+ throw new MastraError(
2399
+ {
2400
+ id: createStorageErrorId("MONGODB", "GET_ITEM", "FAILED"),
2401
+ domain: ErrorDomain.STORAGE,
2402
+ category: ErrorCategory.THIRD_PARTY
2403
+ },
2404
+ error
2405
+ );
2406
+ }
2407
+ }
2408
+ async getItemsByVersion({ datasetId, version }) {
2409
+ try {
2410
+ const collection = await this.getCollection(TABLE_DATASET_ITEMS);
2411
+ const rows = await collection.find({
2412
+ datasetId,
2413
+ datasetVersion: { $lte: version },
2414
+ $or: [{ validTo: null }, { validTo: { $gt: version } }],
2415
+ isDeleted: false
2416
+ }).sort({ createdAt: -1, id: 1 }).toArray();
2417
+ return rows.map((row) => this.transformItemRow(row));
2418
+ } catch (error) {
2419
+ throw new MastraError(
2420
+ {
2421
+ id: createStorageErrorId("MONGODB", "GET_ITEMS_BY_VERSION", "FAILED"),
2422
+ domain: ErrorDomain.STORAGE,
2423
+ category: ErrorCategory.THIRD_PARTY
2424
+ },
2425
+ error
2426
+ );
2427
+ }
2428
+ }
2429
+ async getItemHistory(itemId) {
2430
+ try {
2431
+ const collection = await this.getCollection(TABLE_DATASET_ITEMS);
2432
+ const rows = await collection.find({ id: itemId }).sort({ datasetVersion: -1 }).toArray();
2433
+ return rows.map((row) => this.transformItemRowFull(row));
2434
+ } catch (error) {
2435
+ throw new MastraError(
2436
+ {
2437
+ id: createStorageErrorId("MONGODB", "GET_ITEM_HISTORY", "FAILED"),
2438
+ domain: ErrorDomain.STORAGE,
2439
+ category: ErrorCategory.THIRD_PARTY
2440
+ },
2441
+ error
2442
+ );
2443
+ }
2444
+ }
2445
+ async listItems(args) {
2446
+ try {
2447
+ const { page, perPage: perPageInput } = args.pagination;
2448
+ const collection = await this.getCollection(TABLE_DATASET_ITEMS);
2449
+ const filter = { datasetId: args.datasetId };
2450
+ if (args.version !== void 0) {
2451
+ filter.datasetVersion = { $lte: args.version };
2452
+ filter.$or = [{ validTo: null }, { validTo: { $gt: args.version } }];
2453
+ filter.isDeleted = false;
2454
+ } else {
2455
+ filter.validTo = null;
2456
+ filter.isDeleted = false;
2457
+ }
2458
+ if (args.search) {
2459
+ const escaped = args.search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2460
+ const regex = new RegExp(escaped, "i");
2461
+ const safeStr = (field) => ({
2462
+ $convert: { input: field, to: "string", onError: "", onNull: "" }
2463
+ });
2464
+ const searchCondition = [{ $expr: { $regexMatch: { input: safeStr("$input"), regex } } }];
2465
+ if (filter.$or) {
2466
+ filter.$and = [{ $or: filter.$or }, { $or: searchCondition }];
2467
+ delete filter.$or;
2468
+ } else {
2469
+ filter.$or = searchCondition;
2470
+ }
2471
+ }
2472
+ const total = await collection.countDocuments(filter);
2473
+ if (total === 0) {
2474
+ return { items: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
2475
+ }
2476
+ const perPage = normalizePerPage(perPageInput, 100);
2477
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2478
+ if (perPage === 0) {
2479
+ return { items: [], pagination: { total, page, perPage: perPageForResponse, hasMore: total > 0 } };
2480
+ }
2481
+ const limitValue = perPageInput === false ? total : perPage;
2482
+ const rows = await collection.find(filter).sort({ createdAt: -1, id: 1 }).skip(offset).limit(limitValue).toArray();
2483
+ return {
2484
+ items: rows.map((row) => this.transformItemRow(row)),
2485
+ pagination: {
2486
+ total,
2487
+ page,
2488
+ perPage: perPageForResponse,
2489
+ hasMore: perPageInput === false ? false : offset + perPage < total
2490
+ }
2491
+ };
2492
+ } catch (error) {
2493
+ throw new MastraError(
2494
+ {
2495
+ id: createStorageErrorId("MONGODB", "LIST_ITEMS", "FAILED"),
2496
+ domain: ErrorDomain.STORAGE,
2497
+ category: ErrorCategory.THIRD_PARTY
2498
+ },
2499
+ error
2500
+ );
2501
+ }
2502
+ }
2503
+ // --- Dataset versions ---
2504
+ async createDatasetVersion(datasetId, version) {
2505
+ try {
2506
+ const id = randomUUID();
2507
+ const now = /* @__PURE__ */ new Date();
2508
+ const collection = await this.getCollection(TABLE_DATASET_VERSIONS);
2509
+ await collection.insertOne({ id, datasetId, version, createdAt: now });
2510
+ return { id, datasetId, version, createdAt: now };
2511
+ } catch (error) {
2512
+ throw new MastraError(
2513
+ {
2514
+ id: createStorageErrorId("MONGODB", "CREATE_DATASET_VERSION", "FAILED"),
2515
+ domain: ErrorDomain.STORAGE,
2516
+ category: ErrorCategory.THIRD_PARTY
2517
+ },
2518
+ error
2519
+ );
2520
+ }
2521
+ }
2522
+ async listDatasetVersions(input) {
2523
+ try {
2524
+ const { page, perPage: perPageInput } = input.pagination;
2525
+ const collection = await this.getCollection(TABLE_DATASET_VERSIONS);
2526
+ const filter = { datasetId: input.datasetId };
2527
+ const total = await collection.countDocuments(filter);
2528
+ if (total === 0) {
2529
+ return { versions: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
2530
+ }
2531
+ const perPage = normalizePerPage(perPageInput, 100);
2532
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2533
+ if (perPage === 0) {
2534
+ return { versions: [], pagination: { total, page, perPage: perPageForResponse, hasMore: total > 0 } };
2535
+ }
2536
+ const limitValue = perPageInput === false ? total : perPage;
2537
+ const rows = await collection.find(filter).sort({ version: -1 }).skip(offset).limit(limitValue).toArray();
2538
+ return {
2539
+ versions: rows.map((row) => this.transformDatasetVersionRow(row)),
2540
+ pagination: {
2541
+ total,
2542
+ page,
2543
+ perPage: perPageForResponse,
2544
+ hasMore: perPageInput === false ? false : offset + perPage < total
2545
+ }
2546
+ };
2547
+ } catch (error) {
2548
+ throw new MastraError(
2549
+ {
2550
+ id: createStorageErrorId("MONGODB", "LIST_DATASET_VERSIONS", "FAILED"),
2551
+ domain: ErrorDomain.STORAGE,
2552
+ category: ErrorCategory.THIRD_PARTY
2553
+ },
2554
+ error
2555
+ );
2556
+ }
2557
+ }
2558
+ // --- Clear all ---
2559
+ async dangerouslyClearAll() {
2560
+ const datasetsCollection = await this.getCollection(TABLE_DATASETS);
2561
+ const itemsCollection = await this.getCollection(TABLE_DATASET_ITEMS);
2562
+ const versionsCollection = await this.getCollection(TABLE_DATASET_VERSIONS);
2563
+ const results = await Promise.allSettled([
2564
+ datasetsCollection.deleteMany({}),
2565
+ itemsCollection.deleteMany({}),
2566
+ versionsCollection.deleteMany({})
2567
+ ]);
2568
+ const failures = results.filter((r) => r.status === "rejected");
2569
+ if (failures.length > 0) {
2570
+ throw new MastraError(
2571
+ {
2572
+ id: createStorageErrorId("MONGODB", "CLEAR_ALL", "FAILED"),
2573
+ domain: ErrorDomain.STORAGE,
2574
+ category: ErrorCategory.THIRD_PARTY,
2575
+ details: { failedCollections: failures.length }
2576
+ },
2577
+ failures[0].reason
2578
+ );
2579
+ }
2580
+ }
2581
+ };
2582
+ function toDate(value) {
2583
+ if (value instanceof Date) return value;
2584
+ if (typeof value === "string" || typeof value === "number") return new Date(value);
2585
+ return /* @__PURE__ */ new Date();
2586
+ }
2587
+ function toDateOrNull(value) {
2588
+ if (value === null || value === void 0) return null;
2589
+ return toDate(value);
2590
+ }
2591
+ function parseJsonField(value) {
2592
+ if (value === null || value === void 0) return void 0;
2593
+ if (typeof value === "string") return safelyParseJSON(value);
2594
+ return value;
2595
+ }
2596
+ function transformExperimentRow(row) {
2597
+ return {
2598
+ id: row.id,
2599
+ name: row.name ?? void 0,
2600
+ description: row.description ?? void 0,
2601
+ metadata: parseJsonField(row.metadata) ?? void 0,
2602
+ datasetId: row.datasetId ?? null,
2603
+ datasetVersion: row.datasetVersion != null ? Number(row.datasetVersion) : null,
2604
+ targetType: row.targetType,
2605
+ targetId: row.targetId,
2606
+ status: row.status,
2607
+ totalItems: Number(row.totalItems ?? 0),
2608
+ succeededCount: Number(row.succeededCount ?? 0),
2609
+ failedCount: Number(row.failedCount ?? 0),
2610
+ skippedCount: Number(row.skippedCount ?? 0),
2611
+ agentVersion: row.agentVersion ?? null,
2612
+ startedAt: toDateOrNull(row.startedAt),
2613
+ completedAt: toDateOrNull(row.completedAt),
2614
+ createdAt: toDate(row.createdAt),
2615
+ updatedAt: toDate(row.updatedAt)
2616
+ };
2617
+ }
2618
+ function transformExperimentResultRow(row) {
2619
+ return {
2620
+ id: row.id,
2621
+ experimentId: row.experimentId,
2622
+ itemId: row.itemId,
2623
+ itemDatasetVersion: row.itemDatasetVersion != null ? Number(row.itemDatasetVersion) : null,
2624
+ input: parseJsonField(row.input),
2625
+ output: parseJsonField(row.output) ?? null,
2626
+ groundTruth: parseJsonField(row.groundTruth) ?? null,
2627
+ error: parseJsonField(row.error) ?? null,
2628
+ startedAt: toDate(row.startedAt),
2629
+ completedAt: toDate(row.completedAt),
2630
+ retryCount: Number(row.retryCount ?? 0),
2631
+ traceId: row.traceId ?? null,
2632
+ status: row.status ?? null,
2633
+ tags: Array.isArray(row.tags) ? row.tags : parseJsonField(row.tags) ?? null,
2634
+ createdAt: toDate(row.createdAt)
2635
+ };
2636
+ }
2637
+ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends ExperimentsStorage {
2638
+ #connector;
2639
+ #skipDefaultIndexes;
2640
+ #indexes;
2641
+ static MANAGED_COLLECTIONS = [TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS];
2642
+ constructor(config) {
2643
+ super();
2644
+ this.#connector = resolveMongoDBConfig(config);
2645
+ this.#skipDefaultIndexes = config.skipDefaultIndexes;
2646
+ this.#indexes = config.indexes?.filter(
2647
+ (idx) => _MongoDBExperimentsStorage.MANAGED_COLLECTIONS.includes(idx.collection)
2648
+ );
2649
+ }
2650
+ async getCollection(name) {
2651
+ return this.#connector.getCollection(name);
2652
+ }
2653
+ // -------------------------------------------------------------------------
2654
+ // Index Management
2655
+ // -------------------------------------------------------------------------
2656
+ getDefaultIndexDefinitions() {
2657
+ return [
2658
+ { collection: TABLE_EXPERIMENTS, keys: { id: 1 }, options: { unique: true } },
2659
+ { collection: TABLE_EXPERIMENTS, keys: { datasetId: 1 } },
2660
+ { collection: TABLE_EXPERIMENTS, keys: { createdAt: -1, id: 1 } },
2661
+ { collection: TABLE_EXPERIMENT_RESULTS, keys: { id: 1 }, options: { unique: true } },
2662
+ { collection: TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1 } },
2663
+ { collection: TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1, itemId: 1 }, options: { unique: true } },
2664
+ { collection: TABLE_EXPERIMENT_RESULTS, keys: { createdAt: -1 } },
2665
+ { collection: TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1, startedAt: 1, id: 1 } }
2666
+ ];
2667
+ }
2668
+ async createDefaultIndexes() {
2669
+ if (this.#skipDefaultIndexes) return;
2670
+ for (const indexDef of this.getDefaultIndexDefinitions()) {
2671
+ try {
2672
+ const collection = await this.getCollection(indexDef.collection);
2673
+ await collection.createIndex(indexDef.keys, indexDef.options);
2674
+ } catch (error) {
2675
+ this.logger?.warn?.(`Failed to create index on ${indexDef.collection}:`, error);
2676
+ }
2677
+ }
2678
+ }
2679
+ async createCustomIndexes() {
2680
+ if (!this.#indexes || this.#indexes.length === 0) return;
2681
+ for (const indexDef of this.#indexes) {
2682
+ try {
2683
+ const collection = await this.getCollection(indexDef.collection);
2684
+ await collection.createIndex(indexDef.keys, indexDef.options);
2685
+ } catch (error) {
2686
+ this.logger?.warn?.(`Failed to create custom index on ${indexDef.collection}:`, error);
2687
+ }
2688
+ }
2689
+ }
2690
+ async init() {
2691
+ await this.createDefaultIndexes();
2692
+ await this.createCustomIndexes();
2693
+ }
2694
+ // -------------------------------------------------------------------------
2695
+ // Experiment CRUD
2696
+ // -------------------------------------------------------------------------
2697
+ async createExperiment(input) {
2698
+ const id = input.id ?? randomUUID();
2699
+ const now = /* @__PURE__ */ new Date();
2700
+ const doc = {
2701
+ id,
2702
+ name: input.name ?? null,
2703
+ description: input.description ?? null,
2704
+ metadata: input.metadata ?? null,
2705
+ datasetId: input.datasetId ?? null,
2706
+ datasetVersion: input.datasetVersion ?? null,
2707
+ targetType: input.targetType,
2708
+ targetId: input.targetId,
2709
+ status: "pending",
2710
+ totalItems: input.totalItems,
2711
+ succeededCount: 0,
2712
+ failedCount: 0,
2713
+ skippedCount: 0,
2714
+ agentVersion: null,
2715
+ startedAt: null,
2716
+ completedAt: null,
2717
+ createdAt: now,
2718
+ updatedAt: now
2719
+ };
2720
+ try {
2721
+ const collection = await this.getCollection(TABLE_EXPERIMENTS);
2722
+ await collection.insertOne(doc);
2723
+ return {
2724
+ id,
2725
+ name: input.name,
2726
+ description: input.description,
2727
+ metadata: input.metadata,
2728
+ datasetId: input.datasetId ?? null,
2729
+ datasetVersion: input.datasetVersion ?? null,
2730
+ targetType: input.targetType,
2731
+ targetId: input.targetId,
2732
+ status: "pending",
2733
+ totalItems: input.totalItems,
2734
+ succeededCount: 0,
2735
+ failedCount: 0,
2736
+ skippedCount: 0,
2737
+ agentVersion: null,
2738
+ startedAt: null,
2739
+ completedAt: null,
2740
+ createdAt: now,
2741
+ updatedAt: now
2742
+ };
2743
+ } catch (error) {
2744
+ throw new MastraError(
2745
+ {
2746
+ id: createStorageErrorId("MONGODB", "CREATE_EXPERIMENT", "FAILED"),
2747
+ domain: ErrorDomain.STORAGE,
2748
+ category: ErrorCategory.THIRD_PARTY,
2749
+ details: { name: input.name ?? "unnamed" }
2750
+ },
2751
+ error
2752
+ );
2753
+ }
2754
+ }
2755
+ async updateExperiment(input) {
2756
+ const updateFields = { updatedAt: /* @__PURE__ */ new Date() };
2757
+ if (input.name !== void 0) updateFields.name = input.name;
2758
+ if (input.description !== void 0) updateFields.description = input.description;
2759
+ if (input.metadata !== void 0) updateFields.metadata = input.metadata;
2760
+ if (input.status !== void 0) updateFields.status = input.status;
2761
+ if (input.totalItems !== void 0) updateFields.totalItems = input.totalItems;
2762
+ if (input.succeededCount !== void 0) updateFields.succeededCount = input.succeededCount;
2763
+ if (input.failedCount !== void 0) updateFields.failedCount = input.failedCount;
2764
+ if (input.skippedCount !== void 0) updateFields.skippedCount = input.skippedCount;
2765
+ if (input.startedAt !== void 0) updateFields.startedAt = input.startedAt;
2766
+ if (input.completedAt !== void 0) updateFields.completedAt = input.completedAt;
2767
+ try {
2768
+ const collection = await this.getCollection(TABLE_EXPERIMENTS);
2769
+ const result = await collection.updateOne({ id: input.id }, { $set: updateFields });
2770
+ if (result.matchedCount === 0) {
2771
+ throw new MastraError({
2772
+ id: createStorageErrorId("MONGODB", "UPDATE_EXPERIMENT", "NOT_FOUND"),
2773
+ domain: ErrorDomain.STORAGE,
2774
+ category: ErrorCategory.USER,
2775
+ details: { experimentId: input.id }
2776
+ });
2777
+ }
2778
+ const updated = await this.getExperimentById({ id: input.id });
2779
+ return updated;
2780
+ } catch (error) {
2781
+ if (error instanceof MastraError) throw error;
2782
+ throw new MastraError(
2783
+ {
2784
+ id: createStorageErrorId("MONGODB", "UPDATE_EXPERIMENT", "FAILED"),
2785
+ domain: ErrorDomain.STORAGE,
2786
+ category: ErrorCategory.THIRD_PARTY,
2787
+ details: { experimentId: input.id }
2788
+ },
2789
+ error
2790
+ );
2791
+ }
2792
+ }
2793
+ async getExperimentById({ id }) {
2794
+ try {
2795
+ const collection = await this.getCollection(TABLE_EXPERIMENTS);
2796
+ const doc = await collection.findOne({ id });
2797
+ if (!doc) return null;
2798
+ return transformExperimentRow(doc);
2799
+ } catch (error) {
2800
+ throw new MastraError(
2801
+ {
2802
+ id: createStorageErrorId("MONGODB", "GET_EXPERIMENT", "FAILED"),
2803
+ domain: ErrorDomain.STORAGE,
2804
+ category: ErrorCategory.THIRD_PARTY,
2805
+ details: { id }
2806
+ },
2807
+ error
2808
+ );
2809
+ }
2810
+ }
2811
+ async listExperiments(args) {
2812
+ try {
2813
+ const collection = await this.getCollection(TABLE_EXPERIMENTS);
2814
+ const { page, perPage: perPageInput } = args.pagination;
2815
+ const filter = {};
2816
+ if (args.datasetId) {
2817
+ filter.datasetId = args.datasetId;
2818
+ }
2819
+ const total = await collection.countDocuments(filter);
2820
+ if (total === 0) {
2821
+ return { experiments: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
2822
+ }
2823
+ const normalizedPerPage = normalizePerPage(perPageInput, 100);
2824
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, normalizedPerPage);
2825
+ if (normalizedPerPage === 0) {
2826
+ return { experiments: [], pagination: { total, page, perPage: perPageForResponse, hasMore: total > 0 } };
2827
+ }
2828
+ const limitValue = perPageInput === false ? total : normalizedPerPage;
2829
+ const docs = await collection.find(filter).sort({ createdAt: -1, id: 1 }).skip(offset).limit(limitValue).toArray();
2830
+ return {
2831
+ experiments: docs.map((d) => transformExperimentRow(d)),
2832
+ pagination: {
2833
+ total,
2834
+ page,
2835
+ perPage: perPageForResponse,
2836
+ hasMore: perPageInput === false ? false : offset + normalizedPerPage < total
2837
+ }
2838
+ };
2839
+ } catch (error) {
2840
+ throw new MastraError(
2841
+ {
2842
+ id: createStorageErrorId("MONGODB", "LIST_EXPERIMENTS", "FAILED"),
2843
+ domain: ErrorDomain.STORAGE,
2844
+ category: ErrorCategory.THIRD_PARTY
2845
+ },
2846
+ error
2847
+ );
2848
+ }
2849
+ }
2850
+ async deleteExperiment({ id }) {
2851
+ try {
2852
+ const resultsCollection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
2853
+ await resultsCollection.deleteMany({ experimentId: id });
2854
+ const experimentsCollection = await this.getCollection(TABLE_EXPERIMENTS);
2855
+ await experimentsCollection.deleteOne({ id });
2856
+ } catch (error) {
2857
+ throw new MastraError(
2858
+ {
2859
+ id: createStorageErrorId("MONGODB", "DELETE_EXPERIMENT", "FAILED"),
2860
+ domain: ErrorDomain.STORAGE,
2861
+ category: ErrorCategory.THIRD_PARTY,
2862
+ details: { id }
2863
+ },
2864
+ error
2865
+ );
2866
+ }
2867
+ }
2868
+ // -------------------------------------------------------------------------
2869
+ // Experiment Results
2870
+ // -------------------------------------------------------------------------
2871
+ async addExperimentResult(input) {
2872
+ const id = input.id ?? randomUUID();
2873
+ const now = /* @__PURE__ */ new Date();
2874
+ const doc = {
2875
+ id,
2876
+ experimentId: input.experimentId,
2877
+ itemId: input.itemId,
2878
+ itemDatasetVersion: input.itemDatasetVersion ?? null,
2879
+ input: input.input,
2880
+ output: input.output ?? null,
2881
+ groundTruth: input.groundTruth ?? null,
2882
+ error: input.error ?? null,
2883
+ startedAt: input.startedAt,
2884
+ completedAt: input.completedAt,
2885
+ retryCount: input.retryCount,
2886
+ traceId: input.traceId ?? null,
2887
+ status: input.status ?? null,
2888
+ tags: input.tags ?? null,
2889
+ createdAt: now
2890
+ };
2891
+ try {
2892
+ const collection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
2893
+ await collection.insertOne(doc);
2894
+ return {
2895
+ id,
2896
+ experimentId: input.experimentId,
2897
+ itemId: input.itemId,
2898
+ itemDatasetVersion: input.itemDatasetVersion ?? null,
2899
+ input: input.input,
2900
+ output: input.output ?? null,
2901
+ groundTruth: input.groundTruth ?? null,
2902
+ error: input.error ?? null,
2903
+ startedAt: input.startedAt,
2904
+ completedAt: input.completedAt,
2905
+ retryCount: input.retryCount,
2906
+ traceId: input.traceId ?? null,
2907
+ status: input.status ?? null,
2908
+ tags: input.tags ?? null,
2909
+ createdAt: now
2910
+ };
2911
+ } catch (error) {
2912
+ throw new MastraError(
2913
+ {
2914
+ id: createStorageErrorId("MONGODB", "ADD_EXPERIMENT_RESULT", "FAILED"),
2915
+ domain: ErrorDomain.STORAGE,
2916
+ category: ErrorCategory.THIRD_PARTY,
2917
+ details: { experimentId: input.experimentId }
2918
+ },
2919
+ error
2920
+ );
2921
+ }
2922
+ }
2923
+ async updateExperimentResult(input) {
2924
+ const updateFields = {};
2925
+ if (input.status !== void 0) updateFields.status = input.status;
2926
+ if (input.tags !== void 0) updateFields.tags = input.tags;
2927
+ if (Object.keys(updateFields).length === 0) {
2928
+ const existing = await this.getExperimentResultById({ id: input.id });
2929
+ if (!existing || input.experimentId && existing.experimentId !== input.experimentId) {
2930
+ throw new MastraError({
2931
+ id: createStorageErrorId("MONGODB", "UPDATE_EXPERIMENT_RESULT", "NOT_FOUND"),
2932
+ domain: ErrorDomain.STORAGE,
2933
+ category: ErrorCategory.USER,
2934
+ details: { resultId: input.id }
2935
+ });
2936
+ }
2937
+ return existing;
2938
+ }
2939
+ try {
2940
+ const collection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
2941
+ const filter = { id: input.id };
2942
+ if (input.experimentId) {
2943
+ filter.experimentId = input.experimentId;
2944
+ }
2945
+ const result = await collection.findOneAndUpdate(filter, { $set: updateFields }, { returnDocument: "after" });
2946
+ if (!result) {
2947
+ throw new MastraError({
2948
+ id: createStorageErrorId("MONGODB", "UPDATE_EXPERIMENT_RESULT", "NOT_FOUND"),
2949
+ domain: ErrorDomain.STORAGE,
2950
+ category: ErrorCategory.USER,
2951
+ details: { resultId: input.id }
2952
+ });
2953
+ }
2954
+ return transformExperimentResultRow(result);
2955
+ } catch (error) {
2956
+ if (error instanceof MastraError) throw error;
2957
+ throw new MastraError(
2958
+ {
2959
+ id: createStorageErrorId("MONGODB", "UPDATE_EXPERIMENT_RESULT", "FAILED"),
2960
+ domain: ErrorDomain.STORAGE,
2961
+ category: ErrorCategory.THIRD_PARTY,
2962
+ details: { resultId: input.id }
2963
+ },
2964
+ error
2965
+ );
2966
+ }
2967
+ }
2968
+ async getExperimentResultById({ id }) {
2969
+ try {
2970
+ const collection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
2971
+ const doc = await collection.findOne({ id });
2972
+ if (!doc) return null;
2973
+ return transformExperimentResultRow(doc);
2974
+ } catch (error) {
2975
+ throw new MastraError(
2976
+ {
2977
+ id: createStorageErrorId("MONGODB", "GET_EXPERIMENT_RESULT", "FAILED"),
2978
+ domain: ErrorDomain.STORAGE,
2979
+ category: ErrorCategory.THIRD_PARTY,
2980
+ details: { id }
2981
+ },
2982
+ error
2983
+ );
2984
+ }
2985
+ }
2986
+ async listExperimentResults(args) {
2987
+ try {
2988
+ const collection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
2989
+ const { page, perPage: perPageInput } = args.pagination;
2990
+ const filter = { experimentId: args.experimentId };
2991
+ const total = await collection.countDocuments(filter);
2992
+ if (total === 0) {
2993
+ return { results: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
2994
+ }
2995
+ const normalizedPerPage = normalizePerPage(perPageInput, 100);
2996
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, normalizedPerPage);
2997
+ if (normalizedPerPage === 0) {
2998
+ return { results: [], pagination: { total, page, perPage: perPageForResponse, hasMore: total > 0 } };
2999
+ }
3000
+ const limitValue = perPageInput === false ? total : normalizedPerPage;
3001
+ const docs = await collection.find(filter).sort({ startedAt: 1, id: 1 }).skip(offset).limit(limitValue).toArray();
3002
+ return {
3003
+ results: docs.map((d) => transformExperimentResultRow(d)),
3004
+ pagination: {
3005
+ total,
3006
+ page,
3007
+ perPage: perPageForResponse,
3008
+ hasMore: perPageInput === false ? false : offset + normalizedPerPage < total
3009
+ }
3010
+ };
3011
+ } catch (error) {
3012
+ throw new MastraError(
3013
+ {
3014
+ id: createStorageErrorId("MONGODB", "LIST_EXPERIMENT_RESULTS", "FAILED"),
3015
+ domain: ErrorDomain.STORAGE,
3016
+ category: ErrorCategory.THIRD_PARTY,
3017
+ details: { experimentId: args.experimentId }
3018
+ },
3019
+ error
3020
+ );
3021
+ }
3022
+ }
3023
+ async deleteExperimentResults({ experimentId }) {
3024
+ try {
3025
+ const collection = await this.getCollection(TABLE_EXPERIMENT_RESULTS);
3026
+ await collection.deleteMany({ experimentId });
3027
+ } catch (error) {
3028
+ throw new MastraError(
3029
+ {
3030
+ id: createStorageErrorId("MONGODB", "DELETE_EXPERIMENT_RESULTS", "FAILED"),
3031
+ domain: ErrorDomain.STORAGE,
3032
+ category: ErrorCategory.THIRD_PARTY,
3033
+ details: { experimentId }
3034
+ },
3035
+ error
3036
+ );
3037
+ }
3038
+ }
3039
+ // -------------------------------------------------------------------------
3040
+ // Cleanup
3041
+ // -------------------------------------------------------------------------
3042
+ async dangerouslyClearAll() {
3043
+ for (const collectionName of _MongoDBExperimentsStorage.MANAGED_COLLECTIONS) {
3044
+ try {
3045
+ const collection = await this.getCollection(collectionName);
3046
+ await collection.deleteMany({});
3047
+ } catch {
3048
+ }
3049
+ }
3050
+ }
3051
+ };
1701
3052
  var SNAPSHOT_FIELDS2 = ["name", "description", "servers"];
1702
3053
  var MongoDBMCPClientsStorage = class _MongoDBMCPClientsStorage extends MCPClientsStorage {
1703
3054
  #connector;
@@ -8407,6 +9758,8 @@ var MongoDBStore = class extends MastraCompositeStore {
8407
9758
  const workspaces = new MongoDBWorkspacesStorage(domainConfig);
8408
9759
  const skills = new MongoDBSkillsStorage(domainConfig);
8409
9760
  const blobs = new MongoDBBlobStore(domainConfig);
9761
+ const datasets = new MongoDBDatasetsStorage(domainConfig);
9762
+ const experiments = new MongoDBExperimentsStorage(domainConfig);
8410
9763
  this.stores = {
8411
9764
  memory,
8412
9765
  scores,
@@ -8419,7 +9772,9 @@ var MongoDBStore = class extends MastraCompositeStore {
8419
9772
  mcpServers,
8420
9773
  workspaces,
8421
9774
  skills,
8422
- blobs
9775
+ blobs,
9776
+ datasets,
9777
+ experiments
8423
9778
  };
8424
9779
  }
8425
9780
  /**
@@ -8538,6 +9893,6 @@ Example Complex Query:
8538
9893
  ]
8539
9894
  }`;
8540
9895
 
8541
- export { MONGODB_PROMPT, MemoryStorageMongoDB, MongoDBAgentsStorage, MongoDBBlobStore, MongoDBMCPClientsStorage, MongoDBMCPServersStorage, MongoDBPromptBlocksStorage, MongoDBScorerDefinitionsStorage, MongoDBSkillsStorage, MongoDBStore, MongoDBVector, MongoDBWorkspacesStorage, ObservabilityMongoDB, ScoresStorageMongoDB, WorkflowsStorageMongoDB };
9896
+ export { MONGODB_PROMPT, MemoryStorageMongoDB, MongoDBAgentsStorage, MongoDBBlobStore, MongoDBDatasetsStorage, MongoDBExperimentsStorage, MongoDBMCPClientsStorage, MongoDBMCPServersStorage, MongoDBPromptBlocksStorage, MongoDBScorerDefinitionsStorage, MongoDBSkillsStorage, MongoDBStore, MongoDBVector, MongoDBWorkspacesStorage, ObservabilityMongoDB, ScoresStorageMongoDB, WorkflowsStorageMongoDB };
8542
9897
  //# sourceMappingURL=index.js.map
8543
9898
  //# sourceMappingURL=index.js.map