@mastra/pg 1.3.0 → 1.4.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 +128 -0
  2. package/dist/docs/SKILL.md +1 -1
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/index.cjs +2423 -180
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.js +2422 -182
  7. package/dist/index.js.map +1 -1
  8. package/dist/storage/db/index.d.ts +23 -4
  9. package/dist/storage/db/index.d.ts.map +1 -1
  10. package/dist/storage/domains/agents/index.d.ts +5 -0
  11. package/dist/storage/domains/agents/index.d.ts.map +1 -1
  12. package/dist/storage/domains/datasets/index.d.ts +48 -0
  13. package/dist/storage/domains/datasets/index.d.ts.map +1 -0
  14. package/dist/storage/domains/experiments/index.d.ts +34 -0
  15. package/dist/storage/domains/experiments/index.d.ts.map +1 -0
  16. package/dist/storage/domains/mcp-clients/index.d.ts +33 -0
  17. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  18. package/dist/storage/domains/memory/index.d.ts +10 -0
  19. package/dist/storage/domains/memory/index.d.ts.map +1 -1
  20. package/dist/storage/domains/observability/index.d.ts +10 -0
  21. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  22. package/dist/storage/domains/prompt-blocks/index.d.ts +10 -0
  23. package/dist/storage/domains/prompt-blocks/index.d.ts.map +1 -1
  24. package/dist/storage/domains/scorer-definitions/index.d.ts +10 -0
  25. package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -1
  26. package/dist/storage/domains/scores/index.d.ts +10 -0
  27. package/dist/storage/domains/scores/index.d.ts.map +1 -1
  28. package/dist/storage/domains/workflows/index.d.ts +5 -0
  29. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  30. package/dist/storage/index.d.ts +10 -2
  31. package/dist/storage/index.d.ts.map +1 -1
  32. package/dist/storage/test-utils.d.ts.map +1 -1
  33. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
2
- import { createVectorErrorId, TABLE_SCHEMAS, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, 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, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, MastraCompositeStore, TraceStatus, getDefaultValue, transformScoreRow as transformScoreRow$1, getSqlType } from '@mastra/core/storage';
2
+ import { createVectorErrorId, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_SCHEMAS, createStorageErrorId, normalizePerPage, calculatePagination, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, DATASETS_SCHEMA, TABLE_CONFIGS, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, ensureDate, safelyParseJSON, ExperimentsStorage, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_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, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, MastraCompositeStore, TraceStatus, getDefaultValue, transformScoreRow as transformScoreRow$1, getSqlType } from '@mastra/core/storage';
3
3
  import { parseSqlIdentifier, parseFieldKey } from '@mastra/core/utils';
4
4
  import { MastraVector, validateTopK, validateUpsertInput } from '@mastra/core/vector';
5
5
  import { Mutex } from 'async-mutex';
@@ -12,7 +12,12 @@ import { randomUUID } from 'crypto';
12
12
  import { MessageList } from '@mastra/core/agent';
13
13
  import { saveScorePayloadSchema } from '@mastra/core/evals';
14
14
 
15
- // src/vector/index.ts
15
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
16
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
17
+ }) : x)(function(x) {
18
+ if (typeof require !== "undefined") return require.apply(this, arguments);
19
+ throw Error('Dynamic require of "' + x + '" is not supported');
20
+ });
16
21
 
17
22
  // src/shared/config.ts
