@mastra/pg 1.20.1-alpha.1 → 1.20.1-alpha.3

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
@@ -541,6 +541,7 @@ function buildFilterQuery(filter, minScore, topK) {
541
541
  }
542
542
  //#endregion
543
543
  //#region src/vector/index.ts
544
+ const MAX_UPSERT_ROWS_PER_STATEMENT = Math.floor(65535 / 3);
544
545
  var PgVector = class extends MastraVector {
545
546
  pool;
546
547
  describeIndexCache = /* @__PURE__ */ new Map();
@@ -933,23 +934,41 @@ var PgVector = class extends MastraVector {
933
934
  const indexInfo = await this.getIndexInfo({ indexName });
934
935
  const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType, indexInfo.dimension);
935
936
  const ops = this.getVectorOps(indexInfo.vectorType, indexInfo.metric ?? "cosine");
936
- for (let i = 0; i < vectors.length; i++) {
937
+ if (new Set(vectorIds).size !== vectorIds.length) for (let i = 0; i < vectors.length; i++) {
937
938
  const vectorStr = ops.formatVector(vectors[i], indexInfo.dimension);
938
939
  const query = `
939
- INSERT INTO ${tableName} (vector_id, embedding, metadata)
940
- VALUES ($1, $2::${qualifiedVectorType}, $3::jsonb)
941
- ON CONFLICT (vector_id)
942
- DO UPDATE SET
943
- embedding = $2::${qualifiedVectorType},
944
- metadata = $3::jsonb
945
- RETURNING embedding::text
946
- `;
940
+ INSERT INTO ${tableName} (vector_id, embedding, metadata)
941
+ VALUES ($1, $2::${qualifiedVectorType}, $3::jsonb)
942
+ ON CONFLICT (vector_id)
943
+ DO UPDATE SET
944
+ embedding = $2::${qualifiedVectorType},
945
+ metadata = $3::jsonb
946
+ `;
947
947
  await client.query(query, [
948
948
  vectorIds[i],
949
949
  vectorStr,
950
950
  JSON.stringify(metadata?.[i] || {})
951
951
  ]);
952
952
  }
953
+ else for (let start = 0; start < vectors.length; start += MAX_UPSERT_ROWS_PER_STATEMENT) {
954
+ const end = Math.min(start + MAX_UPSERT_ROWS_PER_STATEMENT, vectors.length);
955
+ const rows = [];
956
+ const values = [];
957
+ for (let i = start; i < end; i++) {
958
+ const base = values.length;
959
+ rows.push(`($${base + 1}, $${base + 2}::${qualifiedVectorType}, $${base + 3}::jsonb)`);
960
+ values.push(vectorIds[i], ops.formatVector(vectors[i], indexInfo.dimension), JSON.stringify(metadata?.[i] || {}));
961
+ }
962
+ const query = `
963
+ INSERT INTO ${tableName} (vector_id, embedding, metadata)
964
+ VALUES ${rows.join(", ")}
965
+ ON CONFLICT (vector_id)
966
+ DO UPDATE SET
967
+ embedding = EXCLUDED.embedding,
968
+ metadata = EXCLUDED.metadata
969
+ `;
970
+ await client.query(query, values);
971
+ }
953
972
  await client.query("COMMIT");
954
973
  this.logger?.debug(`Upserted ${vectors.length} vectors to ${indexName}`, {
955
974
  indexName,
@@ -3779,6 +3798,7 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
3779
3798
  "workspace",
3780
3799
  "skills",
3781
3800
  "skillsFormat",
3801
+ "durable",
3782
3802
  "browser",
3783
3803
  "toolProviders"
3784
3804
  ]
@@ -4258,10 +4278,10 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
4258
4278
  "defaultOptions", workflows, agents, "integrationTools", "toolProviders",
4259
4279
  "inputProcessors", "outputProcessors", memory, scorers,
4260
4280
  "mcpClients", "requestContextSchema", workspace, skills, "skillsFormat",
4261
- browser,
4281
+ durable, browser,
4262
4282
  "changedFields", "changeMessage",
4263
4283
  "createdAt", "createdAtZ"
4264
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27)`, [
4284
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)`, [
4265
4285
  input.id,
4266
4286
  input.agentId,
4267
4287
  input.versionNumber,
@@ -4284,6 +4304,7 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
4284
4304
  input.workspace ? JSON.stringify(input.workspace) : null,
4285
4305
  input.skills ? JSON.stringify(input.skills) : null,
4286
4306
  input.skillsFormat ?? null,
4307
+ input.durable !== void 0 ? JSON.stringify(input.durable) : null,
4287
4308
  input.browser ? JSON.stringify(input.browser) : null,
4288
4309
  input.changedFields ? JSON.stringify(input.changedFields) : null,
4289
4310
  input.changeMessage ?? null,
@@ -4512,6 +4533,7 @@ var AgentsPG = class AgentsPG extends AgentsStorage {
4512
4533
  workspace: parseJsonResilient(row.workspace, "workspace"),
4513
4534
  skills: parseJsonResilient(row.skills, "skills"),
4514
4535
  skillsFormat: row.skillsFormat,
4536
+ durable: parseJsonResilient(row.durable, "durable"),
4515
4537
  browser: parseJsonResilient(row.browser, "browser"),
4516
4538
  changedFields: parseJsonResilient(row.changedFields, "changedFields"),
4517
4539
  changeMessage: row.changeMessage,
@@ -20728,6 +20750,38 @@ var PgFactoryStorageOps = class {
20728
20750
  * Supports serializable app-table transactions for cross-replica invariant
20729
20751
  * enforcement and `authDatabase()` exposing the shared pool.
20730
20752
  */
20753
+ /**
20754
+ * A pool-level `error` listener only covers *idle* clients: pg hands ownership
20755
+ * of a client to the borrower for the duration of a checkout and takes its own
20756
+ * listener off. So a backend restart or network blip that lands on a client
20757
+ * mid-transaction reaches an emitter with no listener, and Node escalates that
20758
+ * to an uncaughtException that kills the process — the pool handler logs the
20759
+ * idle siblings and the borrowed one still brings everything down.
20760
+ *
20761
+ * Attach a listener once per physical connection instead. `connect` fires when
20762
+ * the pool establishes a client, so the client stays covered for its whole life
20763
+ * and there is nothing to remove on release.
20764
+ *
20765
+ * That listener outlives the checkout, so it also sees the failures the pool is
20766
+ * already reporting through its own idle listener. Follow `acquire`/`release`
20767
+ * to tell the two apart and stay quiet while the client is idle — otherwise one
20768
+ * dropped connection is announced twice, the second time as the wrong thing.
20769
+ *
20770
+ * The pool still discards the failed connection; this only keeps the failure
20771
+ * reportable instead of fatal.
20772
+ */
20773
+ function guardCheckedOutClientErrors(pool, warn = console.warn) {
20774
+ const borrowed = /* @__PURE__ */ new WeakSet();
20775
+ pool.on("connect", (client) => {
20776
+ borrowed.add(client);
20777
+ client.on("error", (err) => {
20778
+ if (!borrowed.has(client)) return;
20779
+ warn(`PgFactoryStorage: client error while checked out (the pool discards this connection): ${err instanceof Error ? err.message : String(err)}`);
20780
+ });
20781
+ });
20782
+ pool.on("acquire", (client) => borrowed.add(client));
20783
+ pool.on("release", (_err, client) => borrowed.delete(client));
20784
+ }
20731
20785
  var PgFactoryStorage = class extends FactoryStorage {
20732
20786
  ops;
20733
20787
  #pool;
@@ -20748,6 +20802,7 @@ var PgFactoryStorage = class extends FactoryStorage {
20748
20802
  this.#pool.on("error", (err) => {
20749
20803
  console.warn(`PgFactoryStorage: idle pool client error (pool discards the client and reconnects on next checkout): ${err instanceof Error ? err.message : String(err)}`);
20750
20804
  });
20805
+ guardCheckedOutClientErrors(this.#pool);
20751
20806
  }
20752
20807
  this.ops = new PgFactoryStorageOps(this.#pool, this.#schemas);
20753
20808
  }