@mastra/pg 1.9.0-alpha.0 → 1.9.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.9.1-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed `batchInsert` and `batchUpdate` in `@mastra/pg` to run on a single Postgres transaction connection. ([#15312](https://github.com/mastra-ai/mastra/pull/15312))
8
+
9
+ This prevents pooled `BEGIN`/`COMMIT`/`ROLLBACK` calls from landing on different connections and leaving idle transactions open during batch writes.
10
+
11
+ - Fixed "column does not exist" errors when using experiment review features on databases created before the review pipeline was introduced. Startup now automatically migrates older experiment tables to the latest schema. ([#15304](https://github.com/mastra-ai/mastra/pull/15304))
12
+
13
+ ## 1.9.0
14
+
15
+ ### Minor Changes
16
+
17
+ - Implemented `updateObservationalMemoryConfig()` in Postgres, LibSQL, and MongoDB storage adapters. This enables per-record config overrides for observational memory thresholds, supporting the new `memory.updateObservationalMemoryConfig()` API in `@mastra/memory`. ([#15115](https://github.com/mastra-ai/mastra/pull/15115))
18
+
19
+ ### Patch Changes
20
+
21
+ - Fixed observational memory date-range queries to use ISO-string timestamp columns (`createdAtZ`) instead of the raw `createdAt` column, ensuring correct filtering when querying observations by date range. ([#15115](https://github.com/mastra-ai/mastra/pull/15115))
22
+
23
+ - Updated dependencies [[`f32b9e1`](https://github.com/mastra-ai/mastra/commit/f32b9e115a3c754d1c8cfa3f4256fba87b09cfb7), [`7d6f521`](https://github.com/mastra-ai/mastra/commit/7d6f52164d0cca099f0b07cb2bba334360f1c8ab), [`a50d220`](https://github.com/mastra-ai/mastra/commit/a50d220b01ecbc5644d489a3d446c3bd4ab30245), [`665477b`](https://github.com/mastra-ai/mastra/commit/665477bc104fd52cfef8e7610d7664781a70c220), [`4cc2755`](https://github.com/mastra-ai/mastra/commit/4cc2755a7194cb08720ff2ab4dffb4b4a5103dfd), [`ac7baf6`](https://github.com/mastra-ai/mastra/commit/ac7baf66ef1db15e03975ef4ebb02724f015a391), [`ed425d7`](https://github.com/mastra-ai/mastra/commit/ed425d78e7c66cbda8209fee910856f98c6c6b82), [`1371703`](https://github.com/mastra-ai/mastra/commit/1371703835080450ef3f9aea58059a95d0da2e5a), [`0df8321`](https://github.com/mastra-ai/mastra/commit/0df832196eeb2450ab77ce887e8553abdd44c5a6), [`98f8a8b`](https://github.com/mastra-ai/mastra/commit/98f8a8bdf5761b9982f3ad3acbe7f1cc3efa71f3), [`ba6f7e9`](https://github.com/mastra-ai/mastra/commit/ba6f7e9086d8281393f2acae60fda61de3bff1f9), [`7eb2596`](https://github.com/mastra-ai/mastra/commit/7eb25960d607e07468c9a10c5437abd2deaf1e9a), [`1805ddc`](https://github.com/mastra-ai/mastra/commit/1805ddc9c9b3b14b63749735a13c05a45af43a80), [`fff91cf`](https://github.com/mastra-ai/mastra/commit/fff91cf914de0e731578aacebffdeebef82f0440), [`61109b3`](https://github.com/mastra-ai/mastra/commit/61109b34feb0e38d54bee4b8ca83eb7345b1d557), [`33f1ead`](https://github.com/mastra-ai/mastra/commit/33f1eadfa19c86953f593478e5fa371093b33779)]:
24
+ - @mastra/core@1.23.0
25
+
3
26
  ## 1.9.0-alpha.0
4
27
 
5
28
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-pg
3
3
  description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/pg"
6
- version: "1.9.0-alpha.0"
6
+ version: "1.9.1-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.9.0-alpha.0",
2
+ "version": "1.9.1-alpha.0",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -118,8 +118,6 @@ export const agent = new Agent({
118
118
  })
119
119
  ```
120
120
 
121
- > **Warning:** Agent-level storage isn't supported when using [Mastra Cloud Store](https://mastra.ai/docs/mastra-cloud/deployment). If you use Mastra Cloud Store, configure storage on the Mastra instance instead. This limitation doesn't apply if you bring your own database.
122
-
123
121
  ## Threads and resources
124
122
 
125
123
  Mastra organizes conversations using two identifiers:
@@ -397,4 +397,4 @@ const response = await agent.generate('What do you know about me?', {
397
397
 
398
398
  - [Working memory with template](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-template)
399
399
  - [Working memory with schema](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-schema)
400
- - [Per-resource working memory](https://github.com/mastra-ai/mastra/tree/main/examples/memory-per-resource-example) - Complete example showing resource-scoped memory persistence
400
+ - [Per-resource working memory](https://github.com/mastra-ai/mastra/tree/main/examples/memory-per-resource-example): Complete example showing resource-scoped memory persistence
package/dist/index.cjs CHANGED
@@ -2499,36 +2499,39 @@ var PgDB = class extends base.MastraBase {
2499
2499
  return storage.getDefaultValue(type);
2500
2500
  }
2501
2501
  }
2502
- async insert({ tableName, record }) {
2503
- try {
2504
- this.addTimestampZColumns(record);
2505
- const filteredRecord = await this.filterRecordToKnownColumns(tableName, record);
2506
- const schemaName = getSchemaName(this.schemaName);
2507
- const columns = Object.keys(filteredRecord).map((col) => utils.parseSqlIdentifier(col, "column name"));
2508
- if (columns.length === 0) return;
2509
- const values = this.prepareValuesForInsert(filteredRecord, tableName);
2510
- const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
2511
- const fullTableName = getTableName({ indexName: tableName, schemaName });
2512
- const columnList = columns.map((c) => `"${c}"`).join(", ");
2513
- if (tableName === storage.TABLE_SPANS) {
2514
- const updateColumns = columns.filter((c) => c !== "traceId" && c !== "spanId");
2515
- if (updateColumns.length > 0) {
2516
- const updateClause = updateColumns.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ");
2517
- await this.client.none(
2518
- `INSERT INTO ${fullTableName} (${columnList}) VALUES (${placeholders})
2502
+ async executeInsert(client, { tableName, record }) {
2503
+ this.addTimestampZColumns(record);
2504
+ const filteredRecord = await this.filterRecordToKnownColumns(tableName, record);
2505
+ const schemaName = getSchemaName(this.schemaName);
2506
+ const columns = Object.keys(filteredRecord).map((col) => utils.parseSqlIdentifier(col, "column name"));
2507
+ if (columns.length === 0) return;
2508
+ const values = this.prepareValuesForInsert(filteredRecord, tableName);
2509
+ const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
2510
+ const fullTableName = getTableName({ indexName: tableName, schemaName });
2511
+ const columnList = columns.map((c) => `"${c}"`).join(", ");
2512
+ if (tableName === storage.TABLE_SPANS) {
2513
+ const updateColumns = columns.filter((c) => c !== "traceId" && c !== "spanId");
2514
+ if (updateColumns.length > 0) {
2515
+ const updateClause = updateColumns.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ");
2516
+ await client.none(
2517
+ `INSERT INTO ${fullTableName} (${columnList}) VALUES (${placeholders})
2519
2518
  ON CONFLICT ("traceId", "spanId") DO UPDATE SET ${updateClause}`,
2520
- values
2521
- );
2522
- } else {
2523
- await this.client.none(
2524
- `INSERT INTO ${fullTableName} (${columnList}) VALUES (${placeholders})
2525
- ON CONFLICT ("traceId", "spanId") DO NOTHING`,
2526
- values
2527
- );
2528
- }
2519
+ values
2520
+ );
2529
2521
  } else {
2530
- await this.client.none(`INSERT INTO ${fullTableName} (${columnList}) VALUES (${placeholders})`, values);
2522
+ await client.none(
2523
+ `INSERT INTO ${fullTableName} (${columnList}) VALUES (${placeholders})
2524
+ ON CONFLICT ("traceId", "spanId") DO NOTHING`,
2525
+ values
2526
+ );
2531
2527
  }
2528
+ } else {
2529
+ await client.none(`INSERT INTO ${fullTableName} (${columnList}) VALUES (${placeholders})`, values);
2530
+ }
2531
+ }
2532
+ async insert({ tableName, record }) {
2533
+ try {
2534
+ await this.executeInsert(this.client, { tableName, record });
2532
2535
  } catch (error$1) {
2533
2536
  throw new error.MastraError(
2534
2537
  {
@@ -3003,13 +3006,12 @@ Note: This migration may take some time for large tables.
3003
3006
  }
3004
3007
  async batchInsert({ tableName, records }) {
3005
3008
  try {
3006
- await this.client.query("BEGIN");
3007
- for (const record of records) {
3008
- await this.insert({ tableName, record });
3009
- }
3010
- await this.client.query("COMMIT");
3009
+ await this.client.tx(async (tx) => {
3010
+ for (const record of records) {
3011
+ await this.executeInsert(tx, { tableName, record });
3012
+ }
3013
+ });
3011
3014
  } catch (error$1) {
3012
- await this.client.query("ROLLBACK");
3013
3015
  throw new error.MastraError(
3014
3016
  {
3015
3017
  id: storage.createStorageErrorId("PG", "BATCH_INSERT", "FAILED"),
@@ -3287,30 +3289,7 @@ Note: This migration may take some time for large tables.
3287
3289
  data
3288
3290
  }) {
3289
3291
  try {
3290
- const filteredData = await this.filterRecordToKnownColumns(tableName, data);
3291
- if (Object.keys(filteredData).length === 0) return;
3292
- const setColumns = [];
3293
- const setValues = [];
3294
- let paramIndex = 1;
3295
- Object.entries(filteredData).forEach(([key, value]) => {
3296
- const parsedKey = utils.parseSqlIdentifier(key, "column name");
3297
- setColumns.push(`"${parsedKey}" = $${paramIndex++}`);
3298
- setValues.push(this.prepareValue(value, key, tableName));
3299
- });
3300
- const whereConditions = [];
3301
- const whereValues = [];
3302
- Object.entries(keys).forEach(([key, value]) => {
3303
- const parsedKey = utils.parseSqlIdentifier(key, "column name");
3304
- whereConditions.push(`"${parsedKey}" = $${paramIndex++}`);
3305
- whereValues.push(this.prepareValue(value, key, tableName));
3306
- });
3307
- const tableName_ = getTableName({
3308
- indexName: tableName,
3309
- schemaName: getSchemaName(this.schemaName)
3310
- });
3311
- const sql = `UPDATE ${tableName_} SET ${setColumns.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
3312
- const values = [...setValues, ...whereValues];
3313
- await this.client.none(sql, values);
3292
+ await this.executeUpdate(this.client, { tableName, keys, data });
3314
3293
  } catch (error$1) {
3315
3294
  throw new error.MastraError(
3316
3295
  {
@@ -3330,13 +3309,12 @@ Note: This migration may take some time for large tables.
3330
3309
  updates
3331
3310
  }) {
3332
3311
  try {
3333
- await this.client.query("BEGIN");
3334
- for (const { keys, data } of updates) {
3335
- await this.update({ tableName, keys, data });
3336
- }
3337
- await this.client.query("COMMIT");
3312
+ await this.client.tx(async (tx) => {
3313
+ for (const { keys, data } of updates) {
3314
+ await this.executeUpdate(tx, { tableName, keys, data });
3315
+ }
3316
+ });
3338
3317
  } catch (error$1) {
3339
- await this.client.query("ROLLBACK");
3340
3318
  throw new error.MastraError(
3341
3319
  {
3342
3320
  id: storage.createStorageErrorId("PG", "BATCH_UPDATE", "FAILED"),
@@ -3395,6 +3373,36 @@ Note: This migration may take some time for large tables.
3395
3373
  async deleteData({ tableName }) {
3396
3374
  return this.clearTable({ tableName });
3397
3375
  }
3376
+ async executeUpdate(client, {
3377
+ tableName,
3378
+ keys,
3379
+ data
3380
+ }) {
3381
+ const filteredData = await this.filterRecordToKnownColumns(tableName, data);
3382
+ if (Object.keys(filteredData).length === 0) return;
3383
+ const setColumns = [];
3384
+ const setValues = [];
3385
+ let paramIndex = 1;
3386
+ Object.entries(filteredData).forEach(([key, value]) => {
3387
+ const parsedKey = utils.parseSqlIdentifier(key, "column name");
3388
+ setColumns.push(`"${parsedKey}" = $${paramIndex++}`);
3389
+ setValues.push(this.prepareValue(value, key, tableName));
3390
+ });
3391
+ const whereConditions = [];
3392
+ const whereValues = [];
3393
+ Object.entries(keys).forEach(([key, value]) => {
3394
+ const parsedKey = utils.parseSqlIdentifier(key, "column name");
3395
+ whereConditions.push(`"${parsedKey}" = $${paramIndex++}`);
3396
+ whereValues.push(this.prepareValue(value, key, tableName));
3397
+ });
3398
+ const tableName_ = getTableName({
3399
+ indexName: tableName,
3400
+ schemaName: getSchemaName(this.schemaName)
3401
+ });
3402
+ const sql = `UPDATE ${tableName_} SET ${setColumns.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
3403
+ const values = [...setValues, ...whereValues];
3404
+ await client.none(sql, values);
3405
+ }
3398
3406
  };
3399
3407
  function getSchemaName2(schema) {
3400
3408
  return schema ? `"${utils.parseSqlIdentifier(schema, "schema name")}"` : void 0;
@@ -5308,6 +5316,16 @@ var ExperimentsPG = class _ExperimentsPG extends storage.ExperimentsStorage {
5308
5316
  async init() {
5309
5317
  await this.#db.createTable({ tableName: storage.TABLE_EXPERIMENTS, schema: storage.EXPERIMENTS_SCHEMA });
5310
5318
  await this.#db.createTable({ tableName: storage.TABLE_EXPERIMENT_RESULTS, schema: storage.EXPERIMENT_RESULTS_SCHEMA });
5319
+ await this.#db.alterTable({
5320
+ tableName: storage.TABLE_EXPERIMENTS,
5321
+ schema: storage.EXPERIMENTS_SCHEMA,
5322
+ ifNotExists: ["agentVersion"]
5323
+ });
5324
+ await this.#db.alterTable({
5325
+ tableName: storage.TABLE_EXPERIMENT_RESULTS,
5326
+ schema: storage.EXPERIMENT_RESULTS_SCHEMA,
5327
+ ifNotExists: ["status", "tags"]
5328
+ });
5311
5329
  await this.createDefaultIndexes();
5312
5330
  await this.createCustomIndexes();
5313
5331
  }