@mastra/pg 1.11.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ import { randomUUID } from 'crypto';
12
12
  import { createRequire } from 'module';
13
13
  import { MessageList } from '@mastra/core/agent';
14
14
  import { saveScorePayloadSchema } from '@mastra/core/evals';
15
+ import { parse } from 'pg-connection-string';
15
16
 
16
17
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
17
18
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
@@ -606,7 +607,7 @@ var PgVector = class extends MastraVector {
606
607
  constructor(config) {
607
608
  try {
608
609
  validateConfig("PgVector", config);
609
- super({ id: config.id });
610
+ super({ id: config.id, disableInit: config.disableInit });
610
611
  this.schema = config.schemaName;
611
612
  let poolConfig;
612
613
  if (isConnectionStringConfig(config)) {
@@ -1220,6 +1221,9 @@ var PgVector = class extends MastraVector {
1220
1221
  this.logger?.trackException(mastraError);
1221
1222
  throw mastraError;
1222
1223
  }
1224
+ if (this.disableInit || process.env.MASTRA_DISABLE_STORAGE_INIT === "true") {
1225
+ return;
1226
+ }
1223
1227
  const indexCacheKey = await this.getIndexCacheKey({
1224
1228
  indexName,
1225
1229
  dimension,
@@ -4371,10 +4375,10 @@ function rowToTask(row) {
4371
4375
  retryCount: Number(row.retry_count),
4372
4376
  maxRetries: Number(row.max_retries),
4373
4377
  timeoutMs: Number(row.timeout_ms),
4374
- createdAt: row.createdAt instanceof Date ? row.createdAt : new Date(row.createdAt),
4375
- startedAt: row.startedAt ? row.startedAt instanceof Date ? row.startedAt : new Date(row.startedAt) : void 0,
4376
- suspendedAt: row.suspendedAt ? row.suspendedAt instanceof Date ? row.suspendedAt : new Date(row.suspendedAt) : void 0,
4377
- completedAt: row.completedAt ? row.completedAt instanceof Date ? row.completedAt : new Date(row.completedAt) : void 0
4378
+ createdAt: new Date(row.createdAtZ || row.createdAt),
4379
+ startedAt: row.startedAtZ || row.startedAt ? new Date(row.startedAtZ || row.startedAt) : void 0,
4380
+ suspendedAt: row.suspendedAtZ || row.suspendedAt ? new Date(row.suspendedAtZ || row.suspendedAt) : void 0,
4381
+ completedAt: row.completedAtZ || row.completedAt ? new Date(row.completedAtZ || row.completedAt) : void 0
4378
4382
  };
4379
4383
  }
4380
4384
  var BackgroundTasksPG = class _BackgroundTasksPG extends BackgroundTasksStorage {
@@ -4524,15 +4528,21 @@ var BackgroundTasksPG = class _BackgroundTasksPG extends BackgroundTasksStorage
4524
4528
  }
4525
4529
  if ("startedAt" in update) {
4526
4530
  setClauses.push(`"startedAt" = $${paramIdx++}`);
4527
- params.push(update.startedAt?.toISOString() ?? null);
4531
+ setClauses.push(`"startedAtZ" = $${paramIdx++}`);
4532
+ const val = update.startedAt?.toISOString() ?? null;
4533
+ params.push(val, val);
4528
4534
  }
4529
4535
  if ("suspendedAt" in update) {
4530
4536
  setClauses.push(`"suspendedAt" = $${paramIdx++}`);
4531
- params.push(update.suspendedAt?.toISOString() ?? null);
4537
+ setClauses.push(`"suspendedAtZ" = $${paramIdx++}`);
4538
+ const val = update.suspendedAt?.toISOString() ?? null;
4539
+ params.push(val, val);
4532
4540
  }
4533
4541
  if ("completedAt" in update) {
4534
4542
  setClauses.push(`"completedAt" = $${paramIdx++}`);
4535
- params.push(update.completedAt?.toISOString() ?? null);
4543
+ setClauses.push(`"completedAtZ" = $${paramIdx++}`);
4544
+ const val = update.completedAt?.toISOString() ?? null;
4545
+ params.push(val, val);
4536
4546
  }
4537
4547
  if (setClauses.length === 0) return;
4538
4548
  const table = getTableName3(getSchemaName3(this.#schema));
@@ -4824,9 +4834,10 @@ var ChannelsPG = class _ChannelsPG extends ChannelsStorage {
4824
4834
  const schemaName = getSchemaName2(this.#schema);
4825
4835
  const tableName = getTableName2({ indexName: TABLE_CHANNEL_INSTALLATIONS, schemaName });
4826
4836
  const now = (/* @__PURE__ */ new Date()).toISOString();
4837
+ const createdAt = installation.createdAt?.toISOString() ?? now;
4827
4838
  await this.#db.client.none(
4828
- `INSERT INTO ${tableName} ("id", "platform", "agentId", "status", "webhookId", "data", "configHash", "error", "createdAt", "updatedAt")
4829
- VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7, $8, $9, $10)
4839
+ `INSERT INTO ${tableName} ("id", "platform", "agentId", "status", "webhookId", "data", "configHash", "error", "createdAt", "createdAtZ", "updatedAt", "updatedAtZ")
4840
+ VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7, $8, $9, $10, $11, $12)
4830
4841
  ON CONFLICT ("id") DO UPDATE SET
4831
4842
  "platform" = EXCLUDED."platform",
4832
4843
  "agentId" = EXCLUDED."agentId",
@@ -4835,7 +4846,8 @@ var ChannelsPG = class _ChannelsPG extends ChannelsStorage {
4835
4846
  "data" = EXCLUDED."data",
4836
4847
  "configHash" = EXCLUDED."configHash",
4837
4848
  "error" = EXCLUDED."error",
4838
- "updatedAt" = EXCLUDED."updatedAt"`,
4849
+ "updatedAt" = EXCLUDED."updatedAt",
4850
+ "updatedAtZ" = EXCLUDED."updatedAtZ"`,
4839
4851
  [
4840
4852
  installation.id,
4841
4853
  installation.platform,
@@ -4845,7 +4857,9 @@ var ChannelsPG = class _ChannelsPG extends ChannelsStorage {
4845
4857
  JSON.stringify(installation.data),
4846
4858
  installation.configHash ?? null,
4847
4859
  installation.error ?? null,
4848
- installation.createdAt?.toISOString() ?? now,
4860
+ createdAt,
4861
+ createdAt,
4862
+ now,
4849
4863
  now
4850
4864
  ]
4851
4865
  );
@@ -4888,13 +4902,15 @@ var ChannelsPG = class _ChannelsPG extends ChannelsStorage {
4888
4902
  async saveConfig(config) {
4889
4903
  const schemaName = getSchemaName2(this.#schema);
4890
4904
  const tableName = getTableName2({ indexName: TABLE_CHANNEL_CONFIG, schemaName });
4905
+ const now = config.updatedAt.toISOString();
4891
4906
  await this.#db.client.none(
4892
- `INSERT INTO ${tableName} ("platform", "data", "updatedAt")
4893
- VALUES ($1, $2::jsonb, $3)
4907
+ `INSERT INTO ${tableName} ("platform", "data", "updatedAt", "updatedAtZ")
4908
+ VALUES ($1, $2::jsonb, $3, $4)
4894
4909
  ON CONFLICT ("platform") DO UPDATE SET
4895
4910
  "data" = EXCLUDED."data",
4896
- "updatedAt" = EXCLUDED."updatedAt"`,
4897
- [config.platform, JSON.stringify(config.data), config.updatedAt.toISOString()]
4911
+ "updatedAt" = EXCLUDED."updatedAt",
4912
+ "updatedAtZ" = EXCLUDED."updatedAtZ"`,
4913
+ [config.platform, JSON.stringify(config.data), now, now]
4898
4914
  );
4899
4915
  }
4900
4916
  async getConfig(platform) {
@@ -4905,7 +4921,7 @@ var ChannelsPG = class _ChannelsPG extends ChannelsStorage {
4905
4921
  return {
4906
4922
  platform: row.platform,
4907
4923
  data: typeof row.data === "string" ? JSON.parse(row.data) : row.data,
4908
- updatedAt: new Date(row.updatedAt)
4924
+ updatedAt: new Date(row.updatedAtZ || row.updatedAt)
4909
4925
  };
4910
4926
  }
4911
4927
  async deleteConfig(platform) {
@@ -4923,8 +4939,8 @@ var ChannelsPG = class _ChannelsPG extends ChannelsStorage {
4923
4939
  data: typeof row.data === "string" ? JSON.parse(row.data) : row.data,
4924
4940
  configHash: row.configHash || void 0,
4925
4941
  error: row.error || void 0,
4926
- createdAt: row.createdAt instanceof Date ? row.createdAt : new Date(row.createdAt),
4927
- updatedAt: row.updatedAt instanceof Date ? row.updatedAt : new Date(row.updatedAt)
4942
+ createdAt: new Date(row.createdAtZ || row.createdAt),
4943
+ updatedAt: new Date(row.updatedAtZ || row.updatedAt)
4928
4944
  };
4929
4945
  }
4930
4946
  };
@@ -7955,6 +7971,9 @@ var MCPServersPG = class _MCPServersPG extends MCPServersStorage {
7955
7971
  }
7956
7972
  };
7957
7973
  var OM_TABLE = "mastra_observational_memory";
7974
+ var POSTGRES_MAX_BIND_PARAMETERS = 65535;
7975
+ var MESSAGE_INSERT_BIND_PARAMETERS = 8;
7976
+ var MAX_MESSAGES_PER_INSERT = Math.floor(POSTGRES_MAX_BIND_PARAMETERS / MESSAGE_INSERT_BIND_PARAMETERS);
7958
7977
  var OM_MIGRATION_COLUMNS = [
7959
7978
  "observedMessageIds",
7960
7979
  "observedTimezone",
@@ -7989,6 +8008,24 @@ function getTableName4({ indexName, schemaName }) {
7989
8008
  function inPlaceholders(count, startIndex = 1) {
7990
8009
  return Array.from({ length: count }, (_, i) => `$${i + startIndex}`).join(", ");
7991
8010
  }
8011
+ function dedupeMessagesForSave(messages) {
8012
+ const deduped = /* @__PURE__ */ new Map();
8013
+ for (const message of messages) {
8014
+ const existing = deduped.get(message.id);
8015
+ if (existing) {
8016
+ deduped.set(message.id, {
8017
+ ...message,
8018
+ createdAt: existing.createdAt
8019
+ });
8020
+ } else {
8021
+ deduped.set(message.id, {
8022
+ ...message,
8023
+ createdAt: message.createdAt || /* @__PURE__ */ new Date()
8024
+ });
8025
+ }
8026
+ }
8027
+ return Array.from(deduped.values());
8028
+ }
7992
8029
  var MemoryPG = class _MemoryPG extends MemoryStorage {
7993
8030
  supportsObservationalMemory = true;
7994
8031
  #db;
@@ -8874,63 +8911,83 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
8874
8911
  text: `Thread ID is required`
8875
8912
  });
8876
8913
  }
8877
- const thread = await this.getThreadById({ threadId });
8878
- if (!thread) {
8879
- throw new MastraError({
8880
- id: createStorageErrorId("PG", "SAVE_MESSAGES", "FAILED"),
8881
- domain: ErrorDomain.STORAGE,
8882
- category: ErrorCategory.THIRD_PARTY,
8883
- text: `Thread ${threadId} not found`,
8884
- details: {
8885
- threadId
8886
- }
8887
- });
8888
- }
8889
8914
  try {
8890
8915
  const tableName = getTableName4({ indexName: TABLE_MESSAGES, schemaName: getSchemaName4(this.#schema) });
8916
+ const threadIds = /* @__PURE__ */ new Set();
8917
+ for (const message of messages) {
8918
+ if (!message.threadId) {
8919
+ throw new Error(
8920
+ `Expected to find a threadId for message, but couldn't find one. An unexpected error has occurred.`
8921
+ );
8922
+ }
8923
+ if (!message.resourceId) {
8924
+ throw new Error(
8925
+ `Expected to find a resourceId for message, but couldn't find one. An unexpected error has occurred.`
8926
+ );
8927
+ }
8928
+ threadIds.add(message.threadId);
8929
+ }
8930
+ for (const threadIdToCheck of threadIds) {
8931
+ const thread = await this.getThreadById({ threadId: threadIdToCheck });
8932
+ if (!thread) {
8933
+ throw new MastraError({
8934
+ id: createStorageErrorId("PG", "SAVE_MESSAGES", "FAILED"),
8935
+ domain: ErrorDomain.STORAGE,
8936
+ category: ErrorCategory.THIRD_PARTY,
8937
+ text: `Thread ${threadIdToCheck} not found`,
8938
+ details: {
8939
+ threadId: threadIdToCheck
8940
+ }
8941
+ });
8942
+ }
8943
+ }
8944
+ const messagesToSave = dedupeMessagesForSave(messages);
8891
8945
  await this.#db.client.tx(async (t) => {
8892
- for (const message of messages) {
8893
- if (!message.threadId) {
8894
- throw new Error(
8895
- `Expected to find a threadId for message, but couldn't find one. An unexpected error has occurred.`
8896
- );
8897
- }
8898
- if (!message.resourceId) {
8899
- throw new Error(
8900
- `Expected to find a resourceId for message, but couldn't find one. An unexpected error has occurred.`
8946
+ for (let offset = 0; offset < messagesToSave.length; offset += MAX_MESSAGES_PER_INSERT) {
8947
+ const batch = messagesToSave.slice(offset, offset + MAX_MESSAGES_PER_INSERT);
8948
+ const values = [];
8949
+ const valuePlaceholders = batch.map((message, messageIndex) => {
8950
+ const createdAt = message.createdAt || /* @__PURE__ */ new Date();
8951
+ values.push(
8952
+ message.id,
8953
+ message.threadId,
8954
+ typeof message.content === "string" ? message.content : JSON.stringify(message.content),
8955
+ createdAt,
8956
+ createdAt,
8957
+ message.role,
8958
+ message.type || "v2",
8959
+ message.resourceId
8901
8960
  );
8902
- }
8961
+ const paramOffset = messageIndex * MESSAGE_INSERT_BIND_PARAMETERS;
8962
+ return `(${Array.from(
8963
+ { length: MESSAGE_INSERT_BIND_PARAMETERS },
8964
+ (_, paramIndex) => `$${paramOffset + paramIndex + 1}`
8965
+ ).join(", ")})`;
8966
+ }).join(", ");
8903
8967
  await t.none(
8904
8968
  `INSERT INTO ${tableName} (id, thread_id, content, "createdAt", "createdAtZ", role, type, "resourceId")
8905
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
8969
+ VALUES ${valuePlaceholders}
8906
8970
  ON CONFLICT (id) DO UPDATE SET
8907
8971
  thread_id = EXCLUDED.thread_id,
8908
8972
  content = EXCLUDED.content,
8909
8973
  role = EXCLUDED.role,
8910
8974
  type = EXCLUDED.type,
8911
8975
  "resourceId" = EXCLUDED."resourceId"`,
8912
- [
8913
- message.id,
8914
- message.threadId,
8915
- typeof message.content === "string" ? message.content : JSON.stringify(message.content),
8916
- message.createdAt || /* @__PURE__ */ new Date(),
8917
- message.createdAt || /* @__PURE__ */ new Date(),
8918
- message.role,
8919
- message.type || "v2",
8920
- message.resourceId
8921
- ]
8976
+ values
8922
8977
  );
8923
8978
  }
8924
8979
  const threadTableName = getTableName4({ indexName: TABLE_THREADS, schemaName: getSchemaName4(this.#schema) });
8925
8980
  const now = /* @__PURE__ */ new Date();
8926
- await t.none(
8927
- `UPDATE ${threadTableName}
8928
- SET
8929
- "updatedAt" = $1,
8930
- "updatedAtZ" = $2
8931
- WHERE id = $3`,
8932
- [now, now, threadId]
8933
- );
8981
+ for (const threadIdToUpdate of threadIds) {
8982
+ await t.none(
8983
+ `UPDATE ${threadTableName}
8984
+ SET
8985
+ "updatedAt" = $1,
8986
+ "updatedAtZ" = $2
8987
+ WHERE id = $3`,
8988
+ [now, now, threadIdToUpdate]
8989
+ );
8990
+ }
8934
8991
  });
8935
8992
  const messagesWithParsedContent = messages.map((message) => {
8936
8993
  if (typeof message.content === "string") {
@@ -8945,6 +9002,9 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
8945
9002
  const list = new MessageList().add(messagesWithParsedContent, "memory");
8946
9003
  return { messages: list.get.all.db() };
8947
9004
  } catch (error) {
9005
+ if (error instanceof MastraError) {
9006
+ throw error;
9007
+ }
8948
9008
  throw new MastraError(
8949
9009
  {
8950
9010
  id: createStorageErrorId("PG", "SAVE_MESSAGES", "FAILED"),
@@ -14905,6 +14965,15 @@ var WorkspacesPG = class _WorkspacesPG extends WorkspacesStorage {
14905
14965
  };
14906
14966
  }
14907
14967
  };
14968
+ function buildConnectionStringPoolConfig(config, defaults) {
14969
+ const parsed = parse(config.connectionString);
14970
+ return {
14971
+ ...parsed,
14972
+ ...config.ssl !== void 0 ? { ssl: config.ssl } : {},
14973
+ max: config.max ?? defaults.max,
14974
+ idleTimeoutMillis: config.idleTimeoutMillis ?? defaults.idleTimeoutMillis
14975
+ };
14976
+ }
14908
14977
 
14909
14978
  // src/storage/index.ts
14910
14979
  var DEFAULT_MAX_CONNECTIONS = 20;
@@ -14995,12 +15064,12 @@ var PostgresStore = class extends MastraCompositeStore {
14995
15064
  }
14996
15065
  createPool(config) {
14997
15066
  if (isConnectionStringConfig(config)) {
14998
- return new Pool({
14999
- connectionString: config.connectionString,
15000
- ssl: config.ssl,
15001
- max: config.max ?? DEFAULT_MAX_CONNECTIONS,
15002
- idleTimeoutMillis: config.idleTimeoutMillis ?? DEFAULT_IDLE_TIMEOUT_MS
15003
- });
15067
+ return new Pool(
15068
+ buildConnectionStringPoolConfig(config, {
15069
+ max: DEFAULT_MAX_CONNECTIONS,
15070
+ idleTimeoutMillis: DEFAULT_IDLE_TIMEOUT_MS
15071
+ })
15072
+ );
15004
15073
  }
15005
15074
  if (isHostConfig(config)) {
15006
15075
  return new Pool({