@mastra/pg 1.19.0 → 1.20.0-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/dist/index.js CHANGED
@@ -146,13 +146,23 @@ var PGFilterTranslator = class extends BaseFilterTranslator {
146
146
  };
147
147
  //#endregion
148
148
  //#region src/vector/sql-builder.ts
149
+ const getTextExtractExpr = (key) => {
150
+ const jsonPathKey = parseJsonPathKey(key);
151
+ if (!key.includes(".")) return `metadata->>'${jsonPathKey}'`;
152
+ return `metadata#>>'{${jsonPathKey}}'`;
153
+ };
154
+ const getJsonExtractExpr = (key) => {
155
+ const jsonPathKey = parseJsonPathKey(key);
156
+ if (!key.includes(".")) return `metadata->'${jsonPathKey}'`;
157
+ return `metadata#>'{${jsonPathKey}}'`;
158
+ };
149
159
  const createBasicOperator = (symbol) => {
150
160
  return (key, paramIndex) => {
151
- const jsonPathKey = parseJsonPathKey(key);
161
+ const textExtract = getTextExtractExpr(key);
152
162
  return {
153
- sql: `CASE
154
- WHEN $${paramIndex}::text IS NULL THEN metadata#>>'{${jsonPathKey}}' IS ${symbol === "=" ? "" : "NOT"} NULL
155
- ELSE metadata#>>'{${jsonPathKey}}' ${symbol} $${paramIndex}::text
163
+ sql: `CASE
164
+ WHEN $${paramIndex}::text IS NULL THEN ${textExtract} IS ${symbol === "=" ? "" : "NOT"} NULL
165
+ ELSE ${textExtract} ${symbol} $${paramIndex}::text
156
166
  END`,
157
167
  needsValue: true
158
168
  };
@@ -160,13 +170,14 @@ const createBasicOperator = (symbol) => {
160
170
  };
161
171
  const createNumericOperator = (symbol) => {
162
172
  return (key, paramIndex, value) => {
163
- const jsonPathKey = parseJsonPathKey(key);
173
+ const textExtract = getTextExtractExpr(key);
174
+ const jsonExtract = getJsonExtractExpr(key);
164
175
  if (typeof value === "number" || typeof value === "string" && !isNaN(Number(value)) && value.trim() !== "") return {
165
- sql: `(CASE WHEN jsonb_typeof(metadata#>'{${jsonPathKey}}') = 'number' THEN (metadata#>>'{${jsonPathKey}}')::numeric ${symbol} $${paramIndex}::numeric ELSE NULL END)`,
176
+ sql: `(CASE WHEN jsonb_typeof(${jsonExtract}) = 'number' THEN (${textExtract})::numeric ${symbol} $${paramIndex}::numeric ELSE NULL END)`,
166
177
  needsValue: true
167
178
  };
168
179
  else return {
169
- sql: `metadata#>>'{${jsonPathKey}}' ${symbol} $${paramIndex}::text`,
180
+ sql: `${textExtract} ${symbol} $${paramIndex}::text`,
170
181
  needsValue: true
171
182
  };
172
183
  };
@@ -197,7 +208,7 @@ function buildElemMatchConditions(value, paramIndex) {
197
208
  const operatorFn = FILTER_OPERATORS[paramOperator];
198
209
  if (!operatorFn) throw new Error(`Invalid operator: ${paramOperator}`);
199
210
  const result = operatorFn(paramKey, nextParamIndex, paramValue);
200
- const sql = result.sql.replaceAll("metadata#>>", "elem#>>").replaceAll("metadata#>", "elem#>");
211
+ const sql = result.sql.replaceAll("metadata->>", "elem->>").replaceAll("metadata->", "elem->").replaceAll("metadata#>>", "elem#>>").replaceAll("metadata#>", "elem#>");
201
212
  conditions.push(sql);
202
213
  if (result.needsValue) values.push(paramValue);
203
214
  });
@@ -214,32 +225,34 @@ const FILTER_OPERATORS = {
214
225
  $lt: createNumericOperator("<"),
215
226
  $lte: createNumericOperator("<="),
216
227
  $in: (key, paramIndex) => {
217
- const jsonPathKey = parseJsonPathKey(key);
228
+ const textExtract = getTextExtractExpr(key);
229
+ const jsonExtract = getJsonExtractExpr(key);
218
230
  return {
219
231
  sql: `(
220
232
  CASE
221
- WHEN jsonb_typeof(metadata->'${jsonPathKey}') = 'array' THEN
233
+ WHEN jsonb_typeof(${jsonExtract}) = 'array' THEN
222
234
  EXISTS (
223
- SELECT 1 FROM jsonb_array_elements_text(metadata->'${jsonPathKey}') as elem
235
+ SELECT 1 FROM jsonb_array_elements_text(${jsonExtract}) as elem
224
236
  WHERE elem = ANY($${paramIndex}::text[])
225
237
  )
226
- ELSE metadata#>>'{${jsonPathKey}}' = ANY($${paramIndex}::text[])
238
+ ELSE ${textExtract} = ANY($${paramIndex}::text[])
227
239
  END
228
240
  )`,
229
241
  needsValue: true
230
242
  };
231
243
  },
232
244
  $nin: (key, paramIndex) => {
233
- const jsonPathKey = parseJsonPathKey(key);
245
+ const textExtract = getTextExtractExpr(key);
246
+ const jsonExtract = getJsonExtractExpr(key);
234
247
  return {
235
248
  sql: `(
236
249
  CASE
237
- WHEN jsonb_typeof(metadata->'${jsonPathKey}') = 'array' THEN
250
+ WHEN jsonb_typeof(${jsonExtract}) = 'array' THEN
238
251
  NOT EXISTS (
239
- SELECT 1 FROM jsonb_array_elements_text(metadata->'${jsonPathKey}') as elem
252
+ SELECT 1 FROM jsonb_array_elements_text(${jsonExtract}) as elem
240
253
  WHERE elem = ANY($${paramIndex}::text[])
241
254
  )
242
- ELSE metadata#>>'{${jsonPathKey}}' != ALL($${paramIndex}::text[])
255
+ ELSE ${textExtract} != ALL($${paramIndex}::text[])
243
256
  END
244
257
  )`,
245
258
  needsValue: true
@@ -247,21 +260,21 @@ const FILTER_OPERATORS = {
247
260
  },
248
261
  $all: (key, paramIndex) => {
249
262
  return {
250
- sql: `CASE WHEN array_length($${paramIndex}::text[], 1) IS NULL THEN false
251
- ELSE (metadata#>'{${parseJsonPathKey(key)}}')::jsonb ?& $${paramIndex}::text[] END`,
263
+ sql: `CASE WHEN array_length($${paramIndex}::text[], 1) IS NULL THEN false
264
+ ELSE (${getJsonExtractExpr(key)})::jsonb ?& $${paramIndex}::text[] END`,
252
265
  needsValue: true
253
266
  };
254
267
  },
255
268
  $elemMatch: (key, paramIndex, value) => {
256
269
  const { sql, values } = buildElemMatchConditions(value, paramIndex);
257
- const jsonPathKey = parseJsonPathKey(key);
270
+ const jsonExtract = getJsonExtractExpr(key);
258
271
  return {
259
272
  sql: `(
260
273
  CASE
261
- WHEN jsonb_typeof(metadata->'${jsonPathKey}') = 'array' THEN
274
+ WHEN jsonb_typeof(${jsonExtract}) = 'array' THEN
262
275
  EXISTS (
263
- SELECT 1
264
- FROM jsonb_array_elements(metadata->'${jsonPathKey}') as elem
276
+ SELECT 1
277
+ FROM jsonb_array_elements(${jsonExtract}) as elem
265
278
  WHERE ${sql}
266
279
  )
267
280
  ELSE FALSE
@@ -291,7 +304,7 @@ const FILTER_OPERATORS = {
291
304
  needsValue: false
292
305
  }),
293
306
  $not: (key) => ({
294
- sql: `NOT (${key})`,
307
+ sql: `(${key})`,
295
308
  needsValue: false
296
309
  }),
297
310
  $nor: (key) => ({
@@ -300,16 +313,17 @@ const FILTER_OPERATORS = {
300
313
  }),
301
314
  $regex: (key, paramIndex) => {
302
315
  return {
303
- sql: `metadata#>>'{${parseJsonPathKey(key)}}' ~ $${paramIndex}`,
316
+ sql: `${getTextExtractExpr(key)} ~ $${paramIndex}`,
304
317
  needsValue: true
305
318
  };
306
319
  },
307
320
  $contains: (key, paramIndex, value) => {
308
- const jsonPathKey = parseJsonPathKey(key);
321
+ const textExtract = getTextExtractExpr(key);
322
+ const jsonExtract = getJsonExtractExpr(key);
309
323
  let sql;
310
- if (Array.isArray(value)) sql = `(metadata->'${jsonPathKey}') ?& $${paramIndex}`;
311
- else if (typeof value === "string") sql = `metadata->>'${jsonPathKey}' ILIKE '%' || $${paramIndex} || '%' ESCAPE '\\'`;
312
- else sql = `metadata->>'${jsonPathKey}' = $${paramIndex}`;
324
+ if (Array.isArray(value)) sql = `(${jsonExtract}) ?& $${paramIndex}`;
325
+ else if (typeof value === "string") sql = `${textExtract} ILIKE '%' || $${paramIndex} || '%' ESCAPE '\\'`;
326
+ else sql = `${textExtract} = $${paramIndex}`;
313
327
  return {
314
328
  sql,
315
329
  needsValue: true,
@@ -321,12 +335,12 @@ const FILTER_OPERATORS = {
321
335
  * Usage: { field: { $objectContains: { ...subobject } } }
322
336
  */
323
337
  $size: (key, paramIndex) => {
324
- const jsonPathKey = parseJsonPathKey(key);
338
+ const jsonExtract = getJsonExtractExpr(key);
325
339
  return {
326
340
  sql: `(
327
341
  CASE
328
- WHEN jsonb_typeof(metadata#>'{${jsonPathKey}}') = 'array' THEN
329
- jsonb_array_length(metadata#>'{${jsonPathKey}}') = $${paramIndex}
342
+ WHEN jsonb_typeof(${jsonExtract}) = 'array' THEN
343
+ jsonb_array_length(${jsonExtract}) = $${paramIndex}
330
344
  ELSE FALSE
331
345
  END
332
346
  )`,
@@ -354,7 +368,7 @@ function buildDeleteFilterQuery(filter) {
354
368
  ].includes(key)) return handleLogicalOperator(key, value, parentPath);
355
369
  if (!value || typeof value !== "object") {
356
370
  values.push(value);
357
- return `metadata#>>'{${parseJsonPathKey(key)}}' = $${values.length}`;
371
+ return `${getTextExtractExpr(key)} = $${values.length}`;
358
372
  }
359
373
  const entries = Object.entries(value);
360
374
  if (entries.length > 1) return entries.map(([operator, operatorValue]) => {
@@ -445,7 +459,7 @@ function buildFilterQuery(filter, minScore, topK) {
445
459
  ].includes(key)) return handleLogicalOperator(key, value, parentPath);
446
460
  if (!value || typeof value !== "object") {
447
461
  values.push(value);
448
- return `metadata#>>'{${parseJsonPathKey(key)}}' = $${values.length}`;
462
+ return `${getTextExtractExpr(key)} = $${values.length}`;
449
463
  }
450
464
  const entries = Object.entries(value);
451
465
  if (entries.length > 1) return entries.map(([operator, operatorValue]) => {
@@ -1778,16 +1792,21 @@ var PoolAdapter = class {
1778
1792
  const client = await this.$pool.connect();
1779
1793
  try {
1780
1794
  await client.query("BEGIN");
1781
- const result = await callback(new TransactionClient(client));
1782
- await client.query("COMMIT");
1783
- return result;
1784
- } catch (error) {
1795
+ const txClient = new TransactionClient(client);
1785
1796
  try {
1786
- await client.query("ROLLBACK");
1787
- } catch (rollbackError) {
1788
- console.error("Transaction rollback failed:", rollbackError);
1797
+ const result = await callback(txClient);
1798
+ await txClient.drain();
1799
+ await client.query("COMMIT");
1800
+ return result;
1801
+ } catch (error) {
1802
+ await txClient.drain().catch(() => void 0);
1803
+ try {
1804
+ await client.query("ROLLBACK");
1805
+ } catch (rollbackError) {
1806
+ console.error("Transaction rollback failed:", rollbackError);
1807
+ }
1808
+ throw error;
1789
1809
  }
1790
- throw error;
1791
1810
  } finally {
1792
1811
  client.release();
1793
1812
  }
@@ -1795,41 +1814,85 @@ var PoolAdapter = class {
1795
1814
  };
1796
1815
  /**
1797
1816
  * Transaction client that wraps a PoolClient for executing queries within a transaction.
1817
+ *
1818
+ * Query methods are serialized through a tail promise (same pattern as
1819
+ * PinnedClientAdapter). Callers such as memory.updateMessages historically
1820
+ * did `queries.push(t.none(...))` then `await t.batch(queries)` — each
1821
+ * `t.none()` is async and starts `client.query` immediately, so by the time
1822
+ * batch runs, N queries are already in flight on one PoolClient. pg@8 queues
1823
+ * those internally and emits a DeprecationWarning; pg@9 will throw.
1824
+ * (#20820)
1798
1825
  */
1799
1826
  var TransactionClient = class {
1800
1827
  client;
1828
+ /**
1829
+ * Serialization tail. Without this gate, concurrent t.none()/t.query()
1830
+ * from Promise.all / batch land on the same PoolClient at once.
1831
+ */
1832
+ #tail = Promise.resolve();
1833
+ #error;
1801
1834
  constructor(client) {
1802
1835
  this.client = client;
1803
1836
  }
1804
- async none(query, values) {
1805
- await this.client.query(query, values);
1806
- return null;
1837
+ #enqueue(fn) {
1838
+ const next = this.#tail.then(fn);
1839
+ this.#tail = next.then(() => void 0, (error) => {
1840
+ this.#error ??= { value: error };
1841
+ });
1842
+ return next;
1807
1843
  }
1808
- async one(query, values) {
1809
- const result = await this.client.query(query, values);
1810
- if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1811
- if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
1812
- return result.rows[0];
1844
+ /**
1845
+ * Wait until every enqueued query has settled and surface the first failure.
1846
+ * PoolAdapter / PinnedClientAdapter call this before COMMIT/ROLLBACK so
1847
+ * those control statements never overlap in-flight work on the same client.
1848
+ */
1849
+ async drain() {
1850
+ await this.#tail;
1851
+ if (this.#error) {
1852
+ const { value } = this.#error;
1853
+ this.#error = void 0;
1854
+ throw value;
1855
+ }
1813
1856
  }
1814
- async oneOrNone(query, values) {
1815
- const result = await this.client.query(query, values);
1816
- if (result.rows.length === 0) return null;
1817
- if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
1818
- return result.rows[0];
1857
+ none(query, values) {
1858
+ return this.#enqueue(async () => {
1859
+ await this.client.query(query, values);
1860
+ return null;
1861
+ });
1819
1862
  }
1820
- async any(query, values) {
1821
- return (await this.client.query(query, values)).rows;
1863
+ one(query, values) {
1864
+ return this.#enqueue(async () => {
1865
+ const result = await this.client.query(query, values);
1866
+ if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1867
+ if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
1868
+ return result.rows[0];
1869
+ });
1822
1870
  }
1823
- async manyOrNone(query, values) {
1871
+ oneOrNone(query, values) {
1872
+ return this.#enqueue(async () => {
1873
+ const result = await this.client.query(query, values);
1874
+ if (result.rows.length === 0) return null;
1875
+ if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
1876
+ return result.rows[0];
1877
+ });
1878
+ }
1879
+ any(query, values) {
1880
+ return this.#enqueue(async () => {
1881
+ return (await this.client.query(query, values)).rows;
1882
+ });
1883
+ }
1884
+ manyOrNone(query, values) {
1824
1885
  return this.any(query, values);
1825
1886
  }
1826
- async many(query, values) {
1827
- const result = await this.client.query(query, values);
1828
- if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1829
- return result.rows;
1887
+ many(query, values) {
1888
+ return this.#enqueue(async () => {
1889
+ const result = await this.client.query(query, values);
1890
+ if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
1891
+ return result.rows;
1892
+ });
1830
1893
  }
1831
- async query(query, values) {
1832
- return this.client.query(query, values);
1894
+ query(query, values) {
1895
+ return this.#enqueue(() => this.client.query(query, values));
1833
1896
  }
1834
1897
  async batch(promises) {
1835
1898
  return Promise.all(promises);
@@ -1922,11 +1985,14 @@ var PinnedClientAdapter = class {
1922
1985
  tx(callback) {
1923
1986
  return this.#enqueue(async () => {
1924
1987
  await this.pinnedClient.query("BEGIN");
1988
+ const txClient = new TransactionClient(this.pinnedClient);
1925
1989
  try {
1926
- const result = await callback(new TransactionClient(this.pinnedClient));
1990
+ const result = await callback(txClient);
1991
+ await txClient.drain();
1927
1992
  await this.pinnedClient.query("COMMIT");
1928
1993
  return result;
1929
1994
  } catch (error) {
1995
+ await txClient.drain().catch(() => void 0);
1930
1996
  try {
1931
1997
  await this.pinnedClient.query("ROLLBACK");
1932
1998
  } catch (rollbackError) {
@@ -6416,7 +6482,13 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
6416
6482
  ifNotExists: [
6417
6483
  "agentVersion",
6418
6484
  "organizationId",
6419
- "projectId"
6485
+ "projectId",
6486
+ "provenance",
6487
+ "runnerAttestation",
6488
+ "experimentSetId",
6489
+ "comparisonId",
6490
+ "variantId",
6491
+ "trialIndex"
6420
6492
  ]
6421
6493
  });
6422
6494
  await this.#db.alterTable({
@@ -6522,6 +6594,16 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
6522
6594
  table: TABLE_EXPERIMENTS,
6523
6595
  columns: ["datasetId"]
6524
6596
  },
6597
+ {
6598
+ name: "idx_experiments_grouping",
6599
+ table: TABLE_EXPERIMENTS,
6600
+ columns: [
6601
+ "experimentSetId",
6602
+ "comparisonId",
6603
+ "variantId",
6604
+ "trialIndex"
6605
+ ]
6606
+ },
6525
6607
  {
6526
6608
  name: "idx_experiment_results_experimentid",
6527
6609
  table: TABLE_EXPERIMENT_RESULTS,
@@ -6567,6 +6649,12 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
6567
6649
  name: row.name ?? void 0,
6568
6650
  description: row.description ?? void 0,
6569
6651
  metadata: row.metadata ? safelyParseJSON(row.metadata) : void 0,
6652
+ provenance: row.provenance ? safelyParseJSON(row.provenance) : null,
6653
+ runnerAttestation: row.runnerAttestation ? safelyParseJSON(row.runnerAttestation) : null,
6654
+ experimentSetId: row.experimentSetId ?? null,
6655
+ comparisonId: row.comparisonId ?? null,
6656
+ variantId: row.variantId ?? null,
6657
+ trialIndex: row.trialIndex != null ? row.trialIndex : null,
6570
6658
  datasetId: row.datasetId ?? null,
6571
6659
  datasetVersion: row.datasetVersion != null ? row.datasetVersion : null,
6572
6660
  agentVersion: row.agentVersion ?? null,
@@ -6620,6 +6708,12 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
6620
6708
  name: input.name ?? null,
6621
6709
  description: input.description ?? null,
6622
6710
  metadata: input.metadata ?? null,
6711
+ provenance: input.provenance ?? null,
6712
+ runnerAttestation: input.runnerAttestation ?? null,
6713
+ experimentSetId: input.experimentSetId ?? null,
6714
+ comparisonId: input.comparisonId ?? null,
6715
+ variantId: input.variantId ?? null,
6716
+ trialIndex: input.trialIndex ?? null,
6623
6717
  datasetId: input.datasetId ?? null,
6624
6718
  datasetVersion: input.datasetVersion ?? null,
6625
6719
  agentVersion: input.agentVersion ?? null,
@@ -6643,6 +6737,12 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
6643
6737
  name: input.name,
6644
6738
  description: input.description,
6645
6739
  metadata: input.metadata,
6740
+ provenance: input.provenance ?? null,
6741
+ runnerAttestation: input.runnerAttestation ?? null,
6742
+ experimentSetId: input.experimentSetId ?? null,
6743
+ comparisonId: input.comparisonId ?? null,
6744
+ variantId: input.variantId ?? null,
6745
+ trialIndex: input.trialIndex ?? null,
6646
6746
  datasetId: input.datasetId ?? null,
6647
6747
  datasetVersion: input.datasetVersion ?? null,
6648
6748
  agentVersion: input.agentVersion ?? null,
@@ -6784,6 +6884,22 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
6784
6884
  conditions.push(`"status" = $${paramIndex++}`);
6785
6885
  queryParams.push(args.status);
6786
6886
  }
6887
+ if (args.experimentSetId !== void 0) {
6888
+ conditions.push(`"experimentSetId" = $${paramIndex++}`);
6889
+ queryParams.push(args.experimentSetId);
6890
+ }
6891
+ if (args.comparisonId !== void 0) {
6892
+ conditions.push(`"comparisonId" = $${paramIndex++}`);
6893
+ queryParams.push(args.comparisonId);
6894
+ }
6895
+ if (args.variantId !== void 0) {
6896
+ conditions.push(`"variantId" = $${paramIndex++}`);
6897
+ queryParams.push(args.variantId);
6898
+ }
6899
+ if (args.trialIndex !== void 0) {
6900
+ conditions.push(`"trialIndex" = $${paramIndex++}`);
6901
+ queryParams.push(args.trialIndex);
6902
+ }
6787
6903
  if (args.filters) {
6788
6904
  const { organizationId, projectId } = args.filters;
6789
6905
  if (organizationId !== void 0) {
@@ -8565,6 +8681,13 @@ function getTableName$3({ indexName, schemaName }) {
8565
8681
  function inPlaceholders(count, startIndex = 1) {
8566
8682
  return Array.from({ length: count }, (_, i) => `$${i + startIndex}`).join(", ");
8567
8683
  }
8684
+ /**
8685
+ * Bind dates as UTC strings because node-postgres serializes Date parameters
8686
+ * for TIMESTAMP columns using the process's local timezone.
8687
+ */
8688
+ function toUtcISOString(date) {
8689
+ return date.toISOString();
8690
+ }
8568
8691
  function dedupeMessagesForSave(messages) {
8569
8692
  const deduped = /* @__PURE__ */ new Map();
8570
8693
  for (const message of messages) {
@@ -8979,6 +9102,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
8979
9102
  hasMore: perPageInput === false ? false : offset + perPage < total
8980
9103
  };
8981
9104
  } catch (error) {
9105
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
8982
9106
  const mastraError = new MastraError({
8983
9107
  id: createStorageErrorId("PG", "LIST_THREADS", "FAILED"),
8984
9108
  domain: ErrorDomain.STORAGE,
@@ -8991,13 +9115,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
8991
9115
  }, error);
8992
9116
  this.logger?.error?.(mastraError.toString());
8993
9117
  this.logger?.trackException(mastraError);
8994
- return {
8995
- threads: [],
8996
- total: 0,
8997
- page,
8998
- perPage: perPageForResponse,
8999
- hasMore: false
9000
- };
9118
+ throw mastraError;
9001
9119
  }
9002
9120
  }
9003
9121
  async saveThread({ thread }) {
@@ -9006,6 +9124,8 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9006
9124
  indexName: TABLE_THREADS,
9007
9125
  schemaName: getSchemaName$3(this.#schema)
9008
9126
  });
9127
+ const createdAt = toUtcISOString(thread.createdAt);
9128
+ const updatedAt = toUtcISOString(thread.updatedAt);
9009
9129
  await this.#db.client.none(`INSERT INTO ${tableName} (
9010
9130
  id,
9011
9131
  "resourceId",
@@ -9028,10 +9148,10 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9028
9148
  thread.resourceId,
9029
9149
  thread.title,
9030
9150
  thread.metadata ? JSON.stringify(thread.metadata) : null,
9031
- thread.createdAt,
9032
- thread.createdAt,
9033
- thread.updatedAt,
9034
- thread.updatedAt
9151
+ createdAt,
9152
+ createdAt,
9153
+ updatedAt,
9154
+ updatedAt
9035
9155
  ]);
9036
9156
  return thread;
9037
9157
  } catch (error) {
@@ -9064,7 +9184,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9064
9184
  ...metadata
9065
9185
  };
9066
9186
  try {
9067
- const now = /* @__PURE__ */ new Date();
9187
+ const nowStr = toUtcISOString(/* @__PURE__ */ new Date());
9068
9188
  const thread = await this.#db.client.one(`UPDATE ${threadTableName}
9069
9189
  SET
9070
9190
  title = $1,
@@ -9076,8 +9196,8 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9076
9196
  `, [
9077
9197
  title,
9078
9198
  mergedMetadata,
9079
- now,
9080
- now,
9199
+ nowStr,
9200
+ nowStr,
9081
9201
  id
9082
9202
  ]);
9083
9203
  return {
@@ -9266,7 +9386,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9266
9386
  }, error);
9267
9387
  this.logger?.error?.(mastraError.toString());
9268
9388
  this.logger?.trackException(mastraError);
9269
- return { messages: [] };
9389
+ throw mastraError;
9270
9390
  }
9271
9391
  }
9272
9392
  async listMessages(args) {
@@ -9392,6 +9512,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9392
9512
  hasMore
9393
9513
  };
9394
9514
  } catch (error) {
9515
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
9395
9516
  const mastraError = new MastraError({
9396
9517
  id: createStorageErrorId("PG", "LIST_MESSAGES", "FAILED"),
9397
9518
  domain: ErrorDomain.STORAGE,
@@ -9403,13 +9524,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9403
9524
  }, error);
9404
9525
  this.logger?.error?.(mastraError.toString());
9405
9526
  this.logger?.trackException(mastraError);
9406
- return {
9407
- messages: [],
9408
- total: 0,
9409
- page,
9410
- perPage: perPageForResponse,
9411
- hasMore: false
9412
- };
9527
+ throw mastraError;
9413
9528
  }
9414
9529
  }
9415
9530
  async listMessagesByResourceId(args) {
@@ -9529,6 +9644,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9529
9644
  hasMore
9530
9645
  };
9531
9646
  } catch (error) {
9647
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
9532
9648
  const mastraError = new MastraError({
9533
9649
  id: createStorageErrorId("PG", "LIST_MESSAGES_BY_RESOURCE_ID", "FAILED"),
9534
9650
  domain: ErrorDomain.STORAGE,
@@ -9537,13 +9653,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9537
9653
  }, error);
9538
9654
  this.logger?.error?.(mastraError.toString());
9539
9655
  this.logger?.trackException(mastraError);
9540
- return {
9541
- messages: [],
9542
- total: 0,
9543
- page,
9544
- perPage: perPageForResponse,
9545
- hasMore: false
9546
- };
9656
+ throw mastraError;
9547
9657
  }
9548
9658
  }
9549
9659
  async saveMessages({ messages }) {
@@ -9579,7 +9689,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9579
9689
  const batch = messagesToSave.slice(offset, offset + MAX_MESSAGES_PER_INSERT);
9580
9690
  const values = [];
9581
9691
  const valuePlaceholders = batch.map((message, messageIndex) => {
9582
- const createdAt = message.createdAt || /* @__PURE__ */ new Date();
9692
+ const createdAt = toUtcISOString(message.createdAt || /* @__PURE__ */ new Date());
9583
9693
  values.push(message.id, message.threadId, typeof message.content === "string" ? message.content : JSON.stringify(message.content), createdAt, createdAt, message.role, message.type || "v2", message.resourceId);
9584
9694
  const paramOffset = messageIndex * MESSAGE_INSERT_BIND_PARAMETERS;
9585
9695
  return `(${Array.from({ length: MESSAGE_INSERT_BIND_PARAMETERS }, (_, paramIndex) => `$${paramOffset + paramIndex + 1}`).join(", ")})`;
@@ -9597,7 +9707,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9597
9707
  indexName: TABLE_THREADS,
9598
9708
  schemaName: getSchemaName$3(this.#schema)
9599
9709
  });
9600
- const now = /* @__PURE__ */ new Date();
9710
+ const now = toUtcISOString(/* @__PURE__ */ new Date());
9601
9711
  for (const threadIdToUpdate of threadIds) await t.none(`UPDATE ${threadTableName}
9602
9712
  SET
9603
9713
  "updatedAt" = $1,
@@ -9749,11 +9859,15 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9749
9859
  };
9750
9860
  }
9751
9861
  async saveResource({ resource }) {
9862
+ const createdAt = toUtcISOString(resource.createdAt);
9863
+ const updatedAt = toUtcISOString(resource.updatedAt);
9752
9864
  await this.#db.insert({
9753
9865
  tableName: TABLE_RESOURCES,
9754
9866
  record: {
9755
9867
  ...resource,
9756
- metadata: JSON.stringify(resource.metadata)
9868
+ metadata: JSON.stringify(resource.metadata),
9869
+ createdAt,
9870
+ updatedAt
9757
9871
  }
9758
9872
  });
9759
9873
  return resource;
@@ -9857,6 +9971,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9857
9971
  }
9858
9972
  const sourceMessages = await t.manyOrNone(messageQuery, messageParams);
9859
9973
  const now = /* @__PURE__ */ new Date();
9974
+ const nowStr = toUtcISOString(now);
9860
9975
  const lastMessageId = sourceMessages.length > 0 ? sourceMessages[sourceMessages.length - 1].id : void 0;
9861
9976
  const cloneMetadata = {
9862
9977
  sourceThreadId,
@@ -9888,10 +10003,10 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9888
10003
  newThread.resourceId,
9889
10004
  newThread.title,
9890
10005
  newThread.metadata ? JSON.stringify(newThread.metadata) : null,
9891
- now,
9892
- now,
9893
- now,
9894
- now
10006
+ nowStr,
10007
+ nowStr,
10008
+ nowStr,
10009
+ nowStr
9895
10010
  ]);
9896
10011
  const clonedMessages = [];
9897
10012
  const messageIdMap = {};
@@ -9904,13 +10019,14 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
9904
10019
  try {
9905
10020
  parsedContent = JSON.parse(normalizedMsg.content);
9906
10021
  } catch {}
10022
+ const createdAt = toUtcISOString(new Date(normalizedMsg.createdAt));
9907
10023
  await t.none(`INSERT INTO ${messageTableName} (id, thread_id, content, "createdAt", "createdAtZ", role, type, "resourceId")
9908
10024
  VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, [
9909
10025
  newMessageId,
9910
10026
  newThreadId,
9911
10027
  typeof normalizedMsg.content === "string" ? normalizedMsg.content : JSON.stringify(normalizedMsg.content),
9912
- normalizedMsg.createdAt,
9913
- normalizedMsg.createdAt,
10028
+ createdAt,
10029
+ createdAt,
9914
10030
  normalizedMsg.role,
9915
10031
  normalizedMsg.type || "v2",
9916
10032
  targetResourceId