18
23
  var isPoolConfig = (cfg) => {
@@ -1972,8 +1977,17 @@ function generateTableSQL({
1972
1977
  tableName,
1973
1978
  schema,
1974
1979
  schemaName,
1980
+ compositePrimaryKey,
1975
1981
  includeAllConstraints = false
1976
1982
  }) {
1983
+ if (compositePrimaryKey) {
1984
+ for (const col of compositePrimaryKey) {
1985
+ if (!(col in schema)) {
1986
+ throw new Error(`compositePrimaryKey column "${col}" does not exist in schema for table "${tableName}"`);
1987
+ }
1988
+ }
1989
+ }
1990
+ const compositePKSet = compositePrimaryKey ? new Set(compositePrimaryKey) : null;
1977
1991
  const timeZColumns = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => {
1978
1992
  const parsedName = parseSqlIdentifier(name, "column name");
1979
1993
  return `"${parsedName}Z" TIMESTAMPTZ DEFAULT NOW()`;
@@ -1981,11 +1995,16 @@ function generateTableSQL({
1981
1995
  const columns = Object.entries(schema).map(([name, def]) => {
1982
1996
  const parsedName = parseSqlIdentifier(name, "column name");
1983
1997
  const constraints = [];
1984
- if (def.primaryKey) constraints.push("PRIMARY KEY");
1998
+ if (def.primaryKey && !compositePKSet?.has(name)) constraints.push("PRIMARY KEY");
1985
1999
  if (!def.nullable) constraints.push("NOT NULL");
1986
2000
  return `"${parsedName}" ${mapToSqlType(def.type)} ${constraints.join(" ")}`;
1987
2001
  });
1988
- const finalColumns = [...columns, ...timeZColumns].join(",\n");
2002
+ const tableConstraints = [];
2003
+ if (compositePrimaryKey) {
2004
+ const pkCols = compositePrimaryKey.map((c) => `"${parseSqlIdentifier(c, "column name")}"`).join(", ");
2005
+ tableConstraints.push(`PRIMARY KEY (${pkCols})`);
2006
+ }
2007
+ const finalColumns = [...columns, ...timeZColumns, ...tableConstraints].join(",\n");
1989
2008
  const parsedSchemaName = schemaName ? parseSqlIdentifier(schemaName, "schema name") : "";
1990
2009
  const workflowSnapshotConstraint = buildConstraintName({
1991
2010
  baseName: "mastra_workflow_snapshot_workflow_name_run_id_key",
@@ -2029,27 +2048,55 @@ function generateTableSQL({
2029
2048
  `;
2030
2049
  return sql;
2031
2050
  }
2032
- function exportSchemas(schemaName) {
2033
- const statements = [];
2034
- if (schemaName) {
2035
- const quotedSchemaName = getSchemaName(schemaName);
2036
- statements.push(`-- Create schema if it doesn't exist`);
2037
- statements.push(`CREATE SCHEMA IF NOT EXISTS ${quotedSchemaName};`);
2038
- statements.push("");
2039
- }
2040
- for (const [tableName, schema] of Object.entries(TABLE_SCHEMAS)) {
2041
- statements.push(`-- Table: ${tableName}`);
2042
- const sql = generateTableSQL({
2043
- tableName,
2044
- schema,
2045
- schemaName,
2046
- includeAllConstraints: true
2047
- // Include all constraints for exports/documentation
2048
- });
2049
- statements.push(sql.trim());
2050
- statements.push("");
2051
- }
2052
- return statements.join("\n");
2051
+ function generateIndexSQL(options, schemaName) {
2052
+ const { name, table, columns, unique = false, where, method = "btree" } = options;
2053
+ const quotedSchemaName = getSchemaName(schemaName);
2054
+ const fullTableName = getTableName({ indexName: table, schemaName: quotedSchemaName });
2055
+ const uniqueStr = unique ? "UNIQUE " : "";
2056
+ const methodStr = method !== "btree" ? `USING ${method} ` : "";
2057
+ const columnsStr = columns.map((col) => {
2058
+ if (col.includes(" DESC") || col.includes(" ASC")) {
2059
+ const [colName, ...modifiers] = col.split(" ");
2060
+ if (!colName) {
2061
+ throw new Error(`Invalid column specification: ${col}`);
2062
+ }
2063
+ return `"${parseSqlIdentifier(colName, "column name")}" ${modifiers.join(" ")}`;
2064
+ }
2065
+ return `"${parseSqlIdentifier(col, "column name")}"`;
2066
+ }).join(", ");
2067
+ const whereStr = where ? ` WHERE ${where}` : "";
2068
+ const quotedIndexName = `"${parseSqlIdentifier(name, "index name")}"`;
2069
+ return `CREATE ${uniqueStr}INDEX IF NOT EXISTS ${quotedIndexName} ON ${fullTableName} ${methodStr}(${columnsStr})${whereStr};`;
2070
+ }
2071
+ function generateTimestampTriggerSQL(tableName, schemaName) {
2072
+ const quotedSchemaName = getSchemaName(schemaName);
2073
+ const fullTableName = getTableName({ indexName: tableName, schemaName: quotedSchemaName });
2074
+ const functionName = `${quotedSchemaName}.trigger_set_timestamps`;
2075
+ const triggerName = `"${parseSqlIdentifier(`${tableName}_timestamps`, "trigger name")}"`;
2076
+ return `CREATE OR REPLACE FUNCTION ${functionName}()
2077
+ RETURNS TRIGGER AS $$
2078
+ BEGIN
2079
+ IF TG_OP = 'INSERT' THEN
2080
+ NEW."createdAt" = NOW();
2081
+ NEW."updatedAt" = NOW();
2082
+ NEW."createdAtZ" = NOW();
2083
+ NEW."updatedAtZ" = NOW();
2084
+ ELSIF TG_OP = 'UPDATE' THEN
2085
+ NEW."updatedAt" = NOW();
2086
+ NEW."updatedAtZ" = NOW();
2087
+ NEW."createdAt" = OLD."createdAt";
2088
+ NEW."createdAtZ" = OLD."createdAtZ";
2089
+ END IF;
2090
+ RETURN NEW;
2091
+ END;
2092
+ $$ LANGUAGE plpgsql;
2093
+
2094
+ DROP TRIGGER IF EXISTS ${triggerName} ON ${fullTableName};
2095
+
2096
+ CREATE TRIGGER ${triggerName}
2097
+ BEFORE INSERT OR UPDATE ON ${fullTableName}
2098
+ FOR EACH ROW
2099
+ EXECUTE FUNCTION ${functionName}();`;
2053
2100
  }
2054
2101
  var schemaSetupRegistry = /* @__PURE__ */ new Map();
2055
2102
  var PgDB = class extends MastraBase {
@@ -2250,14 +2297,15 @@ var PgDB = class extends MastraBase {
2250
2297
  }
2251
2298
  async createTable({
2252
2299
  tableName,
2253
- schema
2300
+ schema,
2301
+ compositePrimaryKey
2254
2302
  }) {
2255
2303
  try {
2256
2304
  const timeZColumnNames = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => name);
2257
2305
  if (this.schemaName) {
2258
2306
  await this.setupSchema();
2259
2307
  }
2260
- const sql = generateTableSQL({ tableName, schema, schemaName: this.schemaName });
2308
+ const sql = generateTableSQL({ tableName, schema, schemaName: this.schemaName, compositePrimaryKey });
2261
2309
  await this.client.none(sql);
2262
2310
  await this.alterTable({
2263
2311
  tableName,
@@ -2321,36 +2369,9 @@ Note: This migration may take some time for large tables.
2321
2369
  }
2322
2370
  }
2323
2371
  async setupTimestampTriggers(tableName) {
2324
- const schemaName = getSchemaName(this.schemaName);
2325
- const fullTableName = getTableName({ indexName: tableName, schemaName });
2326
- const functionName = `${schemaName}.trigger_set_timestamps`;
2327
- try {
2328
- const triggerSQL = `
2329
- CREATE OR REPLACE FUNCTION ${functionName}()
2330
- RETURNS TRIGGER AS $$
2331
- BEGIN
2332
- IF TG_OP = 'INSERT' THEN
2333
- NEW."createdAt" = NOW();
2334
- NEW."updatedAt" = NOW();
2335
- NEW."createdAtZ" = NOW();
2336
- NEW."updatedAtZ" = NOW();
2337
- ELSIF TG_OP = 'UPDATE' THEN
2338
- NEW."updatedAt" = NOW();
2339
- NEW."updatedAtZ" = NOW();
2340
- NEW."createdAt" = OLD."createdAt";
2341
- NEW."createdAtZ" = OLD."createdAtZ";
2342
- END IF;
2343
- RETURN NEW;
2344
- END;
2345
- $$ LANGUAGE plpgsql;
2346
-
2347
- DROP TRIGGER IF EXISTS ${tableName}_timestamps ON ${fullTableName};
2348
-
2349
- CREATE TRIGGER ${tableName}_timestamps
2350
- BEFORE INSERT OR UPDATE ON ${fullTableName}
2351
- FOR EACH ROW
2352
- EXECUTE FUNCTION ${functionName}();
2353
- `;
2372
+ const fullTableName = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
2373
+ try {
2374
+ const triggerSQL = generateTimestampTriggerSQL(tableName, this.schemaName);
2354
2375
  await this.client.none(triggerSQL);
2355
2376
  this.logger?.debug?.(`Set up timestamp triggers for table ${fullTableName}`);
2356
2377
  } catch (error) {
@@ -3143,6 +3164,24 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3143
3164
  this.#skipDefaultIndexes = skipDefaultIndexes;
3144
3165
  this.#indexes = indexes?.filter((idx) => _AgentsPG.MANAGED_TABLES.includes(idx.table));
3145
3166
  }
3167
+ /**
3168
+ * Returns all DDL statements for this domain: tables.
3169
+ * Used by exportSchemas to produce a complete, reproducible schema export.
3170
+ */
3171
+ static getExportDDL(schemaName) {
3172
+ const statements = [];
3173
+ for (const tableName of _AgentsPG.MANAGED_TABLES) {
3174
+ statements.push(
3175
+ generateTableSQL({
3176
+ tableName,
3177
+ schema: TABLE_SCHEMAS[tableName],
3178
+ schemaName,
3179
+ includeAllConstraints: true
3180
+ })
3181
+ );
3182
+ }
3183
+ return statements;
3184
+ }
3146
3185
  /**
3147
3186
  * Returns default index definitions for the agents domain tables.
3148
3187
  * Currently no default indexes are defined for agents.
@@ -3488,7 +3527,9 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3488
3527
  "inputProcessors",
3489
3528
  "outputProcessors",
3490
3529
  "memory",
3491
- "scorers"
3530
+ "scorers",
3531
+ "mcpClients",
3532
+ "requestContextSchema"
3492
3533
  ];
3493
3534
  const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
3494
3535
  if (hasConfigUpdate) {
@@ -3618,16 +3659,1975 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3618
3659
  },
3619
3660
  new Error("page must be >= 0")
3620
3661
  );
3621
- }
3622
- const perPage = normalizePerPage(perPageInput, 100);
3623
- const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
3624
- try {
3625
- const tableName = getTableName2({ indexName: TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3626
- const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName}`);
3662
+ }
3663
+ const perPage = normalizePerPage(perPageInput, 100);
3664
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
3665
+ try {
3666
+ const tableName = getTableName2({ indexName: TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3667
+ const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName}`);
3668
+ const total = parseInt(countResult.count, 10);
3669
+ if (total === 0) {
3670
+ return {
3671
+ agents: [],
3672
+ total: 0,
3673
+ page,
3674
+ perPage: perPageForResponse,
3675
+ hasMore: false
3676
+ };
3677
+ }
3678
+ const limitValue = perPageInput === false ? total : perPage;
3679
+ const dataResult = await this.#db.client.manyOrNone(
3680
+ `SELECT * FROM ${tableName} ORDER BY "${field}" ${direction} LIMIT $1 OFFSET $2`,
3681
+ [limitValue, offset]
3682
+ );
3683
+ const agents = (dataResult || []).map((row) => this.parseRow(row));
3684
+ return {
3685
+ agents,
3686
+ total,
3687
+ page,
3688
+ perPage: perPageForResponse,
3689
+ hasMore: perPageInput === false ? false : offset + perPage < total
3690
+ };
3691
+ } catch (error) {
3692
+ if (error instanceof MastraError) throw error;
3693
+ throw new MastraError(
3694
+ {
3695
+ id: createStorageErrorId("PG", "LIST_AGENTS", "FAILED"),
3696
+ domain: ErrorDomain.STORAGE,
3697
+ category: ErrorCategory.THIRD_PARTY
3698
+ },
3699
+ error
3700
+ );
3701
+ }
3702
+ }
3703
+ // ==========================================================================
3704
+ // Agent Version Methods
3705
+ // ==========================================================================
3706
+ async createVersion(input) {
3707
+ try {
3708
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3709
+ const now = /* @__PURE__ */ new Date();
3710
+ const nowIso = now.toISOString();
3711
+ await this.#db.client.none(
3712
+ `INSERT INTO ${tableName} (
3713
+ id, "agentId", "versionNumber",
3714
+ name, description, instructions, model, tools,
3715
+ "defaultOptions", workflows, agents, "integrationTools",
3716
+ "inputProcessors", "outputProcessors", memory, scorers,
3717
+ "mcpClients", "requestContextSchema", "changedFields", "changeMessage",
3718
+ "createdAt", "createdAtZ"
3719
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22)`,
3720
+ [
3721
+ input.id,
3722
+ input.agentId,
3723
+ input.versionNumber,
3724
+ input.name,
3725
+ input.description ?? null,
3726
+ this.serializeInstructions(input.instructions),
3727
+ JSON.stringify(input.model),
3728
+ input.tools ? JSON.stringify(input.tools) : null,
3729
+ input.defaultOptions ? JSON.stringify(input.defaultOptions) : null,
3730
+ input.workflows ? JSON.stringify(input.workflows) : null,
3731
+ input.agents ? JSON.stringify(input.agents) : null,
3732
+ input.integrationTools ? JSON.stringify(input.integrationTools) : null,
3733
+ input.inputProcessors ? JSON.stringify(input.inputProcessors) : null,
3734
+ input.outputProcessors ? JSON.stringify(input.outputProcessors) : null,
3735
+ input.memory ? JSON.stringify(input.memory) : null,
3736
+ input.scorers ? JSON.stringify(input.scorers) : null,
3737
+ input.mcpClients ? JSON.stringify(input.mcpClients) : null,
3738
+ input.requestContextSchema ? JSON.stringify(input.requestContextSchema) : null,
3739
+ input.changedFields ? JSON.stringify(input.changedFields) : null,
3740
+ input.changeMessage ?? null,
3741
+ nowIso,
3742
+ nowIso
3743
+ ]
3744
+ );
3745
+ return {
3746
+ ...input,
3747
+ createdAt: now
3748
+ };
3749
+ } catch (error) {
3750
+ if (error instanceof MastraError) throw error;
3751
+ throw new MastraError(
3752
+ {
3753
+ id: createStorageErrorId("PG", "CREATE_VERSION", "FAILED"),
3754
+ domain: ErrorDomain.STORAGE,
3755
+ category: ErrorCategory.THIRD_PARTY,
3756
+ details: { versionId: input.id, agentId: input.agentId }
3757
+ },
3758
+ error
3759
+ );
3760
+ }
3761
+ }
3762
+ async getVersion(id) {
3763
+ try {
3764
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3765
+ const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [id]);
3766
+ if (!result) {
3767
+ return null;
3768
+ }
3769
+ return this.parseVersionRow(result);
3770
+ } catch (error) {
3771
+ if (error instanceof MastraError) throw error;
3772
+ throw new MastraError(
3773
+ {
3774
+ id: createStorageErrorId("PG", "GET_VERSION", "FAILED"),
3775
+ domain: ErrorDomain.STORAGE,
3776
+ category: ErrorCategory.THIRD_PARTY,
3777
+ details: { versionId: id }
3778
+ },
3779
+ error
3780
+ );
3781
+ }
3782
+ }
3783
+ async getVersionByNumber(agentId, versionNumber) {
3784
+ try {
3785
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3786
+ const result = await this.#db.client.oneOrNone(
3787
+ `SELECT * FROM ${tableName} WHERE "agentId" = $1 AND "versionNumber" = $2`,
3788
+ [agentId, versionNumber]
3789
+ );
3790
+ if (!result) {
3791
+ return null;
3792
+ }
3793
+ return this.parseVersionRow(result);
3794
+ } catch (error) {
3795
+ if (error instanceof MastraError) throw error;
3796
+ throw new MastraError(
3797
+ {
3798
+ id: createStorageErrorId("PG", "GET_VERSION_BY_NUMBER", "FAILED"),
3799
+ domain: ErrorDomain.STORAGE,
3800
+ category: ErrorCategory.THIRD_PARTY,
3801
+ details: { agentId, versionNumber }
3802
+ },
3803
+ error
3804
+ );
3805
+ }
3806
+ }
3807
+ async getLatestVersion(agentId) {
3808
+ try {
3809
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3810
+ const result = await this.#db.client.oneOrNone(
3811
+ `SELECT * FROM ${tableName} WHERE "agentId" = $1 ORDER BY "versionNumber" DESC LIMIT 1`,
3812
+ [agentId]
3813
+ );
3814
+ if (!result) {
3815
+ return null;
3816
+ }
3817
+ return this.parseVersionRow(result);
3818
+ } catch (error) {
3819
+ if (error instanceof MastraError) throw error;
3820
+ throw new MastraError(
3821
+ {
3822
+ id: createStorageErrorId("PG", "GET_LATEST_VERSION", "FAILED"),
3823
+ domain: ErrorDomain.STORAGE,
3824
+ category: ErrorCategory.THIRD_PARTY,
3825
+ details: { agentId }
3826
+ },
3827
+ error
3828
+ );
3829
+ }
3830
+ }
3831
+ async listVersions(input) {
3832
+ const { agentId, page = 0, perPage: perPageInput, orderBy } = input;
3833
+ if (page < 0) {
3834
+ throw new MastraError(
3835
+ {
3836
+ id: createStorageErrorId("PG", "LIST_VERSIONS", "INVALID_PAGE"),
3837
+ domain: ErrorDomain.STORAGE,
3838
+ category: ErrorCategory.USER,
3839
+ details: { page }
3840
+ },
3841
+ new Error("page must be >= 0")
3842
+ );
3843
+ }
3844
+ const perPage = normalizePerPage(perPageInput, 20);
3845
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
3846
+ try {
3847
+ const { field, direction } = this.parseVersionOrderBy(orderBy);
3848
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3849
+ const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "agentId" = $1`, [
3850
+ agentId
3851
+ ]);
3852
+ const total = parseInt(countResult.count, 10);
3853
+ if (total === 0) {
3854
+ return {
3855
+ versions: [],
3856
+ total: 0,
3857
+ page,
3858
+ perPage: perPageForResponse,
3859
+ hasMore: false
3860
+ };
3861
+ }
3862
+ const limitValue = perPageInput === false ? total : perPage;
3863
+ const dataResult = await this.#db.client.manyOrNone(
3864
+ `SELECT * FROM ${tableName} WHERE "agentId" = $1 ORDER BY "${field}" ${direction} LIMIT $2 OFFSET $3`,
3865
+ [agentId, limitValue, offset]
3866
+ );
3867
+ const versions = (dataResult || []).map((row) => this.parseVersionRow(row));
3868
+ return {
3869
+ versions,
3870
+ total,
3871
+ page,
3872
+ perPage: perPageForResponse,
3873
+ hasMore: perPageInput === false ? false : offset + perPage < total
3874
+ };
3875
+ } catch (error) {
3876
+ if (error instanceof MastraError) throw error;
3877
+ throw new MastraError(
3878
+ {
3879
+ id: createStorageErrorId("PG", "LIST_VERSIONS", "FAILED"),
3880
+ domain: ErrorDomain.STORAGE,
3881
+ category: ErrorCategory.THIRD_PARTY,
3882
+ details: { agentId }
3883
+ },
3884
+ error
3885
+ );
3886
+ }
3887
+ }
3888
+ async deleteVersion(id) {
3889
+ try {
3890
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3891
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE id = $1`, [id]);
3892
+ } catch (error) {
3893
+ if (error instanceof MastraError) throw error;
3894
+ throw new MastraError(
3895
+ {
3896
+ id: createStorageErrorId("PG", "DELETE_VERSION", "FAILED"),
3897
+ domain: ErrorDomain.STORAGE,
3898
+ category: ErrorCategory.THIRD_PARTY,
3899
+ details: { versionId: id }
3900
+ },
3901
+ error
3902
+ );
3903
+ }
3904
+ }
3905
+ async deleteVersionsByParentId(entityId) {
3906
+ try {
3907
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3908
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE "agentId" = $1`, [entityId]);
3909
+ } catch (error) {
3910
+ if (error instanceof MastraError) throw error;
3911
+ throw new MastraError(
3912
+ {
3913
+ id: createStorageErrorId("PG", "DELETE_VERSIONS_BY_AGENT_ID", "FAILED"),
3914
+ domain: ErrorDomain.STORAGE,
3915
+ category: ErrorCategory.THIRD_PARTY,
3916
+ details: { agentId: entityId }
3917
+ },
3918
+ error
3919
+ );
3920
+ }
3921
+ }
3922
+ async countVersions(agentId) {
3923
+ try {
3924
+ const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3925
+ const result = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "agentId" = $1`, [
3926
+ agentId
3927
+ ]);
3928
+ return parseInt(result.count, 10);
3929
+ } catch (error) {
3930
+ if (error instanceof MastraError) throw error;
3931
+ throw new MastraError(
3932
+ {
3933
+ id: createStorageErrorId("PG", "COUNT_VERSIONS", "FAILED"),
3934
+ domain: ErrorDomain.STORAGE,
3935
+ category: ErrorCategory.THIRD_PARTY,
3936
+ details: { agentId }
3937
+ },
3938
+ error
3939
+ );
3940
+ }
3941
+ }
3942
+ // ==========================================================================
3943
+ // Private Helper Methods
3944
+ // ==========================================================================
3945
+ serializeInstructions(instructions) {
3946
+ if (instructions == null) return void 0;
3947
+ return Array.isArray(instructions) ? JSON.stringify(instructions) : instructions;
3948
+ }
3949
+ deserializeInstructions(raw) {
3950
+ if (!raw) return "";
3951
+ try {
3952
+ const parsed = JSON.parse(raw);
3953
+ if (Array.isArray(parsed)) return parsed;
3954
+ } catch {
3955
+ }
3956
+ return raw;
3957
+ }
3958
+ parseVersionRow(row) {
3959
+ return {
3960
+ id: row.id,
3961
+ agentId: row.agentId,
3962
+ versionNumber: row.versionNumber,
3963
+ name: row.name,
3964
+ description: row.description,
3965
+ instructions: this.deserializeInstructions(row.instructions),
3966
+ model: this.parseJson(row.model, "model"),
3967
+ tools: this.parseJson(row.tools, "tools"),
3968
+ defaultOptions: this.parseJson(row.defaultOptions, "defaultOptions"),
3969
+ workflows: this.parseJson(row.workflows, "workflows"),
3970
+ agents: this.parseJson(row.agents, "agents"),
3971
+ integrationTools: this.parseJson(row.integrationTools, "integrationTools"),
3972
+ inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
3973
+ outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
3974
+ memory: this.parseJson(row.memory, "memory"),
3975
+ scorers: this.parseJson(row.scorers, "scorers"),
3976
+ mcpClients: this.parseJson(row.mcpClients, "mcpClients"),
3977
+ requestContextSchema: this.parseJson(row.requestContextSchema, "requestContextSchema"),
3978
+ changedFields: this.parseJson(row.changedFields, "changedFields"),
3979
+ changeMessage: row.changeMessage,
3980
+ createdAt: row.createdAtZ || row.createdAt
3981
+ };
3982
+ }
3983
+ };
3984
+ function jsonbArg(value) {
3985
+ return value === void 0 || value === null ? null : JSON.stringify(value);
3986
+ }
3987
+ var DatasetsPG = class _DatasetsPG extends DatasetsStorage {
3988
+ #db;
3989
+ #schema;
3990
+ #skipDefaultIndexes;
3991
+ #indexes;
3992
+ static MANAGED_TABLES = [TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS];
3993
+ constructor(config) {
3994
+ super();
3995
+ const { client, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
3996
+ this.#db = new PgDB({ client, schemaName, skipDefaultIndexes });
3997
+ this.#schema = schemaName || "public";
3998
+ this.#skipDefaultIndexes = skipDefaultIndexes;
3999
+ this.#indexes = indexes?.filter((idx) => _DatasetsPG.MANAGED_TABLES.includes(idx.table));
4000
+ }
4001
+ static getExportDDL(schemaName) {
4002
+ const statements = [];
4003
+ for (const tableName of _DatasetsPG.MANAGED_TABLES) {
4004
+ statements.push(
4005
+ generateTableSQL({
4006
+ tableName,
4007
+ schema: TABLE_SCHEMAS[tableName],
4008
+ schemaName,
4009
+ compositePrimaryKey: TABLE_CONFIGS[tableName]?.compositePrimaryKey,
4010
+ includeAllConstraints: true
4011
+ })
4012
+ );
4013
+ }
4014
+ return statements;
4015
+ }
4016
+ async init() {
4017
+ await this.#db.createTable({ tableName: TABLE_DATASETS, schema: DATASETS_SCHEMA });
4018
+ await this.#db.createTable({
4019
+ tableName: TABLE_DATASET_ITEMS,
4020
+ schema: DATASET_ITEMS_SCHEMA,
4021
+ compositePrimaryKey: TABLE_CONFIGS[TABLE_DATASET_ITEMS]?.compositePrimaryKey
4022
+ });
4023
+ await this.#db.createTable({ tableName: TABLE_DATASET_VERSIONS, schema: DATASET_VERSIONS_SCHEMA });
4024
+ await this.createDefaultIndexes();
4025
+ await this.createCustomIndexes();
4026
+ }
4027
+ getDefaultIndexDefinitions() {
4028
+ return [
4029
+ { name: "idx_dataset_items_dataset_validto", table: TABLE_DATASET_ITEMS, columns: ["datasetId", "validTo"] },
4030
+ {
4031
+ name: "idx_dataset_items_dataset_version",
4032
+ table: TABLE_DATASET_ITEMS,
4033
+ columns: ["datasetId", "datasetVersion"]
4034
+ },
4035
+ {
4036
+ name: "idx_dataset_items_dataset_validto_deleted",
4037
+ table: TABLE_DATASET_ITEMS,
4038
+ columns: ["datasetId", "validTo", "isDeleted"]
4039
+ },
4040
+ {
4041
+ name: "idx_dataset_versions_dataset_version",
4042
+ table: TABLE_DATASET_VERSIONS,
4043
+ columns: ["datasetId", "version"]
4044
+ },
4045
+ {
4046
+ name: "idx_dataset_versions_dataset_version_unique",
4047
+ table: TABLE_DATASET_VERSIONS,
4048
+ columns: ["datasetId", "version"],
4049
+ unique: true
4050
+ }
4051
+ ];
4052
+ }
4053
+ async createDefaultIndexes() {
4054
+ if (this.#skipDefaultIndexes) return;
4055
+ for (const indexDef of this.getDefaultIndexDefinitions()) {
4056
+ try {
4057
+ await this.#db.createIndex(indexDef);
4058
+ } catch (error) {
4059
+ this.logger?.warn?.(`Failed to create default index ${indexDef.name}:`, error);
4060
+ }
4061
+ }
4062
+ }
4063
+ async createCustomIndexes() {
4064
+ if (!this.#indexes || this.#indexes.length === 0) return;
4065
+ for (const indexDef of this.#indexes) {
4066
+ try {
4067
+ await this.#db.createIndex(indexDef);
4068
+ } catch (error) {
4069
+ this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
4070
+ }
4071
+ }
4072
+ }
4073
+ // --- Row transformers ---
4074
+ transformDatasetRow(row) {
4075
+ return {
4076
+ id: row.id,
4077
+ name: row.name,
4078
+ description: row.description ?? void 0,
4079
+ metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
4080
+ inputSchema: row.inputSchema ? safelyParseJSON(row.inputSchema) : void 0,
4081
+ groundTruthSchema: row.groundTruthSchema ? safelyParseJSON(row.groundTruthSchema) : void 0,
4082
+ version: row.version,
4083
+ createdAt: ensureDate(row.createdAtZ || row.createdAt),
4084
+ updatedAt: ensureDate(row.updatedAtZ || row.updatedAt)
4085
+ };
4086
+ }
4087
+ transformItemRow(row) {
4088
+ return {
4089
+ id: row.id,
4090
+ datasetId: row.datasetId,
4091
+ datasetVersion: row.datasetVersion,
4092
+ input: safelyParseJSON(row.input),
4093
+ groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : void 0,
4094
+ metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
4095
+ createdAt: ensureDate(row.createdAtZ || row.createdAt),
4096
+ updatedAt: ensureDate(row.updatedAtZ || row.updatedAt)
4097
+ };
4098
+ }
4099
+ transformItemRowFull(row) {
4100
+ return {
4101
+ id: row.id,
4102
+ datasetId: row.datasetId,
4103
+ datasetVersion: row.datasetVersion,
4104
+ validTo: row.validTo,
4105
+ isDeleted: Boolean(row.isDeleted),
4106
+ input: safelyParseJSON(row.input),
4107
+ groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : void 0,
4108
+ metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
4109
+ createdAt: ensureDate(row.createdAtZ || row.createdAt),
4110
+ updatedAt: ensureDate(row.updatedAtZ || row.updatedAt)
4111
+ };
4112
+ }
4113
+ transformDatasetVersionRow(row) {
4114
+ return {
4115
+ id: row.id,
4116
+ datasetId: row.datasetId,
4117
+ version: row.version,
4118
+ createdAt: ensureDate(row.createdAtZ || row.createdAt)
4119
+ };
4120
+ }
4121
+ // --- Dataset CRUD ---
4122
+ async createDataset(input) {
4123
+ try {
4124
+ const id = crypto.randomUUID();
4125
+ const now = /* @__PURE__ */ new Date();
4126
+ const nowIso = now.toISOString();
4127
+ await this.#db.insert({
4128
+ tableName: TABLE_DATASETS,
4129
+ record: {
4130
+ id,
4131
+ name: input.name,
4132
+ description: input.description ?? null,
4133
+ metadata: input.metadata ?? null,
4134
+ inputSchema: input.inputSchema ?? null,
4135
+ groundTruthSchema: input.groundTruthSchema ?? null,
4136
+ version: 0,
4137
+ createdAt: nowIso,
4138
+ updatedAt: nowIso
4139
+ }
4140
+ });
4141
+ return {
4142
+ id,
4143
+ name: input.name,
4144
+ description: input.description,
4145
+ metadata: input.metadata,
4146
+ inputSchema: input.inputSchema,
4147
+ groundTruthSchema: input.groundTruthSchema,
4148
+ version: 0,
4149
+ createdAt: now,
4150
+ updatedAt: now
4151
+ };
4152
+ } catch (error) {
4153
+ throw new MastraError(
4154
+ {
4155
+ id: createStorageErrorId("PG", "CREATE_DATASET", "FAILED"),
4156
+ domain: ErrorDomain.STORAGE,
4157
+ category: ErrorCategory.THIRD_PARTY
4158
+ },
4159
+ error
4160
+ );
4161
+ }
4162
+ }
4163
+ async getDatasetById({ id }) {
4164
+ try {
4165
+ const tableName = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4166
+ const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1`, [id]);
4167
+ return result ? this.transformDatasetRow(result) : null;
4168
+ } catch (error) {
4169
+ throw new MastraError(
4170
+ {
4171
+ id: createStorageErrorId("PG", "GET_DATASET", "FAILED"),
4172
+ domain: ErrorDomain.STORAGE,
4173
+ category: ErrorCategory.THIRD_PARTY
4174
+ },
4175
+ error
4176
+ );
4177
+ }
4178
+ }
4179
+ async _doUpdateDataset(args) {
4180
+ try {
4181
+ const existing = await this.getDatasetById({ id: args.id });
4182
+ if (!existing) {
4183
+ throw new MastraError({
4184
+ id: createStorageErrorId("PG", "UPDATE_DATASET", "NOT_FOUND"),
4185
+ domain: ErrorDomain.STORAGE,
4186
+ category: ErrorCategory.USER,
4187
+ details: { datasetId: args.id }
4188
+ });
4189
+ }
4190
+ const tableName = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4191
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4192
+ const setClauses = ['"updatedAt" = $1', '"updatedAtZ" = $2'];
4193
+ const values = [now, now];
4194
+ let paramIndex = 3;
4195
+ if (args.name !== void 0) {
4196
+ setClauses.push(`"name" = $${paramIndex++}`);
4197
+ values.push(args.name);
4198
+ }
4199
+ if (args.description !== void 0) {
4200
+ setClauses.push(`"description" = $${paramIndex++}`);
4201
+ values.push(args.description);
4202
+ }
4203
+ if (args.metadata !== void 0) {
4204
+ setClauses.push(`"metadata" = $${paramIndex++}`);
4205
+ values.push(JSON.stringify(args.metadata));
4206
+ }
4207
+ if (args.inputSchema !== void 0) {
4208
+ setClauses.push(`"inputSchema" = $${paramIndex++}`);
4209
+ values.push(args.inputSchema === null ? null : JSON.stringify(args.inputSchema));
4210
+ }
4211
+ if (args.groundTruthSchema !== void 0) {
4212
+ setClauses.push(`"groundTruthSchema" = $${paramIndex++}`);
4213
+ values.push(args.groundTruthSchema === null ? null : JSON.stringify(args.groundTruthSchema));
4214
+ }
4215
+ values.push(args.id);
4216
+ await this.#db.client.none(
4217
+ `UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE "id" = $${paramIndex}`,
4218
+ values
4219
+ );
4220
+ return {
4221
+ ...existing,
4222
+ name: args.name ?? existing.name,
4223
+ description: args.description ?? existing.description,
4224
+ metadata: args.metadata ?? existing.metadata,
4225
+ inputSchema: args.inputSchema !== void 0 ? args.inputSchema : existing.inputSchema,
4226
+ groundTruthSchema: args.groundTruthSchema !== void 0 ? args.groundTruthSchema : existing.groundTruthSchema,
4227
+ updatedAt: new Date(now)
4228
+ };
4229
+ } catch (error) {
4230
+ if (error instanceof MastraError) throw error;
4231
+ throw new MastraError(
4232
+ {
4233
+ id: createStorageErrorId("PG", "UPDATE_DATASET", "FAILED"),
4234
+ domain: ErrorDomain.STORAGE,
4235
+ category: ErrorCategory.THIRD_PARTY
4236
+ },
4237
+ error
4238
+ );
4239
+ }
4240
+ }
4241
+ async deleteDataset({ id }) {
4242
+ try {
4243
+ const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4244
+ const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4245
+ const versionsTable = getTableName2({
4246
+ indexName: TABLE_DATASET_VERSIONS,
4247
+ schemaName: getSchemaName2(this.#schema)
4248
+ });
4249
+ const experimentsTable = getTableName2({ indexName: TABLE_EXPERIMENTS, schemaName: getSchemaName2(this.#schema) });
4250
+ const experimentResultsTable = getTableName2({
4251
+ indexName: TABLE_EXPERIMENT_RESULTS,
4252
+ schemaName: getSchemaName2(this.#schema)
4253
+ });
4254
+ try {
4255
+ await this.#db.client.none(
4256
+ `DELETE FROM ${experimentResultsTable} WHERE "experimentId" IN (SELECT "id" FROM ${experimentsTable} WHERE "datasetId" = $1)`,
4257
+ [id]
4258
+ );
4259
+ } catch {
4260
+ }
4261
+ try {
4262
+ await this.#db.client.none(
4263
+ `UPDATE ${experimentsTable} SET "datasetId" = NULL, "datasetVersion" = NULL WHERE "datasetId" = $1`,
4264
+ [id]
4265
+ );
4266
+ } catch {
4267
+ }
4268
+ await this.#db.client.tx(async (t) => {
4269
+ await t.none(`DELETE FROM ${versionsTable} WHERE "datasetId" = $1`, [id]);
4270
+ await t.none(`DELETE FROM ${itemsTable} WHERE "datasetId" = $1`, [id]);
4271
+ await t.none(`DELETE FROM ${datasetsTable} WHERE "id" = $1`, [id]);
4272
+ });
4273
+ } catch (error) {
4274
+ if (error instanceof MastraError) throw error;
4275
+ throw new MastraError(
4276
+ {
4277
+ id: createStorageErrorId("PG", "DELETE_DATASET", "FAILED"),
4278
+ domain: ErrorDomain.STORAGE,
4279
+ category: ErrorCategory.THIRD_PARTY
4280
+ },
4281
+ error
4282
+ );
4283
+ }
4284
+ }
4285
+ async listDatasets(args) {
4286
+ try {
4287
+ const { page, perPage: perPageInput } = args.pagination;
4288
+ const tableName = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4289
+ const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName}`);
4290
+ const total = parseInt(countResult.count, 10);
4291
+ if (total === 0) {
4292
+ return { datasets: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
4293
+ }
4294
+ const perPage = normalizePerPage(perPageInput, 100);
4295
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
4296
+ const limitValue = perPageInput === false ? total : perPage;
4297
+ const rows = await this.#db.client.manyOrNone(
4298
+ `SELECT * FROM ${tableName} ORDER BY "createdAt" DESC LIMIT $1 OFFSET $2`,
4299
+ [limitValue, offset]
4300
+ );
4301
+ return {
4302
+ datasets: (rows || []).map((row) => this.transformDatasetRow(row)),
4303
+ pagination: {
4304
+ total,
4305
+ page,
4306
+ perPage: perPageForResponse,
4307
+ hasMore: perPageInput === false ? false : offset + perPage < total
4308
+ }
4309
+ };
4310
+ } catch (error) {
4311
+ throw new MastraError(
4312
+ {
4313
+ id: createStorageErrorId("PG", "LIST_DATASETS", "FAILED"),
4314
+ domain: ErrorDomain.STORAGE,
4315
+ category: ErrorCategory.THIRD_PARTY
4316
+ },
4317
+ error
4318
+ );
4319
+ }
4320
+ }
4321
+ // --- SCD-2 mutations ---
4322
+ async _doAddItem(args) {
4323
+ try {
4324
+ const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4325
+ const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4326
+ const versionsTable = getTableName2({
4327
+ indexName: TABLE_DATASET_VERSIONS,
4328
+ schemaName: getSchemaName2(this.#schema)
4329
+ });
4330
+ const id = crypto.randomUUID();
4331
+ const versionId = crypto.randomUUID();
4332
+ const now = /* @__PURE__ */ new Date();
4333
+ const nowIso = now.toISOString();
4334
+ let newVersion;
4335
+ await this.#db.client.tx(async (t) => {
4336
+ const row = await t.one(
4337
+ `UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`,
4338
+ [args.datasetId]
4339
+ );
4340
+ newVersion = row.version;
4341
+ await t.none(
4342
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","validTo","isDeleted","input","groundTruth","metadata","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,NULL,false,$4,$5,$6,$7,$8,$9,$10)`,
4343
+ [
4344
+ id,
4345
+ args.datasetId,
4346
+ newVersion,
4347
+ JSON.stringify(args.input),
4348
+ jsonbArg(args.groundTruth),
4349
+ jsonbArg(args.metadata),
4350
+ nowIso,
4351
+ nowIso,
4352
+ nowIso,
4353
+ nowIso
4354
+ ]
4355
+ );
4356
+ await t.none(
4357
+ `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
4358
+ [versionId, args.datasetId, newVersion, nowIso, nowIso]
4359
+ );
4360
+ });
4361
+ return {
4362
+ id,
4363
+ datasetId: args.datasetId,
4364
+ datasetVersion: newVersion,
4365
+ input: args.input,
4366
+ groundTruth: args.groundTruth,
4367
+ metadata: args.metadata,
4368
+ createdAt: now,
4369
+ updatedAt: now
4370
+ };
4371
+ } catch (error) {
4372
+ if (error instanceof MastraError) throw error;
4373
+ throw new MastraError(
4374
+ {
4375
+ id: createStorageErrorId("PG", "ADD_ITEM", "FAILED"),
4376
+ domain: ErrorDomain.STORAGE,
4377
+ category: ErrorCategory.THIRD_PARTY
4378
+ },
4379
+ error
4380
+ );
4381
+ }
4382
+ }
4383
+ async _doUpdateItem(args) {
4384
+ try {
4385
+ const existing = await this.getItemById({ id: args.id });
4386
+ if (!existing) {
4387
+ throw new MastraError({
4388
+ id: createStorageErrorId("PG", "UPDATE_ITEM", "NOT_FOUND"),
4389
+ domain: ErrorDomain.STORAGE,
4390
+ category: ErrorCategory.USER,
4391
+ details: { itemId: args.id }
4392
+ });
4393
+ }
4394
+ if (existing.datasetId !== args.datasetId) {
4395
+ throw new MastraError({
4396
+ id: createStorageErrorId("PG", "UPDATE_ITEM", "DATASET_MISMATCH"),
4397
+ domain: ErrorDomain.STORAGE,
4398
+ category: ErrorCategory.USER,
4399
+ details: { itemId: args.id, expectedDatasetId: args.datasetId, actualDatasetId: existing.datasetId }
4400
+ });
4401
+ }
4402
+ const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4403
+ const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4404
+ const versionsTable = getTableName2({
4405
+ indexName: TABLE_DATASET_VERSIONS,
4406
+ schemaName: getSchemaName2(this.#schema)
4407
+ });
4408
+ const versionId = crypto.randomUUID();
4409
+ const now = /* @__PURE__ */ new Date();
4410
+ const nowIso = now.toISOString();
4411
+ const mergedInput = args.input ?? existing.input;
4412
+ const mergedGroundTruth = args.groundTruth ?? existing.groundTruth;
4413
+ const mergedMetadata = args.metadata ?? existing.metadata;
4414
+ let newVersion;
4415
+ await this.#db.client.tx(async (t) => {
4416
+ const row = await t.one(
4417
+ `UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`,
4418
+ [args.datasetId]
4419
+ );
4420
+ newVersion = row.version;
4421
+ await t.none(
4422
+ `UPDATE ${itemsTable} SET "validTo" = $1 WHERE "id" = $2 AND "validTo" IS NULL AND "isDeleted" = false`,
4423
+ [newVersion, args.id]
4424
+ );
4425
+ await t.none(
4426
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","validTo","isDeleted","input","groundTruth","metadata","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,NULL,false,$4,$5,$6,$7,$8,$9,$10)`,
4427
+ [
4428
+ args.id,
4429
+ args.datasetId,
4430
+ newVersion,
4431
+ JSON.stringify(mergedInput),
4432
+ jsonbArg(mergedGroundTruth),
4433
+ jsonbArg(mergedMetadata),
4434
+ existing.createdAt.toISOString(),
4435
+ existing.createdAt.toISOString(),
4436
+ nowIso,
4437
+ nowIso
4438
+ ]
4439
+ );
4440
+ await t.none(
4441
+ `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
4442
+ [versionId, args.datasetId, newVersion, nowIso, nowIso]
4443
+ );
4444
+ });
4445
+ return {
4446
+ ...existing,
4447
+ datasetVersion: newVersion,
4448
+ input: mergedInput,
4449
+ groundTruth: mergedGroundTruth,
4450
+ metadata: mergedMetadata,
4451
+ updatedAt: now
4452
+ };
4453
+ } catch (error) {
4454
+ if (error instanceof MastraError) throw error;
4455
+ throw new MastraError(
4456
+ {
4457
+ id: createStorageErrorId("PG", "UPDATE_ITEM", "FAILED"),
4458
+ domain: ErrorDomain.STORAGE,
4459
+ category: ErrorCategory.THIRD_PARTY
4460
+ },
4461
+ error
4462
+ );
4463
+ }
4464
+ }
4465
+ async _doDeleteItem({ id, datasetId }) {
4466
+ try {
4467
+ const existing = await this.getItemById({ id });
4468
+ if (!existing) return;
4469
+ if (existing.datasetId !== datasetId) {
4470
+ throw new MastraError({
4471
+ id: createStorageErrorId("PG", "DELETE_ITEM", "DATASET_MISMATCH"),
4472
+ domain: ErrorDomain.STORAGE,
4473
+ category: ErrorCategory.USER,
4474
+ details: { itemId: id, expectedDatasetId: datasetId, actualDatasetId: existing.datasetId }
4475
+ });
4476
+ }
4477
+ const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4478
+ const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4479
+ const versionsTable = getTableName2({
4480
+ indexName: TABLE_DATASET_VERSIONS,
4481
+ schemaName: getSchemaName2(this.#schema)
4482
+ });
4483
+ const versionId = crypto.randomUUID();
4484
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
4485
+ await this.#db.client.tx(async (t) => {
4486
+ const row = await t.one(
4487
+ `UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`,
4488
+ [datasetId]
4489
+ );
4490
+ const newVersion = row.version;
4491
+ await t.none(
4492
+ `UPDATE ${itemsTable} SET "validTo" = $1 WHERE "id" = $2 AND "validTo" IS NULL AND "isDeleted" = false`,
4493
+ [newVersion, id]
4494
+ );
4495
+ await t.none(
4496
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","validTo","isDeleted","input","groundTruth","metadata","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,NULL,true,$4,$5,$6,$7,$8,$9,$10)`,
4497
+ [
4498
+ id,
4499
+ datasetId,
4500
+ newVersion,
4501
+ JSON.stringify(existing.input),
4502
+ jsonbArg(existing.groundTruth),
4503
+ jsonbArg(existing.metadata),
4504
+ existing.createdAt.toISOString(),
4505
+ existing.createdAt.toISOString(),
4506
+ nowIso,
4507
+ nowIso
4508
+ ]
4509
+ );
4510
+ await t.none(
4511
+ `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
4512
+ [versionId, datasetId, newVersion, nowIso, nowIso]
4513
+ );
4514
+ });
4515
+ } catch (error) {
4516
+ if (error instanceof MastraError) throw error;
4517
+ throw new MastraError(
4518
+ {
4519
+ id: createStorageErrorId("PG", "DELETE_ITEM", "FAILED"),
4520
+ domain: ErrorDomain.STORAGE,
4521
+ category: ErrorCategory.THIRD_PARTY
4522
+ },
4523
+ error
4524
+ );
4525
+ }
4526
+ }
4527
+ async _doBatchInsertItems(input) {
4528
+ try {
4529
+ const dataset = await this.getDatasetById({ id: input.datasetId });
4530
+ if (!dataset) {
4531
+ throw new MastraError({
4532
+ id: createStorageErrorId("PG", "BULK_ADD_ITEMS", "DATASET_NOT_FOUND"),
4533
+ domain: ErrorDomain.STORAGE,
4534
+ category: ErrorCategory.USER,
4535
+ details: { datasetId: input.datasetId }
4536
+ });
4537
+ }
4538
+ const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4539
+ const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4540
+ const versionsTable = getTableName2({
4541
+ indexName: TABLE_DATASET_VERSIONS,
4542
+ schemaName: getSchemaName2(this.#schema)
4543
+ });
4544
+ const now = /* @__PURE__ */ new Date();
4545
+ const nowIso = now.toISOString();
4546
+ const versionId = crypto.randomUUID();
4547
+ const itemsWithIds = input.items.map((itemInput) => ({ id: crypto.randomUUID(), input: itemInput }));
4548
+ let newVersion;
4549
+ await this.#db.client.tx(async (t) => {
4550
+ const row = await t.one(
4551
+ `UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`,
4552
+ [input.datasetId]
4553
+ );
4554
+ newVersion = row.version;
4555
+ for (const { id, input: itemInput } of itemsWithIds) {
4556
+ await t.none(
4557
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","validTo","isDeleted","input","groundTruth","metadata","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,NULL,false,$4,$5,$6,$7,$8,$9,$10)`,
4558
+ [
4559
+ id,
4560
+ input.datasetId,
4561
+ newVersion,
4562
+ JSON.stringify(itemInput.input),
4563
+ jsonbArg(itemInput.groundTruth),
4564
+ jsonbArg(itemInput.metadata),
4565
+ nowIso,
4566
+ nowIso,
4567
+ nowIso,
4568
+ nowIso
4569
+ ]
4570
+ );
4571
+ }
4572
+ await t.none(
4573
+ `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
4574
+ [versionId, input.datasetId, newVersion, nowIso, nowIso]
4575
+ );
4576
+ });
4577
+ return itemsWithIds.map(({ id, input: itemInput }) => ({
4578
+ id,
4579
+ datasetId: input.datasetId,
4580
+ datasetVersion: newVersion,
4581
+ input: itemInput.input,
4582
+ groundTruth: itemInput.groundTruth,
4583
+ metadata: itemInput.metadata,
4584
+ createdAt: now,
4585
+ updatedAt: now
4586
+ }));
4587
+ } catch (error) {
4588
+ if (error instanceof MastraError) throw error;
4589
+ throw new MastraError(
4590
+ {
4591
+ id: createStorageErrorId("PG", "BULK_ADD_ITEMS", "FAILED"),
4592
+ domain: ErrorDomain.STORAGE,
4593
+ category: ErrorCategory.THIRD_PARTY
4594
+ },
4595
+ error
4596
+ );
4597
+ }
4598
+ }
4599
+ async _doBatchDeleteItems(input) {
4600
+ try {
4601
+ const dataset = await this.getDatasetById({ id: input.datasetId });
4602
+ if (!dataset) {
4603
+ throw new MastraError({
4604
+ id: createStorageErrorId("PG", "BULK_DELETE_ITEMS", "DATASET_NOT_FOUND"),
4605
+ domain: ErrorDomain.STORAGE,
4606
+ category: ErrorCategory.USER,
4607
+ details: { datasetId: input.datasetId }
4608
+ });
4609
+ }
4610
+ const currentItems = [];
4611
+ for (const itemId of input.itemIds) {
4612
+ const item = await this.getItemById({ id: itemId });
4613
+ if (item && item.datasetId === input.datasetId) {
4614
+ currentItems.push(item);
4615
+ }
4616
+ }
4617
+ if (currentItems.length === 0) return;
4618
+ const datasetsTable = getTableName2({ indexName: TABLE_DATASETS, schemaName: getSchemaName2(this.#schema) });
4619
+ const itemsTable = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4620
+ const versionsTable = getTableName2({
4621
+ indexName: TABLE_DATASET_VERSIONS,
4622
+ schemaName: getSchemaName2(this.#schema)
4623
+ });
4624
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
4625
+ const versionId = crypto.randomUUID();
4626
+ await this.#db.client.tx(async (t) => {
4627
+ const row = await t.one(
4628
+ `UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`,
4629
+ [input.datasetId]
4630
+ );
4631
+ const newVersion = row.version;
4632
+ for (const item of currentItems) {
4633
+ await t.none(
4634
+ `UPDATE ${itemsTable} SET "validTo" = $1 WHERE "id" = $2 AND "validTo" IS NULL AND "isDeleted" = false`,
4635
+ [newVersion, item.id]
4636
+ );
4637
+ await t.none(
4638
+ `INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","validTo","isDeleted","input","groundTruth","metadata","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,NULL,true,$4,$5,$6,$7,$8,$9,$10)`,
4639
+ [
4640
+ item.id,
4641
+ input.datasetId,
4642
+ newVersion,
4643
+ JSON.stringify(item.input),
4644
+ jsonbArg(item.groundTruth),
4645
+ jsonbArg(item.metadata),
4646
+ item.createdAt.toISOString(),
4647
+ item.createdAt.toISOString(),
4648
+ nowIso,
4649
+ nowIso
4650
+ ]
4651
+ );
4652
+ }
4653
+ await t.none(
4654
+ `INSERT INTO ${versionsTable} ("id","datasetId","version","createdAt","createdAtZ") VALUES ($1,$2,$3,$4,$5)`,
4655
+ [versionId, input.datasetId, newVersion, nowIso, nowIso]
4656
+ );
4657
+ });
4658
+ } catch (error) {
4659
+ if (error instanceof MastraError) throw error;
4660
+ throw new MastraError(
4661
+ {
4662
+ id: createStorageErrorId("PG", "BULK_DELETE_ITEMS", "FAILED"),
4663
+ domain: ErrorDomain.STORAGE,
4664
+ category: ErrorCategory.THIRD_PARTY
4665
+ },
4666
+ error
4667
+ );
4668
+ }
4669
+ }
4670
+ // --- SCD-2 queries ---
4671
+ async getItemById(args) {
4672
+ try {
4673
+ const tableName = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4674
+ let result;
4675
+ if (args.datasetVersion !== void 0) {
4676
+ result = await this.#db.client.oneOrNone(
4677
+ `SELECT * FROM ${tableName} WHERE "id" = $1 AND "datasetVersion" = $2 AND "isDeleted" = false`,
4678
+ [args.id, args.datasetVersion]
4679
+ );
4680
+ } else {
4681
+ result = await this.#db.client.oneOrNone(
4682
+ `SELECT * FROM ${tableName} WHERE "id" = $1 AND "validTo" IS NULL AND "isDeleted" = false`,
4683
+ [args.id]
4684
+ );
4685
+ }
4686
+ return result ? this.transformItemRow(result) : null;
4687
+ } catch (error) {
4688
+ throw new MastraError(
4689
+ {
4690
+ id: createStorageErrorId("PG", "GET_ITEM", "FAILED"),
4691
+ domain: ErrorDomain.STORAGE,
4692
+ category: ErrorCategory.THIRD_PARTY
4693
+ },
4694
+ error
4695
+ );
4696
+ }
4697
+ }
4698
+ async getItemsByVersion({ datasetId, version }) {
4699
+ try {
4700
+ const tableName = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4701
+ const rows = await this.#db.client.manyOrNone(
4702
+ `SELECT * FROM ${tableName} WHERE "datasetId" = $1 AND "datasetVersion" <= $2 AND ("validTo" IS NULL OR "validTo" > $3) AND "isDeleted" = false ORDER BY "createdAt" DESC`,
4703
+ [datasetId, version, version]
4704
+ );
4705
+ return (rows || []).map((row) => this.transformItemRow(row));
4706
+ } catch (error) {
4707
+ throw new MastraError(
4708
+ {
4709
+ id: createStorageErrorId("PG", "GET_ITEMS_BY_VERSION", "FAILED"),
4710
+ domain: ErrorDomain.STORAGE,
4711
+ category: ErrorCategory.THIRD_PARTY
4712
+ },
4713
+ error
4714
+ );
4715
+ }
4716
+ }
4717
+ async getItemHistory(itemId) {
4718
+ try {
4719
+ const tableName = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4720
+ const rows = await this.#db.client.manyOrNone(
4721
+ `SELECT * FROM ${tableName} WHERE "id" = $1 ORDER BY "datasetVersion" DESC`,
4722
+ [itemId]
4723
+ );
4724
+ return (rows || []).map((row) => this.transformItemRowFull(row));
4725
+ } catch (error) {
4726
+ throw new MastraError(
4727
+ {
4728
+ id: createStorageErrorId("PG", "GET_ITEM_HISTORY", "FAILED"),
4729
+ domain: ErrorDomain.STORAGE,
4730
+ category: ErrorCategory.THIRD_PARTY
4731
+ },
4732
+ error
4733
+ );
4734
+ }
4735
+ }
4736
+ async listItems(args) {
4737
+ try {
4738
+ const { page, perPage: perPageInput } = args.pagination;
4739
+ const tableName = getTableName2({ indexName: TABLE_DATASET_ITEMS, schemaName: getSchemaName2(this.#schema) });
4740
+ const conditions = ['"datasetId" = $1'];
4741
+ const queryParams = [args.datasetId];
4742
+ let paramIndex = 2;
4743
+ if (args.version !== void 0) {
4744
+ conditions.push(`"datasetVersion" <= $${paramIndex++}`);
4745
+ queryParams.push(args.version);
4746
+ conditions.push(`("validTo" IS NULL OR "validTo" > $${paramIndex++})`);
4747
+ queryParams.push(args.version);
4748
+ conditions.push(`"isDeleted" = false`);
4749
+ } else {
4750
+ conditions.push(`"validTo" IS NULL`);
4751
+ conditions.push(`"isDeleted" = false`);
4752
+ }
4753
+ if (args.search) {
4754
+ conditions.push(
4755
+ `("input"::text ILIKE $${paramIndex} OR COALESCE("groundTruth"::text, '') ILIKE $${paramIndex})`
4756
+ );
4757
+ queryParams.push(`%${args.search}%`);
4758
+ paramIndex++;
4759
+ }
4760
+ const whereClause = `WHERE ${conditions.join(" AND ")}`;
4761
+ const countResult = await this.#db.client.one(
4762
+ `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`,
4763
+ queryParams
4764
+ );
4765
+ const total = parseInt(countResult.count, 10);
4766
+ if (total === 0) {
4767
+ return { items: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
4768
+ }
4769
+ const perPage = normalizePerPage(perPageInput, 100);
4770
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
4771
+ const limitValue = perPageInput === false ? total : perPage;
4772
+ const rows = await this.#db.client.manyOrNone(
4773
+ `SELECT * FROM ${tableName} ${whereClause} ORDER BY "createdAt" DESC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`,
4774
+ [...queryParams, limitValue, offset]
4775
+ );
4776
+ return {
4777
+ items: (rows || []).map((row) => this.transformItemRow(row)),
4778
+ pagination: {
4779
+ total,
4780
+ page,
4781
+ perPage: perPageForResponse,
4782
+ hasMore: perPageInput === false ? false : offset + perPage < total
4783
+ }
4784
+ };
4785
+ } catch (error) {
4786
+ throw new MastraError(
4787
+ {
4788
+ id: createStorageErrorId("PG", "LIST_ITEMS", "FAILED"),
4789
+ domain: ErrorDomain.STORAGE,
4790
+ category: ErrorCategory.THIRD_PARTY
4791
+ },
4792
+ error
4793
+ );
4794
+ }
4795
+ }
4796
+ // --- Dataset versions ---
4797
+ async createDatasetVersion(datasetId, version) {
4798
+ try {
4799
+ const id = crypto.randomUUID();
4800
+ const now = /* @__PURE__ */ new Date();
4801
+ const nowIso = now.toISOString();
4802
+ await this.#db.insert({
4803
+ tableName: TABLE_DATASET_VERSIONS,
4804
+ record: { id, datasetId, version, createdAt: nowIso }
4805
+ });
4806
+ return { id, datasetId, version, createdAt: now };
4807
+ } catch (error) {
4808
+ throw new MastraError(
4809
+ {
4810
+ id: createStorageErrorId("PG", "CREATE_DATASET_VERSION", "FAILED"),
4811
+ domain: ErrorDomain.STORAGE,
4812
+ category: ErrorCategory.THIRD_PARTY
4813
+ },
4814
+ error
4815
+ );
4816
+ }
4817
+ }
4818
+ async listDatasetVersions(input) {
4819
+ try {
4820
+ const { page, perPage: perPageInput } = input.pagination;
4821
+ const tableName = getTableName2({ indexName: TABLE_DATASET_VERSIONS, schemaName: getSchemaName2(this.#schema) });
4822
+ const countResult = await this.#db.client.one(
4823
+ `SELECT COUNT(*) as count FROM ${tableName} WHERE "datasetId" = $1`,
4824
+ [input.datasetId]
4825
+ );
4826
+ const total = parseInt(countResult.count, 10);
4827
+ if (total === 0) {
4828
+ return { versions: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
4829
+ }
4830
+ const perPage = normalizePerPage(perPageInput, 100);
4831
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
4832
+ const limitValue = perPageInput === false ? total : perPage;
4833
+ const rows = await this.#db.client.manyOrNone(
4834
+ `SELECT * FROM ${tableName} WHERE "datasetId" = $1 ORDER BY "version" DESC LIMIT $2 OFFSET $3`,
4835
+ [input.datasetId, limitValue, offset]
4836
+ );
4837
+ return {
4838
+ versions: (rows || []).map((row) => this.transformDatasetVersionRow(row)),
4839
+ pagination: {
4840
+ total,
4841
+ page,
4842
+ perPage: perPageForResponse,
4843
+ hasMore: perPageInput === false ? false : offset + perPage < total
4844
+ }
4845
+ };
4846
+ } catch (error) {
4847
+ throw new MastraError(
4848
+ {
4849
+ id: createStorageErrorId("PG", "LIST_DATASET_VERSIONS", "FAILED"),
4850
+ domain: ErrorDomain.STORAGE,
4851
+ category: ErrorCategory.THIRD_PARTY
4852
+ },
4853
+ error
4854
+ );
4855
+ }
4856
+ }
4857
+ // --- Clear ---
4858
+ async dangerouslyClearAll() {
4859
+ await this.#db.clearTable({ tableName: TABLE_DATASET_VERSIONS });
4860
+ await this.#db.clearTable({ tableName: TABLE_DATASET_ITEMS });
4861
+ await this.#db.clearTable({ tableName: TABLE_DATASETS });
4862
+ }
4863
+ };
4864
+ var ExperimentsPG = class _ExperimentsPG extends ExperimentsStorage {
4865
+ #db;
4866
+ #schema;
4867
+ #skipDefaultIndexes;
4868
+ #indexes;
4869
+ static MANAGED_TABLES = [TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS];
4870
+ constructor(config) {
4871
+ super();
4872
+ const { client, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
4873
+ this.#db = new PgDB({ client, schemaName, skipDefaultIndexes });
4874
+ this.#schema = schemaName || "public";
4875
+ this.#skipDefaultIndexes = skipDefaultIndexes;
4876
+ this.#indexes = indexes?.filter((idx) => _ExperimentsPG.MANAGED_TABLES.includes(idx.table));
4877
+ }
4878
+ static getExportDDL(schemaName) {
4879
+ const statements = [];
4880
+ for (const tableName of _ExperimentsPG.MANAGED_TABLES) {
4881
+ statements.push(
4882
+ generateTableSQL({
4883
+ tableName,
4884
+ schema: TABLE_SCHEMAS[tableName],
4885
+ schemaName,
4886
+ includeAllConstraints: true
4887
+ })
4888
+ );
4889
+ }
4890
+ return statements;
4891
+ }
4892
+ async init() {
4893
+ await this.#db.createTable({ tableName: TABLE_EXPERIMENTS, schema: EXPERIMENTS_SCHEMA });
4894
+ await this.#db.createTable({ tableName: TABLE_EXPERIMENT_RESULTS, schema: EXPERIMENT_RESULTS_SCHEMA });
4895
+ await this.createDefaultIndexes();
4896
+ await this.createCustomIndexes();
4897
+ }
4898
+ getDefaultIndexDefinitions() {
4899
+ return [
4900
+ { name: "idx_experiments_datasetid", table: TABLE_EXPERIMENTS, columns: ["datasetId"] },
4901
+ { name: "idx_experiment_results_experimentid", table: TABLE_EXPERIMENT_RESULTS, columns: ["experimentId"] },
4902
+ {
4903
+ name: "idx_experiment_results_exp_item",
4904
+ table: TABLE_EXPERIMENT_RESULTS,
4905
+ columns: ["experimentId", "itemId"],
4906
+ unique: true
4907
+ }
4908
+ ];
4909
+ }
4910
+ async createDefaultIndexes() {
4911
+ if (this.#skipDefaultIndexes) return;
4912
+ for (const indexDef of this.getDefaultIndexDefinitions()) {
4913
+ try {
4914
+ await this.#db.createIndex(indexDef);
4915
+ } catch (error) {
4916
+ this.logger?.warn?.(`Failed to create default index ${indexDef.name}:`, error);
4917
+ }
4918
+ }
4919
+ }
4920
+ async createCustomIndexes() {
4921
+ if (!this.#indexes || this.#indexes.length === 0) return;
4922
+ for (const indexDef of this.#indexes) {
4923
+ try {
4924
+ await this.#db.createIndex(indexDef);
4925
+ } catch (error) {
4926
+ this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
4927
+ }
4928
+ }
4929
+ }
4930
+ // --- Row transformers ---
4931
+ transformExperimentRow(row) {
4932
+ return {
4933
+ id: row.id,
4934
+ name: row.name ?? void 0,
4935
+ description: row.description ?? void 0,
4936
+ metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
4937
+ datasetId: row.datasetId ?? null,
4938
+ datasetVersion: row.datasetVersion != null ? row.datasetVersion : null,
4939
+ targetType: row.targetType,
4940
+ targetId: row.targetId,
4941
+ status: row.status,
4942
+ totalItems: row.totalItems,
4943
+ succeededCount: row.succeededCount,
4944
+ failedCount: row.failedCount,
4945
+ skippedCount: row.skippedCount ?? 0,
4946
+ startedAt: row.startedAt ? ensureDate(row.startedAtZ || row.startedAt) : null,
4947
+ completedAt: row.completedAt ? ensureDate(row.completedAtZ || row.completedAt) : null,
4948
+ createdAt: ensureDate(row.createdAtZ || row.createdAt),
4949
+ updatedAt: ensureDate(row.updatedAtZ || row.updatedAt)
4950
+ };
4951
+ }
4952
+ transformExperimentResultRow(row) {
4953
+ return {
4954
+ id: row.id,
4955
+ experimentId: row.experimentId,
4956
+ itemId: row.itemId,
4957
+ itemDatasetVersion: row.itemDatasetVersion != null ? row.itemDatasetVersion : null,
4958
+ input: safelyParseJSON(row.input),
4959
+ output: row.output ? safelyParseJSON(row.output) : null,
4960
+ groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : null,
4961
+ error: row.error ? safelyParseJSON(row.error) : null,
4962
+ startedAt: ensureDate(row.startedAtZ || row.startedAt),
4963
+ completedAt: ensureDate(row.completedAtZ || row.completedAt),
4964
+ retryCount: row.retryCount,
4965
+ traceId: row.traceId ?? null,
4966
+ createdAt: ensureDate(row.createdAtZ || row.createdAt)
4967
+ };
4968
+ }
4969
+ // --- Experiment CRUD ---
4970
+ async createExperiment(input) {
4971
+ try {
4972
+ const id = input.id ?? crypto.randomUUID();
4973
+ const now = /* @__PURE__ */ new Date();
4974
+ const nowIso = now.toISOString();
4975
+ await this.#db.insert({
4976
+ tableName: TABLE_EXPERIMENTS,
4977
+ record: {
4978
+ id,
4979
+ name: input.name ?? null,
4980
+ description: input.description ?? null,
4981
+ metadata: input.metadata ?? null,
4982
+ datasetId: input.datasetId ?? null,
4983
+ datasetVersion: input.datasetVersion ?? null,
4984
+ targetType: input.targetType,
4985
+ targetId: input.targetId,
4986
+ status: "pending",
4987
+ totalItems: input.totalItems,
4988
+ succeededCount: 0,
4989
+ failedCount: 0,
4990
+ skippedCount: 0,
4991
+ startedAt: null,
4992
+ completedAt: null,
4993
+ createdAt: nowIso,
4994
+ updatedAt: nowIso
4995
+ }
4996
+ });
4997
+ return {
4998
+ id,
4999
+ name: input.name,
5000
+ description: input.description,
5001
+ metadata: input.metadata,
5002
+ datasetId: input.datasetId ?? null,
5003
+ datasetVersion: input.datasetVersion ?? null,
5004
+ targetType: input.targetType,
5005
+ targetId: input.targetId,
5006
+ status: "pending",
5007
+ totalItems: input.totalItems,
5008
+ succeededCount: 0,
5009
+ failedCount: 0,
5010
+ skippedCount: 0,
5011
+ startedAt: null,
5012
+ completedAt: null,
5013
+ createdAt: now,
5014
+ updatedAt: now
5015
+ };
5016
+ } catch (error) {
5017
+ throw new MastraError(
5018
+ {
5019
+ id: createStorageErrorId("PG", "CREATE_EXPERIMENT", "FAILED"),
5020
+ domain: ErrorDomain.STORAGE,
5021
+ category: ErrorCategory.THIRD_PARTY
5022
+ },
5023
+ error
5024
+ );
5025
+ }
5026
+ }
5027
+ async updateExperiment(input) {
5028
+ try {
5029
+ const existing = await this.getExperimentById({ id: input.id });
5030
+ if (!existing) {
5031
+ throw new MastraError({
5032
+ id: createStorageErrorId("PG", "UPDATE_EXPERIMENT", "NOT_FOUND"),
5033
+ domain: ErrorDomain.STORAGE,
5034
+ category: ErrorCategory.USER,
5035
+ details: { experimentId: input.id }
5036
+ });
5037
+ }
5038
+ const tableName = getTableName2({ indexName: TABLE_EXPERIMENTS, schemaName: getSchemaName2(this.#schema) });
5039
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5040
+ const setClauses = ['"updatedAt" = $1', '"updatedAtZ" = $2'];
5041
+ const values = [now, now];
5042
+ let paramIndex = 3;
5043
+ if (input.name !== void 0) {
5044
+ setClauses.push(`"name" = $${paramIndex++}`);
5045
+ values.push(input.name);
5046
+ }
5047
+ if (input.description !== void 0) {
5048
+ setClauses.push(`"description" = $${paramIndex++}`);
5049
+ values.push(input.description);
5050
+ }
5051
+ if (input.metadata !== void 0) {
5052
+ setClauses.push(`"metadata" = $${paramIndex++}`);
5053
+ values.push(JSON.stringify(input.metadata));
5054
+ }
5055
+ if (input.status !== void 0) {
5056
+ setClauses.push(`"status" = $${paramIndex++}`);
5057
+ values.push(input.status);
5058
+ }
5059
+ if (input.succeededCount !== void 0) {
5060
+ setClauses.push(`"succeededCount" = $${paramIndex++}`);
5061
+ values.push(input.succeededCount);
5062
+ }
5063
+ if (input.failedCount !== void 0) {
5064
+ setClauses.push(`"failedCount" = $${paramIndex++}`);
5065
+ values.push(input.failedCount);
5066
+ }
5067
+ if (input.skippedCount !== void 0) {
5068
+ setClauses.push(`"skippedCount" = $${paramIndex++}`);
5069
+ values.push(input.skippedCount);
5070
+ }
5071
+ if (input.startedAt !== void 0) {
5072
+ setClauses.push(`"startedAt" = $${paramIndex++}`);
5073
+ values.push(input.startedAt?.toISOString() ?? null);
5074
+ }
5075
+ if (input.completedAt !== void 0) {
5076
+ setClauses.push(`"completedAt" = $${paramIndex++}`);
5077
+ values.push(input.completedAt?.toISOString() ?? null);
5078
+ }
5079
+ values.push(input.id);
5080
+ await this.#db.client.none(
5081
+ `UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE "id" = $${paramIndex}`,
5082
+ values
5083
+ );
5084
+ const updated = await this.getExperimentById({ id: input.id });
5085
+ return updated;
5086
+ } catch (error) {
5087
+ if (error instanceof MastraError) throw error;
5088
+ throw new MastraError(
5089
+ {
5090
+ id: createStorageErrorId("PG", "UPDATE_EXPERIMENT", "FAILED"),
5091
+ domain: ErrorDomain.STORAGE,
5092
+ category: ErrorCategory.THIRD_PARTY
5093
+ },
5094
+ error
5095
+ );
5096
+ }
5097
+ }
5098
+ async getExperimentById({ id }) {
5099
+ try {
5100
+ const tableName = getTableName2({ indexName: TABLE_EXPERIMENTS, schemaName: getSchemaName2(this.#schema) });
5101
+ const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1`, [id]);
5102
+ return result ? this.transformExperimentRow(result) : null;
5103
+ } catch (error) {
5104
+ throw new MastraError(
5105
+ {
5106
+ id: createStorageErrorId("PG", "GET_EXPERIMENT", "FAILED"),
5107
+ domain: ErrorDomain.STORAGE,
5108
+ category: ErrorCategory.THIRD_PARTY
5109
+ },
5110
+ error
5111
+ );
5112
+ }
5113
+ }
5114
+ async listExperiments(args) {
5115
+ try {
5116
+ const { page, perPage: perPageInput } = args.pagination;
5117
+ const tableName = getTableName2({ indexName: TABLE_EXPERIMENTS, schemaName: getSchemaName2(this.#schema) });
5118
+ const conditions = [];
5119
+ const queryParams = [];
5120
+ let paramIndex = 1;
5121
+ if (args.datasetId) {
5122
+ conditions.push(`"datasetId" = $${paramIndex++}`);
5123
+ queryParams.push(args.datasetId);
5124
+ }
5125
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
5126
+ const countResult = await this.#db.client.one(
5127
+ `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`,
5128
+ queryParams
5129
+ );
5130
+ const total = parseInt(countResult.count, 10);
5131
+ if (total === 0) {
5132
+ return { experiments: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
5133
+ }
5134
+ const perPage = normalizePerPage(perPageInput, 100);
5135
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
5136
+ const limitValue = perPageInput === false ? total : perPage;
5137
+ const rows = await this.#db.client.manyOrNone(
5138
+ `SELECT * FROM ${tableName} ${whereClause} ORDER BY "createdAt" DESC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`,
5139
+ [...queryParams, limitValue, offset]
5140
+ );
5141
+ return {
5142
+ experiments: (rows || []).map((row) => this.transformExperimentRow(row)),
5143
+ pagination: {
5144
+ total,
5145
+ page,
5146
+ perPage: perPageForResponse,
5147
+ hasMore: perPageInput === false ? false : offset + perPage < total
5148
+ }
5149
+ };
5150
+ } catch (error) {
5151
+ throw new MastraError(
5152
+ {
5153
+ id: createStorageErrorId("PG", "LIST_EXPERIMENTS", "FAILED"),
5154
+ domain: ErrorDomain.STORAGE,
5155
+ category: ErrorCategory.THIRD_PARTY
5156
+ },
5157
+ error
5158
+ );
5159
+ }
5160
+ }
5161
+ async deleteExperiment({ id }) {
5162
+ try {
5163
+ const resultsTable = getTableName2({
5164
+ indexName: TABLE_EXPERIMENT_RESULTS,
5165
+ schemaName: getSchemaName2(this.#schema)
5166
+ });
5167
+ const experimentsTable = getTableName2({ indexName: TABLE_EXPERIMENTS, schemaName: getSchemaName2(this.#schema) });
5168
+ await this.#db.client.none(`DELETE FROM ${resultsTable} WHERE "experimentId" = $1`, [id]);
5169
+ await this.#db.client.none(`DELETE FROM ${experimentsTable} WHERE "id" = $1`, [id]);
5170
+ } catch (error) {
5171
+ throw new MastraError(
5172
+ {
5173
+ id: createStorageErrorId("PG", "DELETE_EXPERIMENT", "FAILED"),
5174
+ domain: ErrorDomain.STORAGE,
5175
+ category: ErrorCategory.THIRD_PARTY
5176
+ },
5177
+ error
5178
+ );
5179
+ }
5180
+ }
5181
+ // --- Experiment results ---
5182
+ async addExperimentResult(input) {
5183
+ try {
5184
+ const id = input.id ?? crypto.randomUUID();
5185
+ const now = /* @__PURE__ */ new Date();
5186
+ const nowIso = now.toISOString();
5187
+ await this.#db.insert({
5188
+ tableName: TABLE_EXPERIMENT_RESULTS,
5189
+ record: {
5190
+ id,
5191
+ experimentId: input.experimentId,
5192
+ itemId: input.itemId,
5193
+ itemDatasetVersion: input.itemDatasetVersion ?? null,
5194
+ input: input.input,
5195
+ output: input.output ?? null,
5196
+ groundTruth: input.groundTruth ?? null,
5197
+ error: input.error ?? null,
5198
+ startedAt: input.startedAt.toISOString(),
5199
+ completedAt: input.completedAt.toISOString(),
5200
+ retryCount: input.retryCount,
5201
+ traceId: input.traceId ?? null,
5202
+ createdAt: nowIso
5203
+ }
5204
+ });
5205
+ return {
5206
+ id,
5207
+ experimentId: input.experimentId,
5208
+ itemId: input.itemId,
5209
+ itemDatasetVersion: input.itemDatasetVersion ?? null,
5210
+ input: input.input,
5211
+ output: input.output ?? null,
5212
+ groundTruth: input.groundTruth ?? null,
5213
+ error: input.error ?? null,
5214
+ startedAt: input.startedAt,
5215
+ completedAt: input.completedAt,
5216
+ retryCount: input.retryCount,
5217
+ traceId: input.traceId ?? null,
5218
+ createdAt: now
5219
+ };
5220
+ } catch (error) {
5221
+ throw new MastraError(
5222
+ {
5223
+ id: createStorageErrorId("PG", "ADD_EXPERIMENT_RESULT", "FAILED"),
5224
+ domain: ErrorDomain.STORAGE,
5225
+ category: ErrorCategory.THIRD_PARTY
5226
+ },
5227
+ error
5228
+ );
5229
+ }
5230
+ }
5231
+ async getExperimentResultById({ id }) {
5232
+ try {
5233
+ const tableName = getTableName2({ indexName: TABLE_EXPERIMENT_RESULTS, schemaName: getSchemaName2(this.#schema) });
5234
+ const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1`, [id]);
5235
+ return result ? this.transformExperimentResultRow(result) : null;
5236
+ } catch (error) {
5237
+ throw new MastraError(
5238
+ {
5239
+ id: createStorageErrorId("PG", "GET_EXPERIMENT_RESULT", "FAILED"),
5240
+ domain: ErrorDomain.STORAGE,
5241
+ category: ErrorCategory.THIRD_PARTY
5242
+ },
5243
+ error
5244
+ );
5245
+ }
5246
+ }
5247
+ async listExperimentResults(args) {
5248
+ try {
5249
+ const { page, perPage: perPageInput } = args.pagination;
5250
+ const tableName = getTableName2({ indexName: TABLE_EXPERIMENT_RESULTS, schemaName: getSchemaName2(this.#schema) });
5251
+ const countResult = await this.#db.client.one(
5252
+ `SELECT COUNT(*) as count FROM ${tableName} WHERE "experimentId" = $1`,
5253
+ [args.experimentId]
5254
+ );
5255
+ const total = parseInt(countResult.count, 10);
5256
+ if (total === 0) {
5257
+ return { results: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
5258
+ }
5259
+ const perPage = normalizePerPage(perPageInput, 100);
5260
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
5261
+ const limitValue = perPageInput === false ? total : perPage;
5262
+ const rows = await this.#db.client.manyOrNone(
5263
+ `SELECT * FROM ${tableName} WHERE "experimentId" = $1 ORDER BY "startedAt" ASC LIMIT $2 OFFSET $3`,
5264
+ [args.experimentId, limitValue, offset]
5265
+ );
5266
+ return {
5267
+ results: (rows || []).map((row) => this.transformExperimentResultRow(row)),
5268
+ pagination: {
5269
+ total,
5270
+ page,
5271
+ perPage: perPageForResponse,
5272
+ hasMore: perPageInput === false ? false : offset + perPage < total
5273
+ }
5274
+ };
5275
+ } catch (error) {
5276
+ throw new MastraError(
5277
+ {
5278
+ id: createStorageErrorId("PG", "LIST_EXPERIMENT_RESULTS", "FAILED"),
5279
+ domain: ErrorDomain.STORAGE,
5280
+ category: ErrorCategory.THIRD_PARTY
5281
+ },
5282
+ error
5283
+ );
5284
+ }
5285
+ }
5286
+ async deleteExperimentResults({ experimentId }) {
5287
+ try {
5288
+ const tableName = getTableName2({ indexName: TABLE_EXPERIMENT_RESULTS, schemaName: getSchemaName2(this.#schema) });
5289
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE "experimentId" = $1`, [experimentId]);
5290
+ } catch (error) {
5291
+ throw new MastraError(
5292
+ {
5293
+ id: createStorageErrorId("PG", "DELETE_EXPERIMENT_RESULTS", "FAILED"),
5294
+ domain: ErrorDomain.STORAGE,
5295
+ category: ErrorCategory.THIRD_PARTY
5296
+ },
5297
+ error
5298
+ );
5299
+ }
5300
+ }
5301
+ // --- Clear ---
5302
+ async dangerouslyClearAll() {
5303
+ await this.#db.clearTable({ tableName: TABLE_EXPERIMENT_RESULTS });
5304
+ await this.#db.clearTable({ tableName: TABLE_EXPERIMENTS });
5305
+ }
5306
+ };
5307
+ var SNAPSHOT_FIELDS = ["name", "description", "servers"];
5308
+ var MCPClientsPG = class _MCPClientsPG extends MCPClientsStorage {
5309
+ #db;
5310
+ #schema;
5311
+ #skipDefaultIndexes;
5312
+ #indexes;
5313
+ static MANAGED_TABLES = [TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS];
5314
+ constructor(config) {
5315
+ super();
5316
+ const { client, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
5317
+ this.#db = new PgDB({ client, schemaName, skipDefaultIndexes });
5318
+ this.#schema = schemaName || "public";
5319
+ this.#skipDefaultIndexes = skipDefaultIndexes;
5320
+ this.#indexes = indexes?.filter((idx) => _MCPClientsPG.MANAGED_TABLES.includes(idx.table));
5321
+ }
5322
+ getDefaultIndexDefinitions() {
5323
+ return [
5324
+ {
5325
+ name: "idx_mcp_client_versions_client_version",
5326
+ table: TABLE_MCP_CLIENT_VERSIONS,
5327
+ columns: ["mcpClientId", "versionNumber"],
5328
+ unique: true
5329
+ }
5330
+ ];
5331
+ }
5332
+ async createDefaultIndexes() {
5333
+ if (this.#skipDefaultIndexes) {
5334
+ return;
5335
+ }
5336
+ for (const indexDef of this.getDefaultIndexDefinitions()) {
5337
+ try {
5338
+ await this.#db.createIndex(indexDef);
5339
+ } catch {
5340
+ }
5341
+ }
5342
+ }
5343
+ async init() {
5344
+ await this.#db.createTable({
5345
+ tableName: TABLE_MCP_CLIENTS,
5346
+ schema: TABLE_SCHEMAS[TABLE_MCP_CLIENTS]
5347
+ });
5348
+ await this.#db.createTable({
5349
+ tableName: TABLE_MCP_CLIENT_VERSIONS,
5350
+ schema: TABLE_SCHEMAS[TABLE_MCP_CLIENT_VERSIONS]
5351
+ });
5352
+ await this.createDefaultIndexes();
5353
+ await this.createCustomIndexes();
5354
+ }
5355
+ async createCustomIndexes() {
5356
+ if (!this.#indexes || this.#indexes.length === 0) {
5357
+ return;
5358
+ }
5359
+ for (const indexDef of this.#indexes) {
5360
+ try {
5361
+ await this.#db.createIndex(indexDef);
5362
+ } catch (error) {
5363
+ this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
5364
+ }
5365
+ }
5366
+ }
5367
+ async dangerouslyClearAll() {
5368
+ await this.#db.clearTable({ tableName: TABLE_MCP_CLIENT_VERSIONS });
5369
+ await this.#db.clearTable({ tableName: TABLE_MCP_CLIENTS });
5370
+ }
5371
+ // ==========================================================================
5372
+ // MCP Client CRUD Methods
5373
+ // ==========================================================================
5374
+ async getById(id) {
5375
+ try {
5376
+ const tableName = getTableName2({ indexName: TABLE_MCP_CLIENTS, schemaName: getSchemaName2(this.#schema) });
5377
+ const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [id]);
5378
+ if (!result) {
5379
+ return null;
5380
+ }
5381
+ return this.parseMCPClientRow(result);
5382
+ } catch (error) {
5383
+ if (error instanceof MastraError) throw error;
5384
+ throw new MastraError(
5385
+ {
5386
+ id: createStorageErrorId("PG", "GET_MCP_CLIENT_BY_ID", "FAILED"),
5387
+ domain: ErrorDomain.STORAGE,
5388
+ category: ErrorCategory.THIRD_PARTY,
5389
+ details: { mcpClientId: id }
5390
+ },
5391
+ error
5392
+ );
5393
+ }
5394
+ }
5395
+ async create(input) {
5396
+ const { mcpClient } = input;
5397
+ try {
5398
+ const tableName = getTableName2({ indexName: TABLE_MCP_CLIENTS, schemaName: getSchemaName2(this.#schema) });
5399
+ const now = /* @__PURE__ */ new Date();
5400
+ const nowIso = now.toISOString();
5401
+ await this.#db.client.none(
5402
+ `INSERT INTO ${tableName} (
5403
+ id, status, "activeVersionId", "authorId", metadata,
5404
+ "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
5405
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
5406
+ [
5407
+ mcpClient.id,
5408
+ "draft",
5409
+ null,
5410
+ mcpClient.authorId ?? null,
5411
+ mcpClient.metadata ? JSON.stringify(mcpClient.metadata) : null,
5412
+ nowIso,
5413
+ nowIso,
5414
+ nowIso,
5415
+ nowIso
5416
+ ]
5417
+ );
5418
+ const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = mcpClient;
5419
+ const versionId = crypto.randomUUID();
5420
+ await this.createVersion({
5421
+ id: versionId,
5422
+ mcpClientId: mcpClient.id,
5423
+ versionNumber: 1,
5424
+ ...snapshotConfig,
5425
+ changedFields: [...SNAPSHOT_FIELDS],
5426
+ changeMessage: "Initial version"
5427
+ });
5428
+ return {
5429
+ id: mcpClient.id,
5430
+ status: "draft",
5431
+ activeVersionId: void 0,
5432
+ authorId: mcpClient.authorId,
5433
+ metadata: mcpClient.metadata,
5434
+ createdAt: now,
5435
+ updatedAt: now
5436
+ };
5437
+ } catch (error) {
5438
+ try {
5439
+ const tableName = getTableName2({
5440
+ indexName: TABLE_MCP_CLIENTS,
5441
+ schemaName: getSchemaName2(this.#schema)
5442
+ });
5443
+ await this.#db.client.none(
5444
+ `DELETE FROM ${tableName} WHERE id = $1 AND status = 'draft' AND "activeVersionId" IS NULL`,
5445
+ [mcpClient.id]
5446
+ );
5447
+ } catch {
5448
+ }
5449
+ if (error instanceof MastraError) throw error;
5450
+ throw new MastraError(
5451
+ {
5452
+ id: createStorageErrorId("PG", "CREATE_MCP_CLIENT", "FAILED"),
5453
+ domain: ErrorDomain.STORAGE,
5454
+ category: ErrorCategory.THIRD_PARTY,
5455
+ details: { mcpClientId: mcpClient.id }
5456
+ },
5457
+ error
5458
+ );
5459
+ }
5460
+ }
5461
+ async update(input) {
5462
+ const { id, ...updates } = input;
5463
+ try {
5464
+ const tableName = getTableName2({ indexName: TABLE_MCP_CLIENTS, schemaName: getSchemaName2(this.#schema) });
5465
+ const existingClient = await this.getById(id);
5466
+ if (!existingClient) {
5467
+ throw new MastraError({
5468
+ id: createStorageErrorId("PG", "UPDATE_MCP_CLIENT", "NOT_FOUND"),
5469
+ domain: ErrorDomain.STORAGE,
5470
+ category: ErrorCategory.USER,
5471
+ text: `MCP client ${id} not found`,
5472
+ details: { mcpClientId: id }
5473
+ });
5474
+ }
5475
+ const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
5476
+ let versionCreated = false;
5477
+ const hasConfigUpdate = SNAPSHOT_FIELDS.some((field) => field in configFields);
5478
+ if (hasConfigUpdate) {
5479
+ const latestVersion = await this.getLatestVersion(id);
5480
+ if (!latestVersion) {
5481
+ throw new MastraError({
5482
+ id: createStorageErrorId("PG", "UPDATE_MCP_CLIENT", "NO_VERSIONS"),
5483
+ domain: ErrorDomain.STORAGE,
5484
+ category: ErrorCategory.SYSTEM,
5485
+ text: `No versions found for MCP client ${id}`,
5486
+ details: { mcpClientId: id }
5487
+ });
5488
+ }
5489
+ const {
5490
+ id: _versionId,
5491
+ mcpClientId: _mcpClientId,
5492
+ versionNumber: _versionNumber,
5493
+ changedFields: _changedFields,
5494
+ changeMessage: _changeMessage,
5495
+ createdAt: _createdAt,
5496
+ ...latestConfig
5497
+ } = latestVersion;
5498
+ const newConfig = { ...latestConfig, ...configFields };
5499
+ const changedFields = SNAPSHOT_FIELDS.filter(
5500
+ (field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
5501
+ );
5502
+ if (changedFields.length > 0) {
5503
+ versionCreated = true;
5504
+ const newVersionId = crypto.randomUUID();
5505
+ await this.createVersion({
5506
+ id: newVersionId,
5507
+ mcpClientId: id,
5508
+ versionNumber: latestVersion.versionNumber + 1,
5509
+ ...newConfig,
5510
+ changedFields: [...changedFields],
5511
+ changeMessage: `Updated ${changedFields.join(", ")}`
5512
+ });
5513
+ }
5514
+ }
5515
+ const setClauses = [];
5516
+ const values = [];
5517
+ let paramIndex = 1;
5518
+ if (authorId !== void 0) {
5519
+ setClauses.push(`"authorId" = $${paramIndex++}`);
5520
+ values.push(authorId);
5521
+ }
5522
+ if (activeVersionId !== void 0) {
5523
+ setClauses.push(`"activeVersionId" = $${paramIndex++}`);
5524
+ values.push(activeVersionId);
5525
+ if (status === void 0) {
5526
+ setClauses.push(`status = $${paramIndex++}`);
5527
+ values.push("published");
5528
+ }
5529
+ }
5530
+ if (status !== void 0) {
5531
+ setClauses.push(`status = $${paramIndex++}`);
5532
+ values.push(status);
5533
+ }
5534
+ if (metadata !== void 0) {
5535
+ const mergedMetadata = { ...existingClient.metadata || {}, ...metadata };
5536
+ setClauses.push(`metadata = $${paramIndex++}`);
5537
+ values.push(JSON.stringify(mergedMetadata));
5538
+ }
5539
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5540
+ setClauses.push(`"updatedAt" = $${paramIndex++}`);
5541
+ values.push(now);
5542
+ setClauses.push(`"updatedAtZ" = $${paramIndex++}`);
5543
+ values.push(now);
5544
+ values.push(id);
5545
+ if (setClauses.length > 2 || versionCreated) {
5546
+ await this.#db.client.none(
5547
+ `UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE id = $${paramIndex}`,
5548
+ values
5549
+ );
5550
+ }
5551
+ const updatedClient = await this.getById(id);
5552
+ if (!updatedClient) {
5553
+ throw new MastraError({
5554
+ id: createStorageErrorId("PG", "UPDATE_MCP_CLIENT", "NOT_FOUND_AFTER_UPDATE"),
5555
+ domain: ErrorDomain.STORAGE,
5556
+ category: ErrorCategory.SYSTEM,
5557
+ text: `MCP client ${id} not found after update`,
5558
+ details: { mcpClientId: id }
5559
+ });
5560
+ }
5561
+ return updatedClient;
5562
+ } catch (error) {
5563
+ if (error instanceof MastraError) throw error;
5564
+ throw new MastraError(
5565
+ {
5566
+ id: createStorageErrorId("PG", "UPDATE_MCP_CLIENT", "FAILED"),
5567
+ domain: ErrorDomain.STORAGE,
5568
+ category: ErrorCategory.THIRD_PARTY,
5569
+ details: { mcpClientId: id }
5570
+ },
5571
+ error
5572
+ );
5573
+ }
5574
+ }
5575
+ async delete(id) {
5576
+ try {
5577
+ const tableName = getTableName2({ indexName: TABLE_MCP_CLIENTS, schemaName: getSchemaName2(this.#schema) });
5578
+ await this.deleteVersionsByParentId(id);
5579
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE id = $1`, [id]);
5580
+ } catch (error) {
5581
+ if (error instanceof MastraError) throw error;
5582
+ throw new MastraError(
5583
+ {
5584
+ id: createStorageErrorId("PG", "DELETE_MCP_CLIENT", "FAILED"),
5585
+ domain: ErrorDomain.STORAGE,
5586
+ category: ErrorCategory.THIRD_PARTY,
5587
+ details: { mcpClientId: id }
5588
+ },
5589
+ error
5590
+ );
5591
+ }
5592
+ }
5593
+ async list(args) {
5594
+ const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
5595
+ const { field, direction } = this.parseOrderBy(orderBy);
5596
+ if (page < 0) {
5597
+ throw new MastraError(
5598
+ {
5599
+ id: createStorageErrorId("PG", "LIST_MCP_CLIENTS", "INVALID_PAGE"),
5600
+ domain: ErrorDomain.STORAGE,
5601
+ category: ErrorCategory.USER,
5602
+ details: { page }
5603
+ },
5604
+ new Error("page must be >= 0")
5605
+ );
5606
+ }
5607
+ const perPage = normalizePerPage(perPageInput, 100);
5608
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
5609
+ try {
5610
+ const tableName = getTableName2({ indexName: TABLE_MCP_CLIENTS, schemaName: getSchemaName2(this.#schema) });
5611
+ const conditions = [];
5612
+ const queryParams = [];
5613
+ let paramIdx = 1;
5614
+ if (authorId !== void 0) {
5615
+ conditions.push(`"authorId" = $${paramIdx++}`);
5616
+ queryParams.push(authorId);
5617
+ }
5618
+ if (metadata && Object.keys(metadata).length > 0) {
5619
+ conditions.push(`metadata @> $${paramIdx++}::jsonb`);
5620
+ queryParams.push(JSON.stringify(metadata));
5621
+ }
5622
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
5623
+ const countResult = await this.#db.client.one(
5624
+ `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`,
5625
+ queryParams
5626
+ );
3627
5627
  const total = parseInt(countResult.count, 10);
3628
5628
  if (total === 0) {
3629
5629
  return {
3630
- agents: [],
5630
+ mcpClients: [],
3631
5631
  total: 0,
3632
5632
  page,
3633
5633
  perPage: perPageForResponse,
@@ -3636,12 +5636,12 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3636
5636
  }
3637
5637
  const limitValue = perPageInput === false ? total : perPage;
3638
5638
  const dataResult = await this.#db.client.manyOrNone(
3639
- `SELECT * FROM ${tableName} ORDER BY "${field}" ${direction} LIMIT $1 OFFSET $2`,
3640
- [limitValue, offset]
5639
+ `SELECT * FROM ${tableName} ${whereClause} ORDER BY "${field}" ${direction} LIMIT $${paramIdx++} OFFSET $${paramIdx++}`,
5640
+ [...queryParams, limitValue, offset]
3641
5641
  );
3642
- const agents = (dataResult || []).map((row) => this.parseRow(row));
5642
+ const mcpClients = (dataResult || []).map((row) => this.parseMCPClientRow(row));
3643
5643
  return {
3644
- agents,
5644
+ mcpClients,
3645
5645
  total,
3646
5646
  page,
3647
5647
  perPage: perPageForResponse,
@@ -3651,7 +5651,7 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3651
5651
  if (error instanceof MastraError) throw error;
3652
5652
  throw new MastraError(
3653
5653
  {
3654
- id: createStorageErrorId("PG", "LIST_AGENTS", "FAILED"),
5654
+ id: createStorageErrorId("PG", "LIST_MCP_CLIENTS", "FAILED"),
3655
5655
  domain: ErrorDomain.STORAGE,
3656
5656
  category: ErrorCategory.THIRD_PARTY
3657
5657
  },
@@ -3660,39 +5660,30 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3660
5660
  }
3661
5661
  }
3662
5662
  // ==========================================================================
3663
- // Agent Version Methods
5663
+ // MCP Client Version Methods
3664
5664
  // ==========================================================================
3665
5665
  async createVersion(input) {
3666
5666
  try {
3667
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
5667
+ const tableName = getTableName2({
5668
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5669
+ schemaName: getSchemaName2(this.#schema)
5670
+ });
3668
5671
  const now = /* @__PURE__ */ new Date();
3669
5672
  const nowIso = now.toISOString();
3670
5673
  await this.#db.client.none(
3671
5674
  `INSERT INTO ${tableName} (
3672
- id, "agentId", "versionNumber",
3673
- name, description, instructions, model, tools,
3674
- "defaultOptions", workflows, agents, "integrationTools",
3675
- "inputProcessors", "outputProcessors", memory, scorers,
5675
+ id, "mcpClientId", "versionNumber",
5676
+ name, description, servers,
3676
5677
  "changedFields", "changeMessage",
3677
5678
  "createdAt", "createdAtZ"
3678
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)`,
5679
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
3679
5680
  [
3680
5681
  input.id,
3681
- input.agentId,
5682
+ input.mcpClientId,
3682
5683
  input.versionNumber,
3683
5684
  input.name,
3684
5685
  input.description ?? null,
3685
- this.serializeInstructions(input.instructions),
3686
- JSON.stringify(input.model),
3687
- input.tools ? JSON.stringify(input.tools) : null,
3688
- input.defaultOptions ? JSON.stringify(input.defaultOptions) : null,
3689
- input.workflows ? JSON.stringify(input.workflows) : null,
3690
- input.agents ? JSON.stringify(input.agents) : null,
3691
- input.integrationTools ? JSON.stringify(input.integrationTools) : null,
3692
- input.inputProcessors ? JSON.stringify(input.inputProcessors) : null,
3693
- input.outputProcessors ? JSON.stringify(input.outputProcessors) : null,
3694
- input.memory ? JSON.stringify(input.memory) : null,
3695
- input.scorers ? JSON.stringify(input.scorers) : null,
5686
+ JSON.stringify(input.servers),
3696
5687
  input.changedFields ? JSON.stringify(input.changedFields) : null,
3697
5688
  input.changeMessage ?? null,
3698
5689
  nowIso,
@@ -3707,10 +5698,10 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3707
5698
  if (error instanceof MastraError) throw error;
3708
5699
  throw new MastraError(
3709
5700
  {
3710
- id: createStorageErrorId("PG", "CREATE_VERSION", "FAILED"),
5701
+ id: createStorageErrorId("PG", "CREATE_MCP_CLIENT_VERSION", "FAILED"),
3711
5702
  domain: ErrorDomain.STORAGE,
3712
5703
  category: ErrorCategory.THIRD_PARTY,
3713
- details: { versionId: input.id, agentId: input.agentId }
5704
+ details: { versionId: input.id, mcpClientId: input.mcpClientId }
3714
5705
  },
3715
5706
  error
3716
5707
  );
@@ -3718,7 +5709,10 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3718
5709
  }
3719
5710
  async getVersion(id) {
3720
5711
  try {
3721
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
5712
+ const tableName = getTableName2({
5713
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5714
+ schemaName: getSchemaName2(this.#schema)
5715
+ });
3722
5716
  const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [id]);
3723
5717
  if (!result) {
3724
5718
  return null;
@@ -3728,7 +5722,7 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3728
5722
  if (error instanceof MastraError) throw error;
3729
5723
  throw new MastraError(
3730
5724
  {
3731
- id: createStorageErrorId("PG", "GET_VERSION", "FAILED"),
5725
+ id: createStorageErrorId("PG", "GET_MCP_CLIENT_VERSION", "FAILED"),
3732
5726
  domain: ErrorDomain.STORAGE,
3733
5727
  category: ErrorCategory.THIRD_PARTY,
3734
5728
  details: { versionId: id }
@@ -3737,12 +5731,15 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3737
5731
  );
3738
5732
  }
3739
5733
  }
3740
- async getVersionByNumber(agentId, versionNumber) {
5734
+ async getVersionByNumber(mcpClientId, versionNumber) {
3741
5735
  try {
3742
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
5736
+ const tableName = getTableName2({
5737
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5738
+ schemaName: getSchemaName2(this.#schema)
5739
+ });
3743
5740
  const result = await this.#db.client.oneOrNone(
3744
- `SELECT * FROM ${tableName} WHERE "agentId" = $1 AND "versionNumber" = $2`,
3745
- [agentId, versionNumber]
5741
+ `SELECT * FROM ${tableName} WHERE "mcpClientId" = $1 AND "versionNumber" = $2`,
5742
+ [mcpClientId, versionNumber]
3746
5743
  );
3747
5744
  if (!result) {
3748
5745
  return null;
@@ -3752,21 +5749,24 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3752
5749
  if (error instanceof MastraError) throw error;
3753
5750
  throw new MastraError(
3754
5751
  {
3755
- id: createStorageErrorId("PG", "GET_VERSION_BY_NUMBER", "FAILED"),
5752
+ id: createStorageErrorId("PG", "GET_MCP_CLIENT_VERSION_BY_NUMBER", "FAILED"),
3756
5753
  domain: ErrorDomain.STORAGE,
3757
5754
  category: ErrorCategory.THIRD_PARTY,
3758
- details: { agentId, versionNumber }
5755
+ details: { mcpClientId, versionNumber }
3759
5756
  },
3760
5757
  error
3761
5758
  );
3762
5759
  }
3763
5760
  }
3764
- async getLatestVersion(agentId) {
5761
+ async getLatestVersion(mcpClientId) {
3765
5762
  try {
3766
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
5763
+ const tableName = getTableName2({
5764
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5765
+ schemaName: getSchemaName2(this.#schema)
5766
+ });
3767
5767
  const result = await this.#db.client.oneOrNone(
3768
- `SELECT * FROM ${tableName} WHERE "agentId" = $1 ORDER BY "versionNumber" DESC LIMIT 1`,
3769
- [agentId]
5768
+ `SELECT * FROM ${tableName} WHERE "mcpClientId" = $1 ORDER BY "versionNumber" DESC LIMIT 1`,
5769
+ [mcpClientId]
3770
5770
  );
3771
5771
  if (!result) {
3772
5772
  return null;
@@ -3776,21 +5776,21 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3776
5776
  if (error instanceof MastraError) throw error;
3777
5777
  throw new MastraError(
3778
5778
  {
3779
- id: createStorageErrorId("PG", "GET_LATEST_VERSION", "FAILED"),
5779
+ id: createStorageErrorId("PG", "GET_LATEST_MCP_CLIENT_VERSION", "FAILED"),
3780
5780
  domain: ErrorDomain.STORAGE,
3781
5781
  category: ErrorCategory.THIRD_PARTY,
3782
- details: { agentId }
5782
+ details: { mcpClientId }
3783
5783
  },
3784
5784
  error
3785
5785
  );
3786
5786
  }
3787
5787
  }
3788
5788
  async listVersions(input) {
3789
- const { agentId, page = 0, perPage: perPageInput, orderBy } = input;
5789
+ const { mcpClientId, page = 0, perPage: perPageInput, orderBy } = input;
3790
5790
  if (page < 0) {
3791
5791
  throw new MastraError(
3792
5792
  {
3793
- id: createStorageErrorId("PG", "LIST_VERSIONS", "INVALID_PAGE"),
5793
+ id: createStorageErrorId("PG", "LIST_MCP_CLIENT_VERSIONS", "INVALID_PAGE"),
3794
5794
  domain: ErrorDomain.STORAGE,
3795
5795
  category: ErrorCategory.USER,
3796
5796
  details: { page }
@@ -3802,10 +5802,14 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3802
5802
  const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
3803
5803
  try {
3804
5804
  const { field, direction } = this.parseVersionOrderBy(orderBy);
3805
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3806
- const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "agentId" = $1`, [
3807
- agentId
3808
- ]);
5805
+ const tableName = getTableName2({
5806
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5807
+ schemaName: getSchemaName2(this.#schema)
5808
+ });
5809
+ const countResult = await this.#db.client.one(
5810
+ `SELECT COUNT(*) as count FROM ${tableName} WHERE "mcpClientId" = $1`,
5811
+ [mcpClientId]
5812
+ );
3809
5813
  const total = parseInt(countResult.count, 10);
3810
5814
  if (total === 0) {
3811
5815
  return {
@@ -3818,8 +5822,8 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3818
5822
  }
3819
5823
  const limitValue = perPageInput === false ? total : perPage;
3820
5824
  const dataResult = await this.#db.client.manyOrNone(
3821
- `SELECT * FROM ${tableName} WHERE "agentId" = $1 ORDER BY "${field}" ${direction} LIMIT $2 OFFSET $3`,
3822
- [agentId, limitValue, offset]
5825
+ `SELECT * FROM ${tableName} WHERE "mcpClientId" = $1 ORDER BY "${field}" ${direction} LIMIT $2 OFFSET $3`,
5826
+ [mcpClientId, limitValue, offset]
3823
5827
  );
3824
5828
  const versions = (dataResult || []).map((row) => this.parseVersionRow(row));
3825
5829
  return {
@@ -3833,10 +5837,10 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3833
5837
  if (error instanceof MastraError) throw error;
3834
5838
  throw new MastraError(
3835
5839
  {
3836
- id: createStorageErrorId("PG", "LIST_VERSIONS", "FAILED"),
5840
+ id: createStorageErrorId("PG", "LIST_MCP_CLIENT_VERSIONS", "FAILED"),
3837
5841
  domain: ErrorDomain.STORAGE,
3838
5842
  category: ErrorCategory.THIRD_PARTY,
3839
- details: { agentId }
5843
+ details: { mcpClientId }
3840
5844
  },
3841
5845
  error
3842
5846
  );
@@ -3844,13 +5848,16 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3844
5848
  }
3845
5849
  async deleteVersion(id) {
3846
5850
  try {
3847
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
5851
+ const tableName = getTableName2({
5852
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5853
+ schemaName: getSchemaName2(this.#schema)
5854
+ });
3848
5855
  await this.#db.client.none(`DELETE FROM ${tableName} WHERE id = $1`, [id]);
3849
5856
  } catch (error) {
3850
5857
  if (error instanceof MastraError) throw error;
3851
5858
  throw new MastraError(
3852
5859
  {
3853
- id: createStorageErrorId("PG", "DELETE_VERSION", "FAILED"),
5860
+ id: createStorageErrorId("PG", "DELETE_MCP_CLIENT_VERSION", "FAILED"),
3854
5861
  domain: ErrorDomain.STORAGE,
3855
5862
  category: ErrorCategory.THIRD_PARTY,
3856
5863
  details: { versionId: id }
@@ -3861,36 +5868,42 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3861
5868
  }
3862
5869
  async deleteVersionsByParentId(entityId) {
3863
5870
  try {
3864
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3865
- await this.#db.client.none(`DELETE FROM ${tableName} WHERE "agentId" = $1`, [entityId]);
5871
+ const tableName = getTableName2({
5872
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5873
+ schemaName: getSchemaName2(this.#schema)
5874
+ });
5875
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE "mcpClientId" = $1`, [entityId]);
3866
5876
  } catch (error) {
3867
5877
  if (error instanceof MastraError) throw error;
3868
5878
  throw new MastraError(
3869
5879
  {
3870
- id: createStorageErrorId("PG", "DELETE_VERSIONS_BY_AGENT_ID", "FAILED"),
5880
+ id: createStorageErrorId("PG", "DELETE_MCP_CLIENT_VERSIONS_BY_MCP_CLIENT_ID", "FAILED"),
3871
5881
  domain: ErrorDomain.STORAGE,
3872
5882
  category: ErrorCategory.THIRD_PARTY,
3873
- details: { agentId: entityId }
5883
+ details: { mcpClientId: entityId }
3874
5884
  },
3875
5885
  error
3876
5886
  );
3877
5887
  }
3878
5888
  }
3879
- async countVersions(agentId) {
5889
+ async countVersions(mcpClientId) {
3880
5890
  try {
3881
- const tableName = getTableName2({ indexName: TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3882
- const result = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "agentId" = $1`, [
3883
- agentId
5891
+ const tableName = getTableName2({
5892
+ indexName: TABLE_MCP_CLIENT_VERSIONS,
5893
+ schemaName: getSchemaName2(this.#schema)
5894
+ });
5895
+ const result = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "mcpClientId" = $1`, [
5896
+ mcpClientId
3884
5897
  ]);
3885
5898
  return parseInt(result.count, 10);
3886
5899
  } catch (error) {
3887
5900
  if (error instanceof MastraError) throw error;
3888
5901
  throw new MastraError(
3889
5902
  {
3890
- id: createStorageErrorId("PG", "COUNT_VERSIONS", "FAILED"),
5903
+ id: createStorageErrorId("PG", "COUNT_MCP_CLIENT_VERSIONS", "FAILED"),
3891
5904
  domain: ErrorDomain.STORAGE,
3892
5905
  category: ErrorCategory.THIRD_PARTY,
3893
- details: { agentId }
5906
+ details: { mcpClientId }
3894
5907
  },
3895
5908
  error
3896
5909
  );
@@ -3899,44 +5912,63 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3899
5912
  // ==========================================================================
3900
5913
  // Private Helper Methods
3901
5914
  // ==========================================================================
3902
- serializeInstructions(instructions) {
3903
- if (instructions == null) return void 0;
3904
- return Array.isArray(instructions) ? JSON.stringify(instructions) : instructions;
3905
- }
3906
- deserializeInstructions(raw) {
3907
- if (!raw) return "";
5915
+ parseJson(value, fieldName) {
5916
+ if (!value) return void 0;
5917
+ if (typeof value !== "string") return value;
3908
5918
  try {
3909
- const parsed = JSON.parse(raw);
3910
- if (Array.isArray(parsed)) return parsed;
3911
- } catch {
5919
+ return JSON.parse(value);
5920
+ } catch (error) {
5921
+ if (error instanceof MastraError) throw error;
5922
+ const details = {
5923
+ value: value.length > 100 ? value.substring(0, 100) + "..." : value
5924
+ };
5925
+ if (fieldName) {
5926
+ details.field = fieldName;
5927
+ }
5928
+ throw new MastraError(
5929
+ {
5930
+ id: createStorageErrorId("PG", "PARSE_JSON", "INVALID_JSON"),
5931
+ domain: ErrorDomain.STORAGE,
5932
+ category: ErrorCategory.SYSTEM,
5933
+ text: `Failed to parse JSON${fieldName ? ` for field "${fieldName}"` : ""}: ${error instanceof Error ? error.message : "Unknown error"}`,
5934
+ details
5935
+ },
5936
+ error
5937
+ );
3912
5938
  }
3913
- return raw;
5939
+ }
5940
+ parseMCPClientRow(row) {
5941
+ return {
5942
+ id: row.id,
5943
+ status: row.status,
5944
+ activeVersionId: row.activeVersionId,
5945
+ authorId: row.authorId,
5946
+ metadata: this.parseJson(row.metadata, "metadata"),
5947
+ createdAt: new Date(row.createdAtZ || row.createdAt),
5948
+ updatedAt: new Date(row.updatedAtZ || row.updatedAt)
5949
+ };
3914
5950
  }
3915
5951
  parseVersionRow(row) {
3916
5952
  return {
3917
5953
  id: row.id,
3918
- agentId: row.agentId,
5954
+ mcpClientId: row.mcpClientId,
3919
5955
  versionNumber: row.versionNumber,
3920
5956
  name: row.name,
3921
5957
  description: row.description,
3922
- instructions: this.deserializeInstructions(row.instructions),
3923
- model: this.parseJson(row.model, "model"),
3924
- tools: this.parseJson(row.tools, "tools"),
3925
- defaultOptions: this.parseJson(row.defaultOptions, "defaultOptions"),
3926
- workflows: this.parseJson(row.workflows, "workflows"),
3927
- agents: this.parseJson(row.agents, "agents"),
3928
- integrationTools: this.parseJson(row.integrationTools, "integrationTools"),
3929
- inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
3930
- outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
3931
- memory: this.parseJson(row.memory, "memory"),
3932
- scorers: this.parseJson(row.scorers, "scorers"),
5958
+ servers: this.parseJson(row.servers, "servers"),
3933
5959
  changedFields: this.parseJson(row.changedFields, "changedFields"),
3934
5960
  changeMessage: row.changeMessage,
3935
- createdAt: row.createdAtZ || row.createdAt
5961
+ createdAt: new Date(row.createdAtZ || row.createdAt)
3936
5962
  };
3937
5963
  }
3938
5964
  };
3939
5965
  var OM_TABLE = "mastra_observational_memory";
5966
+ var _omTableSchema;
5967
+ try {
5968
+ const storage = __require("@mastra/core/storage");
5969
+ _omTableSchema = storage.OBSERVATIONAL_MEMORY_TABLE_SCHEMA;
5970
+ } catch {
5971
+ }
3940
5972
  function getSchemaName3(schema) {
3941
5973
  return schema ? `"${schema}"` : '"public"';
3942
5974
  }
@@ -4015,9 +6047,9 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4015
6047
  }
4016
6048
  /**
4017
6049
  * Returns default index definitions for the memory domain tables.
6050
+ * @param schemaPrefix - Prefix for index names (e.g. "my_schema_" or "")
4018
6051
  */
4019
- getDefaultIndexDefinitions() {
4020
- const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
6052
+ static getDefaultIndexDefs(schemaPrefix) {
4021
6053
  return [
4022
6054
  {
4023
6055
  name: `${schemaPrefix}mastra_threads_resourceid_createdat_idx`,
@@ -4031,6 +6063,53 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4031
6063
  }
4032
6064
  ];
4033
6065
  }
6066
+ /**
6067
+ * Returns all DDL statements for this domain: tables (threads, messages, resources, OM), indexes.
6068
+ * Used by exportSchemas to produce a complete, reproducible schema export.
6069
+ */
6070
+ static getExportDDL(schemaName) {
6071
+ const statements = [];
6072
+ const parsedSchema = schemaName ? parseSqlIdentifier(schemaName, "schema name") : "";
6073
+ const schemaPrefix = parsedSchema && parsedSchema !== "public" ? `${parsedSchema}_` : "";
6074
+ const quotedSchemaName = getSchemaName(schemaName);
6075
+ for (const tableName of [TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES]) {
6076
+ statements.push(
6077
+ generateTableSQL({
6078
+ tableName,
6079
+ schema: TABLE_SCHEMAS[tableName],
6080
+ schemaName,
6081
+ includeAllConstraints: true
6082
+ })
6083
+ );
6084
+ }
6085
+ const omSchema = _omTableSchema?.[OM_TABLE];
6086
+ if (omSchema) {
6087
+ statements.push(
6088
+ generateTableSQL({
6089
+ tableName: OM_TABLE,
6090
+ schema: omSchema,
6091
+ schemaName,
6092
+ includeAllConstraints: true
6093
+ })
6094
+ );
6095
+ const fullOmTableName = getTableName({ indexName: OM_TABLE, schemaName: quotedSchemaName });
6096
+ const idxPrefix = schemaPrefix ? `${schemaPrefix}` : "";
6097
+ statements.push(
6098
+ `CREATE INDEX IF NOT EXISTS "${idxPrefix}idx_om_lookup_key" ON ${fullOmTableName} ("lookupKey");`
6099
+ );
6100
+ }
6101
+ for (const idx of _MemoryPG.getDefaultIndexDefs(schemaPrefix)) {
6102
+ statements.push(generateIndexSQL(idx, schemaName));
6103
+ }
6104
+ return statements;
6105
+ }
6106
+ /**
6107
+ * Returns default index definitions for this instance's schema.
6108
+ */
6109
+ getDefaultIndexDefinitions() {
6110
+ const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
6111
+ return _MemoryPG.getDefaultIndexDefs(schemaPrefix);
6112
+ }
4034
6113
  /**
4035
6114
  * Creates default indexes for optimal query performance.
4036
6115
  */
@@ -5392,8 +7471,8 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5392
7471
  input.observations,
5393
7472
  lastObservedAtStr,
5394
7473
  lastObservedAtStr,
5395
- input.tokenCount,
5396
- input.tokenCount,
7474
+ Math.round(input.tokenCount),
7475
+ Math.round(input.tokenCount),
5397
7476
  observedMessageIdsJson,
5398
7477
  nowStr,
5399
7478
  nowStr,
@@ -5488,8 +7567,8 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5488
7567
  nowStr,
5489
7568
  // lastReflectionAtZ
5490
7569
  record.pendingMessageTokens,
5491
- record.totalTokensObserved,
5492
- record.observationTokenCount,
7570
+ Math.round(record.totalTokensObserved),
7571
+ Math.round(record.observationTokenCount),
5493
7572
  false,
5494
7573
  // isObserving
5495
7574
  false,
@@ -5607,7 +7686,7 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5607
7686
  let values;
5608
7687
  if (lastBufferedAtTokens !== void 0) {
5609
7688
  query = `UPDATE ${tableName} SET "isBufferingObservation" = $1, "lastBufferedAtTokens" = $2, "updatedAt" = $3, "updatedAtZ" = $4 WHERE id = $5`;
5610
- values = [isBuffering, lastBufferedAtTokens, nowStr, nowStr, id];
7689
+ values = [isBuffering, Math.round(lastBufferedAtTokens), nowStr, nowStr, id];
5611
7690
  } else {
5612
7691
  query = `UPDATE ${tableName} SET "isBufferingObservation" = $1, "updatedAt" = $2, "updatedAtZ" = $3 WHERE id = $4`;
5613
7692
  values = [isBuffering, nowStr, nowStr, id];
@@ -5705,7 +7784,7 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5705
7784
  "updatedAt" = $2,
5706
7785
  "updatedAtZ" = $3
5707
7786
  WHERE id = $4`,
5708
- [tokenCount, nowStr, nowStr, id]
7787
+ [Math.round(tokenCount), nowStr, nowStr, id]
5709
7788
  );
5710
7789
  if (result.rowCount === 0) {
5711
7790
  throw new MastraError({
@@ -5745,9 +7824,9 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5745
7824
  id: `ombuf-${randomUUID()}`,
5746
7825
  cycleId: input.chunk.cycleId,
5747
7826
  observations: input.chunk.observations,
5748
- tokenCount: input.chunk.tokenCount,
7827
+ tokenCount: Math.round(input.chunk.tokenCount),
5749
7828
  messageIds: input.chunk.messageIds,
5750
- messageTokens: input.chunk.messageTokens,
7829
+ messageTokens: Math.round(input.chunk.messageTokens ?? 0),
5751
7830
  lastObservedAt: input.chunk.lastObservedAt,
5752
7831
  createdAt: /* @__PURE__ */ new Date(),
5753
7832
  suggestedContinuation: input.chunk.suggestedContinuation,
@@ -5856,8 +7935,8 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5856
7935
  const activatedChunks = chunks.slice(0, chunksToActivate);
5857
7936
  const remainingChunks = chunks.slice(chunksToActivate);
5858
7937
  const activatedContent = activatedChunks.map((c) => c.observations).join("\n\n");
5859
- const activatedTokens = activatedChunks.reduce((sum, c) => sum + c.tokenCount, 0);
5860
- const activatedMessageTokens = activatedChunks.reduce((sum, c) => sum + (c.messageTokens ?? 0), 0);
7938
+ const activatedTokens = Math.round(activatedChunks.reduce((sum, c) => sum + c.tokenCount, 0));
7939
+ const activatedMessageTokens = Math.round(activatedChunks.reduce((sum, c) => sum + (c.messageTokens ?? 0), 0));
5861
7940
  const activatedMessageCount = activatedChunks.reduce((sum, c) => sum + c.messageIds.length, 0);
5862
7941
  const activatedCycleIds = activatedChunks.map((c) => c.cycleId).filter((id) => !!id);
5863
7942
  const activatedMessageIds = activatedChunks.flatMap((c) => c.messageIds ?? []);
@@ -5944,8 +8023,8 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
5944
8023
  WHERE id = $7`,
5945
8024
  [
5946
8025
  input.reflection,
5947
- input.tokenCount,
5948
- input.inputTokenCount,
8026
+ Math.round(input.tokenCount),
8027
+ Math.round(input.inputTokenCount),
5949
8028
  input.reflectedObservationLineCount,
5950
8029
  nowStr,
5951
8030
  nowStr,
@@ -6068,9 +8147,9 @@ var ObservabilityPG = class _ObservabilityPG extends ObservabilityStorage {
6068
8147
  }
6069
8148
  /**
6070
8149
  * Returns default index definitions for the observability domain tables.
8150
+ * @param schemaPrefix - Prefix for index names (e.g. "my_schema_" or "")
6071
8151
  */
6072
- getDefaultIndexDefinitions() {
6073
- const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
8152
+ static getDefaultIndexDefs(schemaPrefix) {
6074
8153
  return [
6075
8154
  {
6076
8155
  name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
@@ -6132,6 +8211,35 @@ var ObservabilityPG = class _ObservabilityPG extends ObservabilityStorage {
6132
8211
  }
6133
8212
  ];
6134
8213
  }
8214
+ /**
8215
+ * Returns all DDL statements for this domain: table, constraints, timestamp trigger, and indexes.
8216
+ * Used by exportSchemas to produce a complete, reproducible schema export.
8217
+ */
8218
+ static getExportDDL(schemaName) {
8219
+ const statements = [];
8220
+ const parsedSchema = schemaName ? parseSqlIdentifier(schemaName, "schema name") : "";
8221
+ const schemaPrefix = parsedSchema && parsedSchema !== "public" ? `${parsedSchema}_` : "";
8222
+ statements.push(
8223
+ generateTableSQL({
8224
+ tableName: TABLE_SPANS,
8225
+ schema: TABLE_SCHEMAS[TABLE_SPANS],
8226
+ schemaName,
8227
+ includeAllConstraints: true
8228
+ })
8229
+ );
8230
+ statements.push(generateTimestampTriggerSQL(TABLE_SPANS, schemaName));
8231
+ for (const idx of _ObservabilityPG.getDefaultIndexDefs(schemaPrefix)) {
8232
+ statements.push(generateIndexSQL(idx, schemaName));
8233
+ }
8234
+ return statements;
8235
+ }
8236
+ /**
8237
+ * Returns default index definitions for this instance's schema.
8238
+ */
8239
+ getDefaultIndexDefinitions() {
8240
+ const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
8241
+ return _ObservabilityPG.getDefaultIndexDefs(schemaPrefix);
8242
+ }
6135
8243
  /**
6136
8244
  * Creates default indexes for optimal query performance.
6137
8245
  */
@@ -6660,7 +8768,7 @@ var ObservabilityPG = class _ObservabilityPG extends ObservabilityStorage {
6660
8768
  }
6661
8769
  }
6662
8770
  };
6663
- var SNAPSHOT_FIELDS = ["name", "description", "content", "rules"];
8771
+ var SNAPSHOT_FIELDS2 = ["name", "description", "content", "rules"];
6664
8772
  var PromptBlocksPG = class _PromptBlocksPG extends PromptBlocksStorage {
6665
8773
  #db;
6666
8774
  #schema;
@@ -6675,16 +8783,47 @@ var PromptBlocksPG = class _PromptBlocksPG extends PromptBlocksStorage {
6675
8783
  this.#skipDefaultIndexes = skipDefaultIndexes;
6676
8784
  this.#indexes = indexes?.filter((idx) => _PromptBlocksPG.MANAGED_TABLES.includes(idx.table));
6677
8785
  }
6678
- getDefaultIndexDefinitions() {
8786
+ /**
8787
+ * Returns default index definitions for the prompt blocks domain tables.
8788
+ * @param schemaPrefix - Prefix for index names (e.g. "my_schema_" or "")
8789
+ */
8790
+ static getDefaultIndexDefs(schemaPrefix) {
6679
8791
  return [
6680
8792
  {
6681
- name: "idx_prompt_block_versions_block_version",
8793
+ name: `${schemaPrefix}idx_prompt_block_versions_block_version`,
6682
8794
  table: TABLE_PROMPT_BLOCK_VERSIONS,
6683
8795
  columns: ["blockId", "versionNumber"],
6684
8796
  unique: true
6685
8797
  }
6686
8798
  ];
6687
8799
  }
8800
+ /**
8801
+ * Returns all DDL statements for this domain: tables and indexes.
8802
+ * Used by exportSchemas to produce a complete, reproducible schema export.
8803
+ */
8804
+ static getExportDDL(schemaName) {
8805
+ const statements = [];
8806
+ const parsedSchema = schemaName ? parseSqlIdentifier(schemaName, "schema name") : "";
8807
+ const schemaPrefix = parsedSchema && parsedSchema !== "public" ? `${parsedSchema}_` : "";
8808
+ for (const tableName of _PromptBlocksPG.MANAGED_TABLES) {
8809
+ statements.push(
8810
+ generateTableSQL({
8811
+ tableName,
8812
+ schema: TABLE_SCHEMAS[tableName],
8813
+ schemaName,
8814
+ includeAllConstraints: true
8815
+ })
8816
+ );
8817
+ }
8818
+ for (const idx of _PromptBlocksPG.getDefaultIndexDefs(schemaPrefix)) {
8819
+ statements.push(generateIndexSQL(idx, schemaName));
8820
+ }
8821
+ return statements;
8822
+ }
8823
+ getDefaultIndexDefinitions() {
8824
+ const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
8825
+ return _PromptBlocksPG.getDefaultIndexDefs(schemaPrefix);
8826
+ }
6688
8827
  async createDefaultIndexes() {
6689
8828
  if (this.#skipDefaultIndexes) {
6690
8829
  return;
@@ -6775,7 +8914,7 @@ var PromptBlocksPG = class _PromptBlocksPG extends PromptBlocksStorage {
6775
8914
  blockId: promptBlock.id,
6776
8915
  versionNumber: 1,
6777
8916
  ...snapshotConfig,
6778
- changedFields: [...SNAPSHOT_FIELDS],
8917
+ changedFields: [...SNAPSHOT_FIELDS2],
6779
8918
  changeMessage: "Initial version"
6780
8919
  });
6781
8920
  return {
@@ -6824,7 +8963,7 @@ var PromptBlocksPG = class _PromptBlocksPG extends PromptBlocksStorage {
6824
8963
  }
6825
8964
  const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
6826
8965
  let versionCreated = false;
6827
- const hasConfigUpdate = SNAPSHOT_FIELDS.some((field) => field in configFields);
8966
+ const hasConfigUpdate = SNAPSHOT_FIELDS2.some((field) => field in configFields);
6828
8967
  if (hasConfigUpdate) {
6829
8968
  const latestVersion = await this.getLatestVersion(id);
6830
8969
  if (!latestVersion) {
@@ -6846,7 +8985,7 @@ var PromptBlocksPG = class _PromptBlocksPG extends PromptBlocksStorage {
6846
8985
  ...latestConfig
6847
8986
  } = latestVersion;
6848
8987
  const newConfig = { ...latestConfig, ...configFields };
6849
- const changedFields = SNAPSHOT_FIELDS.filter(
8988
+ const changedFields = SNAPSHOT_FIELDS2.filter(
6850
8989
  (field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
6851
8990
  );
6852
8991
  if (changedFields.length > 0) {
@@ -7312,7 +9451,7 @@ var PromptBlocksPG = class _PromptBlocksPG extends PromptBlocksStorage {
7312
9451
  };
7313
9452
  }
7314
9453
  };
7315
- var SNAPSHOT_FIELDS2 = [
9454
+ var SNAPSHOT_FIELDS3 = [
7316
9455
  "name",
7317
9456
  "description",
7318
9457
  "type",
@@ -7338,16 +9477,47 @@ var ScorerDefinitionsPG = class _ScorerDefinitionsPG extends ScorerDefinitionsSt
7338
9477
  (idx) => _ScorerDefinitionsPG.MANAGED_TABLES.includes(idx.table)
7339
9478
  );
7340
9479
  }
7341
- getDefaultIndexDefinitions() {
9480
+ /**
9481
+ * Returns default index definitions for the scorer definitions domain tables.
9482
+ * @param schemaPrefix - Prefix for index names (e.g. "my_schema_" or "")
9483
+ */
9484
+ static getDefaultIndexDefs(schemaPrefix) {
7342
9485
  return [
7343
9486
  {
7344
- name: "idx_scorer_definition_versions_def_version",
9487
+ name: `${schemaPrefix}idx_scorer_definition_versions_def_version`,
7345
9488
  table: TABLE_SCORER_DEFINITION_VERSIONS,
7346
9489
  columns: ["scorerDefinitionId", "versionNumber"],
7347
9490
  unique: true
7348
9491
  }
7349
9492
  ];
7350
9493
  }
9494
+ /**
9495
+ * Returns all DDL statements for this domain: tables and indexes.
9496
+ * Used by exportSchemas to produce a complete, reproducible schema export.
9497
+ */
9498
+ static getExportDDL(schemaName) {
9499
+ const statements = [];
9500
+ const parsedSchema = schemaName ? parseSqlIdentifier(schemaName, "schema name") : "";
9501
+ const schemaPrefix = parsedSchema && parsedSchema !== "public" ? `${parsedSchema}_` : "";
9502
+ for (const tableName of _ScorerDefinitionsPG.MANAGED_TABLES) {
9503
+ statements.push(
9504
+ generateTableSQL({
9505
+ tableName,
9506
+ schema: TABLE_SCHEMAS[tableName],
9507
+ schemaName,
9508
+ includeAllConstraints: true
9509
+ })
9510
+ );
9511
+ }
9512
+ for (const idx of _ScorerDefinitionsPG.getDefaultIndexDefs(schemaPrefix)) {
9513
+ statements.push(generateIndexSQL(idx, schemaName));
9514
+ }
9515
+ return statements;
9516
+ }
9517
+ getDefaultIndexDefinitions() {
9518
+ const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
9519
+ return _ScorerDefinitionsPG.getDefaultIndexDefs(schemaPrefix);
9520
+ }
7351
9521
  async createDefaultIndexes() {
7352
9522
  if (this.#skipDefaultIndexes) {
7353
9523
  return;
@@ -7441,7 +9611,7 @@ var ScorerDefinitionsPG = class _ScorerDefinitionsPG extends ScorerDefinitionsSt
7441
9611
  scorerDefinitionId: scorerDefinition.id,
7442
9612
  versionNumber: 1,
7443
9613
  ...snapshotConfig,
7444
- changedFields: [...SNAPSHOT_FIELDS2],
9614
+ changedFields: [...SNAPSHOT_FIELDS3],
7445
9615
  changeMessage: "Initial version"
7446
9616
  });
7447
9617
  return {
@@ -7493,7 +9663,7 @@ var ScorerDefinitionsPG = class _ScorerDefinitionsPG extends ScorerDefinitionsSt
7493
9663
  }
7494
9664
  const { authorId, activeVersionId, metadata, status, ...configFields } = updates;
7495
9665
  let versionCreated = false;
7496
- const hasConfigUpdate = SNAPSHOT_FIELDS2.some((field) => field in configFields);
9666
+ const hasConfigUpdate = SNAPSHOT_FIELDS3.some((field) => field in configFields);
7497
9667
  if (hasConfigUpdate) {
7498
9668
  const latestVersion = await this.getLatestVersion(id);
7499
9669
  if (!latestVersion) {
@@ -7515,7 +9685,7 @@ var ScorerDefinitionsPG = class _ScorerDefinitionsPG extends ScorerDefinitionsSt
7515
9685
  ...latestConfig
7516
9686
  } = latestVersion;
7517
9687
  const newConfig = { ...latestConfig, ...configFields };
7518
- const changedFields = SNAPSHOT_FIELDS2.filter(
9688
+ const changedFields = SNAPSHOT_FIELDS3.filter(
7519
9689
  (field) => field in configFields && JSON.stringify(configFields[field]) !== JSON.stringify(latestConfig[field])
7520
9690
  );
7521
9691
  if (changedFields.length > 0) {
@@ -8034,9 +10204,9 @@ var ScoresPG = class _ScoresPG extends ScoresStorage {
8034
10204
  }
8035
10205
  /**
8036
10206
  * Returns default index definitions for the scores domain tables.
10207
+ * @param schemaPrefix - Prefix for index names (e.g. "my_schema_" or "")
8037
10208
  */
8038
- getDefaultIndexDefinitions() {
8039
- const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
10209
+ static getDefaultIndexDefs(schemaPrefix) {
8040
10210
  return [
8041
10211
  {
8042
10212
  name: `${schemaPrefix}mastra_scores_trace_id_span_id_created_at_idx`,
@@ -8045,6 +10215,34 @@ var ScoresPG = class _ScoresPG extends ScoresStorage {
8045
10215
  }
8046
10216
  ];
8047
10217
  }
10218
+ /**
10219
+ * Returns all DDL statements for this domain: table and indexes.
10220
+ * Used by exportSchemas to produce a complete, reproducible schema export.
10221
+ */
10222
+ static getExportDDL(schemaName) {
10223
+ const statements = [];
10224
+ const parsedSchema = schemaName ? parseSqlIdentifier(schemaName, "schema name") : "";
10225
+ const schemaPrefix = parsedSchema && parsedSchema !== "public" ? `${parsedSchema}_` : "";
10226
+ statements.push(
10227
+ generateTableSQL({
10228
+ tableName: TABLE_SCORERS,
10229
+ schema: TABLE_SCHEMAS[TABLE_SCORERS],
10230
+ schemaName,
10231
+ includeAllConstraints: true
10232
+ })
10233
+ );
10234
+ for (const idx of _ScoresPG.getDefaultIndexDefs(schemaPrefix)) {
10235
+ statements.push(generateIndexSQL(idx, schemaName));
10236
+ }
10237
+ return statements;
10238
+ }
10239
+ /**
10240
+ * Returns default index definitions for this instance's schema.
10241
+ */
10242
+ getDefaultIndexDefinitions() {
10243
+ const schemaPrefix = this.#schema !== "public" ? `${this.#schema}_` : "";
10244
+ return _ScoresPG.getDefaultIndexDefs(schemaPrefix);
10245
+ }
8048
10246
  /**
8049
10247
  * Creates default indexes for optimal query performance.
8050
10248
  */
@@ -8416,6 +10614,22 @@ var WorkflowsPG = class _WorkflowsPG extends WorkflowsStorage {
8416
10614
  updatedAt: new Date(row.updatedAtZ || row.updatedAt)
8417
10615
  };
8418
10616
  }
10617
+ /**
10618
+ * Returns all DDL statements for this domain: table with unique constraint.
10619
+ * Used by exportSchemas to produce a complete, reproducible schema export.
10620
+ */
10621
+ static getExportDDL(schemaName) {
10622
+ const statements = [];
10623
+ statements.push(
10624
+ generateTableSQL({
10625
+ tableName: TABLE_WORKFLOW_SNAPSHOT,
10626
+ schema: TABLE_SCHEMAS[TABLE_WORKFLOW_SNAPSHOT],
10627
+ schemaName,
10628
+ includeAllConstraints: true
10629
+ })
10630
+ );
10631
+ return statements;
10632
+ }
8419
10633
  /**
8420
10634
  * Returns default index definitions for the workflows domain tables.
8421
10635
  * Currently no default indexes are defined for workflows.
@@ -8682,6 +10896,29 @@ var WorkflowsPG = class _WorkflowsPG extends WorkflowsStorage {
8682
10896
  // src/storage/index.ts
8683
10897
  var DEFAULT_MAX_CONNECTIONS = 20;
8684
10898
  var DEFAULT_IDLE_TIMEOUT_MS = 3e4;
10899
+ var ALL_DOMAINS = [
10900
+ MemoryPG,
10901
+ ObservabilityPG,
10902
+ ScoresPG,
10903
+ ScorerDefinitionsPG,
10904
+ PromptBlocksPG,
10905
+ AgentsPG,
10906
+ WorkflowsPG,
10907
+ DatasetsPG,
10908
+ ExperimentsPG
10909
+ ];
10910
+ function exportSchemas(schemaName) {
10911
+ const statements = [];
10912
+ if (schemaName) {
10913
+ const quotedSchemaName = getSchemaName(schemaName);
10914
+ statements.push(`CREATE SCHEMA IF NOT EXISTS ${quotedSchemaName};`);
10915
+ statements.push("");
10916
+ }
10917
+ for (const Domain of ALL_DOMAINS) {
10918
+ statements.push(...Domain.getExportDDL(schemaName));
10919
+ }
10920
+ return statements.join("\n");
10921
+ }
8685
10922
  var PostgresStore = class extends MastraCompositeStore {
8686
10923
  #pool;
8687
10924
  #db;
@@ -8715,7 +10952,10 @@ var PostgresStore = class extends MastraCompositeStore {
8715
10952
  observability: new ObservabilityPG(domainConfig),
8716
10953
  agents: new AgentsPG(domainConfig),
8717
10954
  promptBlocks: new PromptBlocksPG(domainConfig),
8718
- scorerDefinitions: new ScorerDefinitionsPG(domainConfig)
10955
+ scorerDefinitions: new ScorerDefinitionsPG(domainConfig),
10956
+ mcpClients: new MCPClientsPG(domainConfig),
10957
+ datasets: new DatasetsPG(domainConfig),
10958
+ experiments: new ExperimentsPG(domainConfig)
8719
10959
  };
8720
10960
  } catch (e) {
8721
10961
  throw new MastraError(
@@ -8904,6 +11144,6 @@ Example Complex Query:
8904
11144
  ]
8905
11145
  }`;
8906
11146
 
8907
- export { AgentsPG, MemoryPG, ObservabilityPG, PGVECTOR_PROMPT, PgVector, PoolAdapter, PostgresStore, PromptBlocksPG, ScorerDefinitionsPG, ScoresPG, WorkflowsPG, exportSchemas };
11147
+ export { AgentsPG, DatasetsPG, ExperimentsPG, MCPClientsPG, MemoryPG, ObservabilityPG, PGVECTOR_PROMPT, PgVector, PoolAdapter, PostgresStore, PromptBlocksPG, ScorerDefinitionsPG, ScoresPG, WorkflowsPG, exportSchemas };
8908
11148
  //# sourceMappingURL=index.js.map
8909
11149
  //# sourceMappingURL=index.js.map