@mastra/pg 1.33.0-alpha.1 → 1.33.0-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.
Files changed (38) hide show
  1. package/dist/_types/@internal_core/dist/knowledge-compat/index.d.ts +0 -2
  2. package/dist/_types/@internal_core/dist/memory/index.d.ts +0 -2
  3. package/dist/docs/SKILL.md +1 -1
  4. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  5. package/dist/docs/references/docs-memory-semantic-recall.md +5 -1
  6. package/dist/docs/references/integrations-databases-dynamodb.md +4 -4
  7. package/dist/docs/references/integrations-databases-postgresql.md +4 -4
  8. package/dist/docs/references/reference-memory-memory-class.md +2 -2
  9. package/dist/docs/references/reference-rag-chunking-and-embedding.md +1 -1
  10. package/dist/docs/references/reference-rag-retrieval.md +11 -0
  11. package/dist/docs/references/reference-tools-vector-query-tool.md +1 -0
  12. package/dist/docs/references/reference-vectors-pg.md +1 -1
  13. package/dist/index.cjs +238 -227
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.js +237 -225
  16. package/dist/index.js.map +1 -1
  17. package/dist/shared/pool-error-guard.d.ts +23 -0
  18. package/dist/shared/pool-error-guard.d.ts.map +1 -0
  19. package/dist/shared/test-fixtures/terminate-backend.d.ts +2 -0
  20. package/dist/shared/test-fixtures/terminate-backend.d.ts.map +1 -0
  21. package/dist/storage/db/index.d.ts +14 -0
  22. package/dist/storage/db/index.d.ts.map +1 -1
  23. package/dist/storage/domains/agents/index.d.ts.map +1 -1
  24. package/dist/storage/domains/memory/index.d.ts.map +1 -1
  25. package/dist/storage/domains/observability/index.d.ts +2 -1
  26. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  27. package/dist/storage/domains/observability/v-next/ddl.d.ts +2 -0
  28. package/dist/storage/domains/observability/v-next/ddl.d.ts.map +1 -1
  29. package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
  30. package/dist/storage/domains/observability/v-next/thread-query.d.ts +0 -2
  31. package/dist/storage/domains/observability/v-next/thread-query.d.ts.map +1 -1
  32. package/dist/storage/domains/workflows/index.d.ts +9 -3
  33. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  34. package/dist/storage/factory-storage.d.ts +1 -22
  35. package/dist/storage/factory-storage.d.ts.map +1 -1
  36. package/dist/storage/index.d.ts.map +1 -1
  37. package/dist/vector/index.d.ts.map +1 -1
  38. package/package.json +9 -9
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region \0rolldown/runtime.js
2
+ // \0rolldown/runtime.js
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -20,7 +20,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
20
20
  value: mod,
21
21
  enumerable: true
22
22
  }) : target, mod));
23
- //#endregion
24
23
  let _mastra_core_error = require("@mastra/core/error");
25
24
  let _mastra_core_storage = require("@mastra/core/storage");
26
25
  _mastra_core_storage = __toESM(_mastra_core_storage, 1);
@@ -40,7 +39,7 @@ let _mastra_core_agent = require("@mastra/core/agent");
40
39
  let _mastra_core_evals = require("@mastra/core/evals");
41
40
  let _mastra_core_storage_domains_skills = require("@mastra/core/storage/domains/skills");
42
41
  let util = require("util");
43
- //#region src/shared/config.ts
42
+ // src/shared/config.ts
44
43
  /**
45
44
  * Type guard for pre-configured pg.Pool config
46
45
  */
@@ -87,8 +86,7 @@ const validateConfig = (name, config) => {
87
86
  ]) if (!config[key] || typeof config[key] !== "string" || config[key].trim() === "") throw new Error(`${name}: ${key} must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults.`);
88
87
  } else throw new Error(`${name}: invalid config. Provide either {pool}, {connectionString}, {host,port,database,user,password}, or a pg ClientConfig (e.g., Cloud SQL connector with \`stream\`).`);
89
88
  };
90
- //#endregion
91
- //#region src/shared/pool-config.ts
89
+ // src/shared/pool-config.ts
92
90
  /**
93
91
  * Builds the `pg.Pool` options for a connection-string based config.
94
92
  *
@@ -117,8 +115,40 @@ function buildConnectionStringPoolConfig(config, defaults) {
117
115
  idleTimeoutMillis: config.idleTimeoutMillis ?? defaults.idleTimeoutMillis
118
116
  };
119
117
  }
120
- //#endregion
121
- //#region src/shared/schema-name.ts
118
+ // src/shared/pool-error-guard.ts
119
+ /**
120
+ * A pool-level `error` listener only covers *idle* clients: pg hands ownership
121
+ * of a client to the borrower for the duration of a checkout and takes its own
122
+ * listener off. So a backend restart or network blip that lands on a client
123
+ * mid-transaction reaches an emitter with no listener, and Node escalates that
124
+ * to an uncaughtException that kills the process — the pool handler logs the
125
+ * idle siblings and the borrowed one still brings everything down.
126
+ *
127
+ * Attach a listener once per physical connection instead. `connect` fires when
128
+ * the pool establishes a client, so the client stays covered for its whole life
129
+ * and there is nothing to remove on release.
130
+ *
131
+ * That listener outlives the checkout, so it also sees the failures the pool is
132
+ * already reporting through its own idle listener. Follow `acquire`/`release`
133
+ * to tell the two apart and stay quiet while the client is idle — otherwise one
134
+ * dropped connection is announced twice, the second time as the wrong thing.
135
+ *
136
+ * The pool still discards the failed connection; this only keeps the failure
137
+ * reportable instead of fatal.
138
+ */
139
+ function guardCheckedOutClientErrors(pool, warn = console.warn) {
140
+ const borrowed = /* @__PURE__ */ new WeakSet();
141
+ pool.on("connect", (client) => {
142
+ borrowed.add(client);
143
+ client.on("error", (err) => {
144
+ if (!borrowed.has(client)) return;
145
+ warn(`PostgreSQL: client error while checked out (the pool discards this connection): ${err instanceof Error ? err.message : String(err)}`);
146
+ });
147
+ });
148
+ pool.on("acquire", (client) => borrowed.add(client));
149
+ pool.on("release", (_err, client) => borrowed.delete(client));
150
+ }
151
+ // src/shared/schema-name.ts
122
152
  const POSTGRES_IDENTIFIER_MAX_BYTES = 63;
123
153
  const UNSAFE_SCHEMA_NAME_CHARS = /["'\\$\u0000-\u001f\u007f]/;
124
154
  /**
@@ -145,8 +175,7 @@ function schemaNamePrefix(name) {
145
175
  const sanitized = parseSchemaName(name).replace(/[^A-Za-z0-9_]/g, "_");
146
176
  return /^[0-9]/.test(sanitized) ? `_${sanitized}` : sanitized;
147
177
  }
148
- //#endregion
149
- //#region src/vector/filter.ts
178
+ // src/vector/filter.ts
150
179
  /**
151
180
  * Translates MongoDB-style filters to PG compatible filters.
152
181
  *
@@ -202,8 +231,7 @@ var PGFilterTranslator = class extends _mastra_core_vector_filter.BaseFilterTran
202
231
  return { $regex: flags ? `(?${flags})${pattern}` : pattern };
203
232
  }
204
233
  };
205
- //#endregion
206
- //#region src/vector/sql-builder.ts
234
+ // src/vector/sql-builder.ts
207
235
  const getTextExtractExpr = (key) => {
208
236
  const jsonPathKey = parseJsonPathKey(key);
209
237
  if (!key.includes(".")) return `metadata->>'${jsonPathKey}'`;
@@ -581,8 +609,7 @@ function buildFilterQuery(filter, minScore, topK) {
581
609
  values
582
610
  };
583
611
  }
584
- //#endregion
585
- //#region src/vector/index.ts
612
+ // src/vector/index.ts
586
613
  const DEFAULT_NAMESPACE = "default";
587
614
  const MAX_UPSERT_ROWS_PER_STATEMENT = Math.floor(65535 / 4);
588
615
  var PgVector = class extends _mastra_core_vector.MastraVector {
@@ -649,6 +676,7 @@ var PgVector = class extends _mastra_core_vector.MastraVector {
649
676
  };
650
677
  else throw new Error("PgVector: invalid configuration provided");
651
678
  this.pool = new pg.Pool(poolConfig);
679
+ guardCheckedOutClientErrors(this.pool, (message) => this.logger?.warn?.(message));
652
680
  this.pool.on("error", (err) => {
653
681
  this.logger?.warn?.("PgVector: idle pool client error (pool discards the client and reconnects on next checkout)", { err: err instanceof Error ? err.message : err });
654
682
  });
@@ -2047,8 +2075,7 @@ var PgVector = class extends _mastra_core_vector.MastraVector {
2047
2075
  }
2048
2076
  }
2049
2077
  };
2050
- //#endregion
2051
- //#region src/storage/client.ts
2078
+ // src/storage/client.ts
2052
2079
  /**
2053
2080
  * Truncate a query string for error messages.
2054
2081
  */
@@ -2430,8 +2457,7 @@ function buildConstraintName({ baseName, schemaName, maxLength = 63, hashWhenTru
2430
2457
  }
2431
2458
  return truncateIdentifier(fullName, maxLength);
2432
2459
  }
2433
- //#endregion
2434
- //#region src/storage/db/pg-errors.ts
2460
+ // src/storage/db/pg-errors.ts
2435
2461
  function asPgError(error) {
2436
2462
  return error ?? {};
2437
2463
  }
@@ -2459,8 +2485,7 @@ function isDuplicateSchemaError(error) {
2459
2485
  if (code === "23505" && constraint === "pg_namespace_nspname_index") return true;
2460
2486
  return /schema .* already exists/i.test(message);
2461
2487
  }
2462
- //#endregion
2463
- //#region src/storage/db/sanitize-json.ts
2488
+ // src/storage/db/sanitize-json.ts
2464
2489
  const repair = (value) => value.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "�").replaceAll("\0", "");
2465
2490
  function repairJson(value) {
2466
2491
  if (typeof value === "string") return repair(value);
@@ -2486,8 +2511,7 @@ function toPgJson(value) {
2486
2511
  if (json === void 0 || !/\\u(?:0000|[dD][89a-fA-F][0-9a-fA-F]{2})/.test(json)) return json;
2487
2512
  return JSON.stringify(repairJson(JSON.parse(json)));
2488
2513
  }
2489
- //#endregion
2490
- //#region src/storage/db/schema-snapshot.ts
2514
+ // src/storage/db/schema-snapshot.ts
2491
2515
  /**
2492
2516
  * Returns the snapshot currently installed on `client`, but only when it was
2493
2517
  * taken from the schema the caller operates on. A store configured for another
@@ -2569,8 +2593,7 @@ async function loadSchemaSnapshot(client, schemaName) {
2569
2593
  invalidIndexes
2570
2594
  };
2571
2595
  }
2572
- //#endregion
2573
- //#region src/storage/db/index.ts
2596
+ // src/storage/db/index.ts
2574
2597
  const POSTGRES_MAX_BIND_PARAMETERS$1 = 65535;
2575
2598
  /**
2576
2599
  * Resolves PgDomainConfig to a database client and schema.
@@ -2613,6 +2636,7 @@ function resolvePgConfig(config) {
2613
2636
  pool.on("error", (err) => {
2614
2637
  console.warn(`resolvePgConfig: idle pool client error (pool discards the client and reconnects on next checkout): ${err instanceof Error ? err.message : String(err)}`);
2615
2638
  });
2639
+ guardCheckedOutClientErrors(pool);
2616
2640
  const client = new PoolAdapter(pool);
2617
2641
  return {
2618
2642
  client,
@@ -3995,6 +4019,42 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
3995
4019
  }, error);
3996
4020
  }
3997
4021
  }
4022
+ /**
4023
+ * Runs one UPDATE per record in a transaction, changing a row only while every
4024
+ * column in `nullColumns` is still NULL. Never inserts. Returns, in input order,
4025
+ * whether each update changed a row.
4026
+ */
4027
+ async batchUpdateWhereNull({ tableName, updates, nullColumns }) {
4028
+ const nullConditions = nullColumns.map((column) => ` AND "${(0, _mastra_core_utils.parseSqlIdentifier)(column, "column name")}" IS NULL`).join("");
4029
+ try {
4030
+ return await this.client.tx(async (tx) => {
4031
+ const applied = [];
4032
+ for (const update of updates) {
4033
+ const query = await this.buildUpdateQuery({
4034
+ tableName,
4035
+ ...update
4036
+ });
4037
+ if (!query) {
4038
+ applied.push(false);
4039
+ continue;
4040
+ }
4041
+ const rows = await tx.any(`${query.sql}${nullConditions} RETURNING 1`, query.values);
4042
+ applied.push(rows.length > 0);
4043
+ }
4044
+ return applied;
4045
+ });
4046
+ } catch (error) {
4047
+ throw new _mastra_core_error.MastraError({
4048
+ id: (0, _mastra_core_storage.createStorageErrorId)("PG", "BATCH_UPDATE_WHERE_NULL", "FAILED"),
4049
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
4050
+ category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
4051
+ details: {
4052
+ tableName,
4053
+ numberOfRecords: updates.length
4054
+ }
4055
+ }, error);
4056
+ }
4057
+ }
3998
4058
  async batchDelete({ tableName, keys }) {
3999
4059
  try {
4000
4060
  if (keys.length === 0) return;
@@ -4115,9 +4175,14 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
4115
4175
  columns: [column]
4116
4176
  });
4117
4177
  }
4118
- async executeUpdate(client, { tableName, keys, data }) {
4178
+ async executeUpdate(client, args) {
4179
+ const query = await this.buildUpdateQuery(args);
4180
+ if (!query) return;
4181
+ await client.none(query.sql, query.values);
4182
+ }
4183
+ async buildUpdateQuery({ tableName, keys, data }) {
4119
4184
  const filteredData = await this.filterRecordToKnownColumns(tableName, data);
4120
- if (Object.keys(filteredData).length === 0) return;
4185
+ if (Object.keys(filteredData).length === 0) return null;
4121
4186
  const setColumns = [];
4122
4187
  const setValues = [];
4123
4188
  let paramIndex = 1;
@@ -4133,16 +4198,16 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
4133
4198
  whereConditions.push(`"${parsedKey}" = $${paramIndex++}`);
4134
4199
  whereValues.push(this.prepareValue(value, key, tableName));
4135
4200
  });
4136
- const sql = `UPDATE ${getTableName$6({
4137
- indexName: tableName,
4138
- schemaName: getSchemaName$6(this.schemaName)
4139
- })} SET ${setColumns.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
4140
- const values = [...setValues, ...whereValues];
4141
- await client.none(sql, values);
4201
+ return {
4202
+ sql: `UPDATE ${getTableName$6({
4203
+ indexName: tableName,
4204
+ schemaName: getSchemaName$6(this.schemaName)
4205
+ })} SET ${setColumns.join(", ")} WHERE ${whereConditions.join(" AND ")}`,
4206
+ values: [...setValues, ...whereValues]
4207
+ };
4142
4208
  }
4143
4209
  };
4144
- //#endregion
4145
- //#region src/storage/domains/utils.ts
4210
+ // src/storage/domains/utils.ts
4146
4211
  function getSchemaName$5(schema) {
4147
4212
  return schema ? `"${parseSchemaName(schema)}"` : void 0;
4148
4213
  }
@@ -4223,8 +4288,7 @@ function tenancyWhere(filters, startIndex) {
4223
4288
  nextIndex: idx
4224
4289
  };
4225
4290
  }
4226
- //#endregion
4227
- //#region src/storage/domains/agents/index.ts
4291
+ // src/storage/domains/agents/index.ts
4228
4292
  var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
4229
4293
  #db;
4230
4294
  #schema;
@@ -5071,8 +5135,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
5071
5135
  };
5072
5136
  }
5073
5137
  };
5074
- //#endregion
5075
- //#region src/storage/retention.ts
5138
+ // src/storage/retention.ts
5076
5139
  function cutoffFor(policy, anchorType, now = Date.now()) {
5077
5140
  const cutoffMs = (0, _mastra_core_storage.retentionCutoffMs)(policy, now);
5078
5141
  return anchorType === "epoch-ms" ? cutoffMs : new Date(cutoffMs);
@@ -5099,8 +5162,7 @@ function resolveTargets({ policies, descriptor, order }) {
5099
5162
  order
5100
5163
  });
5101
5164
  }
5102
- //#endregion
5103
- //#region src/storage/domains/background-tasks/index.ts
5165
+ // src/storage/domains/background-tasks/index.ts
5104
5166
  function getSchemaName$4(schema) {
5105
5167
  return schema ? `"${schema}"` : "\"public\"";
5106
5168
  }
@@ -5514,8 +5576,7 @@ var BackgroundTasksPG = class BackgroundTasksPG extends _mastra_core_storage.Bac
5514
5576
  return Number(result?.count ?? 0);
5515
5577
  }
5516
5578
  };
5517
- //#endregion
5518
- //#region src/storage/domains/blobs/index.ts
5579
+ // src/storage/domains/blobs/index.ts
5519
5580
  var BlobsPG = class extends _mastra_core_storage.BlobStore {
5520
5581
  #db;
5521
5582
  #schema;
@@ -5617,8 +5678,7 @@ var BlobsPG = class extends _mastra_core_storage.BlobStore {
5617
5678
  };
5618
5679
  }
5619
5680
  };
5620
- //#endregion
5621
- //#region src/storage/domains/channels/index.ts
5681
+ // src/storage/domains/channels/index.ts
5622
5682
  var ChannelsPG = class ChannelsPG extends _mastra_core_storage.ChannelsStorage {
5623
5683
  #db;
5624
5684
  #schema;
@@ -5832,8 +5892,7 @@ var ChannelsPG = class ChannelsPG extends _mastra_core_storage.ChannelsStorage {
5832
5892
  };
5833
5893
  }
5834
5894
  };
5835
- //#endregion
5836
- //#region src/storage/domains/datasets/index.ts
5895
+ // src/storage/domains/datasets/index.ts
5837
5896
  /** Serialize a value for a jsonb column. Returns null for null/undefined. */
5838
5897
  function jsonbArg(value) {
5839
5898
  return value === void 0 || value === null ? null : toPgJson(value);
@@ -7104,8 +7163,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
7104
7163
  await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_DATASETS });
7105
7164
  }
7106
7165
  };
7107
- //#endregion
7108
- //#region src/storage/domains/experiments/index.ts
7166
+ // src/storage/domains/experiments/index.ts
7109
7167
  const DEFAULT_PRUNE_BATCH_SIZE = 1e3;
7110
7168
  var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.ExperimentsStorage {
7111
7169
  #db;
@@ -8051,8 +8109,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
8051
8109
  await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_EXPERIMENTS });
8052
8110
  }
8053
8111
  };
8054
- //#endregion
8055
- //#region src/storage/domains/favorites/index.ts
8112
+ // src/storage/domains/favorites/index.ts
8056
8113
  /**
8057
8114
  * Maps a favorite entity type to its parent entity table.
8058
8115
  */
@@ -8324,8 +8381,7 @@ var FavoritesPG = class FavoritesPG extends _mastra_core_storage.FavoritesStorag
8324
8381
  }
8325
8382
  }
8326
8383
  };
8327
- //#endregion
8328
- //#region ../../packages/_internal-core/dist/knowledge-compat/index.js
8384
+ // ../../packages/_internal-core/dist/knowledge-compat/index.js
8329
8385
  const KNOWLEDGE_V2_CORE_FEATURE = "knowledge-v2";
8330
8386
  /** Hard cap on scope nodes returned by one `listScopeNodes` read. */
8331
8387
  const MAX_KNOWLEDGE_SCOPE_NODES = 1e3;
@@ -8959,8 +9015,7 @@ function createKnowledgeV2CoreLoader(features, loadStorageModule) {
8959
9015
  return knowledgeV2Core;
8960
9016
  };
8961
9017
  }
8962
- //#endregion
8963
- //#region src/storage/domains/knowledge/index.ts
9018
+ // src/storage/domains/knowledge/index.ts
8964
9019
  const loadKnowledgeV2Core = createKnowledgeV2CoreLoader(_mastra_core_features.coreFeatures, () => import("@mastra/core/storage"));
8965
9020
  async function assertKnowledgeDescriptionWithinBoundCompat(description) {
8966
9021
  const { assertKnowledgeDescriptionWithinBound } = await loadKnowledgeV2Core();
@@ -10484,8 +10539,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
10484
10539
  });
10485
10540
  }
10486
10541
  };
10487
- //#endregion
10488
- //#region src/storage/domains/mcp-clients/index.ts
10542
+ // src/storage/domains/mcp-clients/index.ts
10489
10543
  const SNAPSHOT_FIELDS$5 = [
10490
10544
  "name",
10491
10545
  "description",
@@ -11046,8 +11100,7 @@ var MCPClientsPG = class MCPClientsPG extends _mastra_core_storage.MCPClientsSto
11046
11100
  };
11047
11101
  }
11048
11102
  };
11049
- //#endregion
11050
- //#region src/storage/domains/mcp-servers/index.ts
11103
+ // src/storage/domains/mcp-servers/index.ts
11051
11104
  const SNAPSHOT_FIELDS$4 = [
11052
11105
  "name",
11053
11106
  "version",
@@ -11629,8 +11682,7 @@ var MCPServersPG = class MCPServersPG extends _mastra_core_storage.MCPServersSto
11629
11682
  };
11630
11683
  }
11631
11684
  };
11632
- //#endregion
11633
- //#region ../../packages/_internal-core/dist/memory/index.js
11685
+ // ../../packages/_internal-core/dist/memory/index.js
11634
11686
  /**
11635
11687
  * Shared rules for observational memory lifecycle writes. Every storage adapter applies
11636
11688
  * these inside its own atomic section (lock, transaction, or conditional update), so the
@@ -11715,8 +11767,7 @@ function isAppendOnlySince(storedObservations, snapshotObservations) {
11715
11767
  const snapshot = snapshotObservations ?? "";
11716
11768
  return stored === snapshot || stored.startsWith(snapshot);
11717
11769
  }
11718
- //#endregion
11719
- //#region src/storage/db/run-fencing.ts
11770
+ // src/storage/db/run-fencing.ts
11720
11771
  /**
11721
11772
  * Epoch milliseconds on the database clock. `clock_timestamp()` rather than
11722
11773
  * `now()`: a statement can wait on a row lock, and lease math must use the
@@ -11748,8 +11799,7 @@ function withRunFence(client, claimsTable, fence, operation, write) {
11748
11799
  return write(t);
11749
11800
  });
11750
11801
  }
11751
- //#endregion
11752
- //#region src/storage/domains/memory/index.ts
11802
+ // src/storage/domains/memory/index.ts
11753
11803
  /**
11754
11804
  * Local constant for the observational memory table name.
11755
11805
  * Defined locally to avoid a static import that crashes on older @mastra/core
@@ -12030,7 +12080,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
12030
12080
  indexName: OM_TABLE,
12031
12081
  schemaName: quotedSchemaName
12032
12082
  });
12033
- const idxPrefix = schemaPrefix ? `${schemaPrefix}` : "";
12083
+ const idxPrefix = schemaPrefix ? schemaPrefix : "";
12034
12084
  statements.push(`CREATE INDEX IF NOT EXISTS "${idxPrefix}idx_om_lookup_key" ON ${fullOmTableName} ("lookupKey");`);
12035
12085
  }
12036
12086
  for (const idx of MemoryPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
@@ -14581,8 +14631,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
14581
14631
  }
14582
14632
  }
14583
14633
  };
14584
- //#endregion
14585
- //#region src/storage/domains/notifications/index.ts
14634
+ // src/storage/domains/notifications/index.ts
14586
14635
  const COMPOSITE_PRIMARY_KEY$1 = _mastra_core_storage.TABLE_CONFIGS[_mastra_core_storage.TABLE_NOTIFICATIONS].compositePrimaryKey;
14587
14636
  const statusTimestamp = (status, now) => {
14588
14637
  if (status === "delivered") return { deliveredAt: now };
@@ -15085,8 +15134,7 @@ var NotificationsPG = class NotificationsPG extends _mastra_core_storage.Notific
15085
15134
  return row ? rowToNotification(row) : void 0;
15086
15135
  }
15087
15136
  };
15088
- //#endregion
15089
- //#region src/storage/domains/observability/index.ts
15137
+ // src/storage/domains/observability/index.ts
15090
15138
  var ObservabilityPG = class ObservabilityPG extends _mastra_core_storage.ObservabilityStorage {
15091
15139
  /**
15092
15140
  * Retention-eligible tables. The observability domain has a single physical
@@ -15706,30 +15754,33 @@ var ObservabilityPG = class ObservabilityPG extends _mastra_core_storage.Observa
15706
15754
  }, error);
15707
15755
  }
15708
15756
  }
15757
+ #toSpanUpdates(records) {
15758
+ return records.map((record) => {
15759
+ const data = { ...record.updates };
15760
+ if (data.endedAt instanceof Date) {
15761
+ const endedAt = data.endedAt.toISOString();
15762
+ data.endedAt = endedAt;
15763
+ data.endedAtZ = endedAt;
15764
+ }
15765
+ if (data.startedAt instanceof Date) {
15766
+ const startedAt = data.startedAt.toISOString();
15767
+ data.startedAt = startedAt;
15768
+ data.startedAtZ = startedAt;
15769
+ }
15770
+ return {
15771
+ keys: {
15772
+ spanId: record.spanId,
15773
+ traceId: record.traceId
15774
+ },
15775
+ data
15776
+ };
15777
+ });
15778
+ }
15709
15779
  async batchUpdateSpans(args) {
15710
15780
  try {
15711
15781
  return this.#db.batchUpdate({
15712
15782
  tableName: _mastra_core_storage.TABLE_SPANS,
15713
- updates: args.records.map((record) => {
15714
- const data = { ...record.updates };
15715
- if (data.endedAt instanceof Date) {
15716
- const endedAt = data.endedAt.toISOString();
15717
- data.endedAt = endedAt;
15718
- data.endedAtZ = endedAt;
15719
- }
15720
- if (data.startedAt instanceof Date) {
15721
- const startedAt = data.startedAt.toISOString();
15722
- data.startedAt = startedAt;
15723
- data.startedAtZ = startedAt;
15724
- }
15725
- return {
15726
- keys: {
15727
- spanId: record.spanId,
15728
- traceId: record.traceId
15729
- },
15730
- data
15731
- };
15732
- })
15783
+ updates: this.#toSpanUpdates(args.records)
15733
15784
  });
15734
15785
  } catch (error) {
15735
15786
  throw new _mastra_core_error.MastraError({
@@ -15739,6 +15790,25 @@ var ObservabilityPG = class ObservabilityPG extends _mastra_core_storage.Observa
15739
15790
  }, error);
15740
15791
  }
15741
15792
  }
15793
+ async batchUpdateUnendedSpans(args) {
15794
+ try {
15795
+ const applied = await this.#db.batchUpdateWhereNull({
15796
+ tableName: _mastra_core_storage.TABLE_SPANS,
15797
+ updates: this.#toSpanUpdates(args.records),
15798
+ nullColumns: ["endedAt"]
15799
+ });
15800
+ return { updated: args.records.filter((_, index) => applied[index]).map(({ traceId, spanId }) => ({
15801
+ traceId,
15802
+ spanId
15803
+ })) };
15804
+ } catch (error) {
15805
+ throw new _mastra_core_error.MastraError({
15806
+ id: (0, _mastra_core_storage.createStorageErrorId)("PG", "BATCH_UPDATE_UNENDED_SPANS", "FAILED"),
15807
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
15808
+ category: _mastra_core_error.ErrorCategory.USER
15809
+ }, error);
15810
+ }
15811
+ }
15742
15812
  async batchDeleteTraces(args) {
15743
15813
  this.assertUnscopedBatchDeleteTraces(args);
15744
15814
  try {
@@ -15757,8 +15827,7 @@ var ObservabilityPG = class ObservabilityPG extends _mastra_core_storage.Observa
15757
15827
  }
15758
15828
  }
15759
15829
  };
15760
- //#endregion
15761
- //#region src/storage/domains/observability/v-next/signal-schema.ts
15830
+ // src/storage/domains/observability/v-next/signal-schema.ts
15762
15831
  const CURSOR_ID_COLUMN = {
15763
15832
  name: "cursorId",
15764
15833
  type: "bigserial"
@@ -16409,8 +16478,7 @@ const TEXT_ARRAY_COLUMNS = new Set(columnNamesByType(ALL_EVENT_COLUMNS, "text[]"
16409
16478
  const METRIC_TYPED_COLUMNS = typedColumnNames(METRIC_EVENT_COLUMNS);
16410
16479
  const SCORE_TYPED_COLUMNS = typedColumnNames(SCORE_EVENT_COLUMNS);
16411
16480
  const FEEDBACK_TYPED_COLUMNS = typedColumnNames(FEEDBACK_EVENT_COLUMNS);
16412
- //#endregion
16413
- //#region src/storage/domains/observability/v-next/ddl.ts
16481
+ // src/storage/domains/observability/v-next/ddl.ts
16414
16482
  /**
16415
16483
  * Raw DDL for Postgres v-next observability tables.
16416
16484
  *
@@ -16807,8 +16875,7 @@ function additiveColumns(schema) {
16807
16875
  function allIndexDDL(schema) {
16808
16876
  return tableIndexes().map((spec) => indexDDL(schema, spec));
16809
16877
  }
16810
- //#endregion
16811
- //#region src/storage/domains/observability/v-next/discovery.ts
16878
+ // src/storage/domains/observability/v-next/discovery.ts
16812
16879
  const DEFAULT_TTL_SECONDS = 300;
16813
16880
  const DEFAULT_LOOKBACK_SECONDS = 2592e3;
16814
16881
  /** All signal tables that contain a column. Used by cross-signal discovery. */
@@ -17043,8 +17110,7 @@ async function getMetricLabelValues(client, schema, args, config) {
17043
17110
  if (args.limit) filtered = filtered.slice(0, args.limit);
17044
17111
  return { values: filtered };
17045
17112
  }
17046
- //#endregion
17047
- //#region src/storage/domains/observability/v-next/filters.ts
17113
+ // src/storage/domains/observability/v-next/filters.ts
17048
17114
  function newFilterAccumulator(startIndex = 1) {
17049
17115
  return {
17050
17116
  conditions: [],
@@ -17119,8 +17185,7 @@ function applySingleOrArrayFilter(acc, column, value, prefix = "") {
17119
17185
  function whereOrEmpty(acc) {
17120
17186
  return acc.conditions.length ? `WHERE ${acc.conditions.join(" AND ")}` : "";
17121
17187
  }
17122
- //#endregion
17123
- //#region src/storage/domains/observability/v-next/preview-compat.ts
17188
+ // src/storage/domains/observability/v-next/preview-compat.ts
17124
17189
  const generator = _mastra_core_storage.buildStoredPreview;
17125
17190
  const canGeneratePreviews = typeof generator === "function";
17126
17191
  /** SQL detection only; preview formatting stays in TypeScript. Empty strings are intentional. */
@@ -17177,8 +17242,7 @@ function buildSpanQueryResponse(...args) {
17177
17242
  }
17178
17243
  return response;
17179
17244
  }
17180
- //#endregion
17181
- //#region src/storage/domains/observability/v-next/review-status.ts
17245
+ // src/storage/domains/observability/v-next/review-status.ts
17182
17246
  const FEEDBACK_REVIEW_STATUSES = ["needs-review", "reviewed"];
17183
17247
  function isFeedbackReviewStatus(value) {
17184
17248
  return FEEDBACK_REVIEW_STATUSES.some((status) => status === value);
@@ -17202,8 +17266,7 @@ function parseUpdateFeedbackReviewStatusArgs(args) {
17202
17266
  reviewStatus: args.reviewStatus
17203
17267
  };
17204
17268
  }
17205
- //#endregion
17206
- //#region src/storage/domains/observability/v-next/sql.ts
17269
+ // src/storage/domains/observability/v-next/sql.ts
17207
17270
  /**
17208
17271
  * SQL helpers for the v-next Postgres observability domain.
17209
17272
  *
@@ -17333,8 +17396,7 @@ const SCORE_SELECT_COLUMNS = `
17333
17396
  ${buildSelectColumns(SCORE_EVENT_COLUMNS)}`;
17334
17397
  const FEEDBACK_SELECT_COLUMNS = `
17335
17398
  ${buildSelectColumns(FEEDBACK_EVENT_COLUMNS)}`;
17336
- //#endregion
17337
- //#region src/storage/domains/observability/v-next/helpers.ts
17399
+ // src/storage/domains/observability/v-next/helpers.ts
17338
17400
  const PROMOTED_KEYS = /* @__PURE__ */ new Set([
17339
17401
  "experimentId",
17340
17402
  "entityType",
@@ -17771,8 +17833,7 @@ function rowToFeedbackRecord(row) {
17771
17833
  scope: parsedJson(row.scope) ?? void 0
17772
17834
  };
17773
17835
  }
17774
- //#endregion
17775
- //#region src/storage/domains/observability/v-next/polling.ts
17836
+ // src/storage/domains/observability/v-next/polling.ts
17776
17837
  /**
17777
17838
  * Delta-polling helpers for the v-next Postgres observability domain.
17778
17839
  *
@@ -17841,8 +17902,7 @@ function decodeDeltaCursor(cursor) {
17841
17902
  async function readSafeXactHorizon(client) {
17842
17903
  return validatePgInteger((await client.one(`SELECT pg_snapshot_xmin(pg_current_snapshot())::text AS "xactId"`)).xactId);
17843
17904
  }
17844
- //#endregion
17845
- //#region src/storage/domains/observability/v-next/listing.ts
17905
+ // src/storage/domains/observability/v-next/listing.ts
17846
17906
  function responseItems(key, items) {
17847
17907
  return { [key]: items };
17848
17908
  }
@@ -17929,8 +17989,7 @@ async function listSignalDelta(config) {
17929
17989
  deltaCursor
17930
17990
  };
17931
17991
  }
17932
- //#endregion
17933
- //#region src/storage/domains/observability/v-next/olap.ts
17992
+ // src/storage/domains/observability/v-next/olap.ts
17934
17993
  /**
17935
17994
  * Shared OLAP helpers for the v-next Postgres observability domain.
17936
17995
  *
@@ -18134,8 +18193,7 @@ const COMPLEX_GROUP_BY_EXCLUDED = /* @__PURE__ */ new Set([
18134
18193
  "tags",
18135
18194
  "requestContext"
18136
18195
  ]);
18137
- //#endregion
18138
- //#region src/storage/domains/observability/v-next/feedback.ts
18196
+ // src/storage/domains/observability/v-next/feedback.ts
18139
18197
  /**
18140
18198
  * Feedback operations for the v-next Postgres observability domain.
18141
18199
  *
@@ -18373,8 +18431,7 @@ async function getFeedbackPercentiles(client, schema, args) {
18373
18431
  `;
18374
18432
  return { series: percentileSeriesFromRows(await client.manyOrNone(sql, acc.params), args.percentiles) };
18375
18433
  }
18376
- //#endregion
18377
- //#region src/storage/domains/observability/v-next/logs.ts
18434
+ // src/storage/domains/observability/v-next/logs.ts
18378
18435
  /**
18379
18436
  * Log operations for the v-next Postgres observability domain.
18380
18437
  */
@@ -18426,8 +18483,7 @@ async function listLogsDelta(client, table, filters, after, limit) {
18426
18483
  mapRow: rowToLogRecord
18427
18484
  });
18428
18485
  }
18429
- //#endregion
18430
- //#region src/storage/domains/observability/v-next/metrics.ts
18486
+ // src/storage/domains/observability/v-next/metrics.ts
18431
18487
  /**
18432
18488
  * Metric operations for the v-next Postgres observability domain.
18433
18489
  *
@@ -18664,8 +18720,7 @@ async function getMetricPercentiles(client, schema, args) {
18664
18720
  `;
18665
18721
  return { series: percentileSeriesFromRows(await client.manyOrNone(sql, acc.params), args.percentiles) };
18666
18722
  }
18667
- //#endregion
18668
- //#region src/storage/domains/observability/v-next/partitioning.ts
18723
+ // src/storage/domains/observability/v-next/partitioning.ts
18669
18724
  const DEFAULT_FUTURE_DAYS = 14;
18670
18725
  async function detectTimescale(client) {
18671
18726
  const row = await client.oneOrNone(`SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'timescaledb') AS "exists"`);
@@ -18824,8 +18879,7 @@ async function setupPartitioning(client, schema, options = {}) {
18824
18879
  return "native";
18825
18880
  }
18826
18881
  }
18827
- //#endregion
18828
- //#region src/storage/domains/observability/v-next/retention.ts
18882
+ // src/storage/domains/observability/v-next/retention.ts
18829
18883
  /**
18830
18884
  * Age-based retention for the v-next Postgres observability domain.
18831
18885
  *
@@ -18945,8 +18999,7 @@ async function pruneTimescaleTable({ client, schema, table, cutoff, options }) {
18945
18999
  done: true
18946
19000
  };
18947
19001
  }
18948
- //#endregion
18949
- //#region src/storage/domains/observability/v-next/scores.ts
19002
+ // src/storage/domains/observability/v-next/scores.ts
18950
19003
  /**
18951
19004
  * Score operations for the v-next Postgres observability domain.
18952
19005
  *
@@ -19225,8 +19278,7 @@ async function getScorePercentiles(client, schema, args) {
19225
19278
  `;
19226
19279
  return { series: percentileSeriesFromRows(await client.manyOrNone(sql, acc.params), args.percentiles) };
19227
19280
  }
19228
- //#endregion
19229
- //#region src/storage/domains/observability/v-next/trace-query.ts
19281
+ // src/storage/domains/observability/v-next/trace-query.ts
19230
19282
  const TRACE_STATUS_SQL = `CASE WHEN r."error" IS NOT NULL THEN 'error' ELSE 'success' END`;
19231
19283
  /** Core versions without the field reject it in strict query results, so it is only returned when core knows it. */
19232
19284
  const timeToFirstChunkSupported = "timeToFirstChunkMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
@@ -20218,8 +20270,7 @@ function compileSpanQueryPredicate(predicate, offset) {
20218
20270
  function compileThreadQueryPredicate(predicate, offset) {
20219
20271
  return compileScalarPredicate(predicate, Object.fromEntries(Object.keys(_mastra_core_storage.THREAD_QUERY_FIELD_REGISTRY).map((field) => [field, `s."${field}"`])), offset);
20220
20272
  }
20221
- //#endregion
20222
- //#region src/storage/domains/observability/v-next/span-query.ts
20273
+ // src/storage/domains/observability/v-next/span-query.ts
20223
20274
  const identityFields = [
20224
20275
  "organizationId",
20225
20276
  "resourceId",
@@ -20432,8 +20483,7 @@ async function querySpans(client, schema, plan, timeoutMs) {
20432
20483
  return buildSpanQueryResponse(plan, hydrated, payloads, metrics);
20433
20484
  }, { repeatableRead: true });
20434
20485
  }
20435
- //#endregion
20436
- //#region src/storage/domains/observability/v-next/thread-query.ts
20486
+ // src/storage/domains/observability/v-next/thread-query.ts
20437
20487
  const contextFields = [
20438
20488
  "resourceId",
20439
20489
  "userId",
@@ -20597,7 +20647,7 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
20597
20647
  return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${values.length}`;
20598
20648
  }).join(" AND ")})`;
20599
20649
  }));
20600
- const payloads = await run(`SELECT "organizationId", "traceId", "cursorId", "spanType", ${contextFields.map((field) => `"${field}"`).join(", ")},
20650
+ const payloads = await run(`SELECT "organizationId", "traceId", "cursorId", ${contextFields.map((field) => `"${field}"`).join(", ")},
20601
20651
  CASE WHEN "spanType" = 'agent_run' THEN "timeToFirstChunkMs" END AS "timeToFirstChunkMs",
20602
20652
  CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
20603
20653
  ${[
@@ -20612,30 +20662,10 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
20612
20662
  String(version)
20613
20663
  ]);
20614
20664
  const byRoot = new Map(payloads.map((row) => [key(row.organizationId, row.traceId, row.cursorId), row]));
20615
- const agents = page.filter((row) => byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId))?.spanType === "agent_run");
20616
- const models = /* @__PURE__ */ new Map();
20617
- if (agents.length) {
20618
- const modelValues = [];
20619
- const rows = await run(`SELECT DISTINCT ON ("organizationId", "traceId") "organizationId", "traceId",
20620
- CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
20621
- CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider
20622
- FROM ${table} WHERE "spanType" = 'model_generation' AND NOT "isPending" AND (${agents.map((row) => `(${Object.entries({
20623
- organizationId: row.organizationId,
20624
- resourceId: row.resourceId,
20625
- traceId: row.firstTraceId,
20626
- parentSpanId: row.firstSpanId
20627
- }).map(([field, value]) => {
20628
- modelValues.push(value);
20629
- return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${modelValues.length}`;
20630
- }).join(" AND ")})`).join(" OR ")})
20631
- ORDER BY "organizationId", "traceId", "startedAt", "spanId" COLLATE "C", "cursorId" DESC`, modelValues);
20632
- for (const row of rows) models.set(JSON.stringify([row.organizationId, row.traceId]), row);
20633
- }
20634
20665
  const threads = page.flatMap((row) => {
20635
20666
  const first = byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId));
20636
20667
  const last = byRoot.get(key(row.organizationId, row.lastTraceId, row.lastCursorId));
20637
20668
  if (!first || !last) return [];
20638
- const model = models.get(JSON.stringify([row.organizationId, row.firstTraceId]));
20639
20669
  return [_mastra_core_storage.threadQueryRowSchema.parse({
20640
20670
  organizationId: row.organizationId,
20641
20671
  threadId: row.threadId,
@@ -20647,8 +20677,6 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
20647
20677
  endedAt: row.endedAt.toISOString(),
20648
20678
  traceCount: Number(row.traceCount),
20649
20679
  timeToFirstChunkMs: first.timeToFirstChunkMs,
20650
- model: model?.model ?? null,
20651
- provider: model?.provider ?? null,
20652
20680
  inputPreview: readPreview(first.inputPreview, first.input),
20653
20681
  outputPreview: readPreview(last.outputPreview, last.output),
20654
20682
  errorPreview: readPreview(last.errorPreview, last.error)
@@ -20664,8 +20692,7 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
20664
20692
  }) : null }
20665
20693
  };
20666
20694
  }
20667
- //#endregion
20668
- //#region src/storage/domains/observability/v-next/trace-aggregate.ts
20695
+ // src/storage/domains/observability/v-next/trace-aggregate.ts
20669
20696
  /** Trace-root column expressions (alias `r`) for each groupable dimension; same values `where` sees. */
20670
20697
  const DIMENSION_SQL = {
20671
20698
  entityType: "r.\"entityType\"",
@@ -20991,8 +21018,7 @@ async function runAggregate(client, plan, compiled, timeoutMs) {
20991
21018
  truncated
20992
21019
  };
20993
21020
  }
20994
- //#endregion
20995
- //#region src/storage/domains/observability/v-next/traces.ts
21021
+ // src/storage/domains/observability/v-next/traces.ts
20996
21022
  /**
20997
21023
  * Trace / branch list reads for the v-next Postgres observability domain.
20998
21024
  *
@@ -21606,8 +21632,7 @@ async function listBranchesDelta(client, span, filters, after, limit) {
21606
21632
  async function readBranchesStreamHeadCursor(client, span, filters) {
21607
21633
  return encodeDeltaCursor(await readSafeXactHorizon(client), 0);
21608
21634
  }
21609
- //#endregion
21610
- //#region src/storage/domains/observability/v-next/tracing.ts
21635
+ // src/storage/domains/observability/v-next/tracing.ts
21611
21636
  async function writeSpanRows(client, schema, rows) {
21612
21637
  const deduped = dedupeSpanRows(rows);
21613
21638
  const insert = buildInsert(schema, TABLE_SPAN_EVENTS, deduped, spanConflictClause(Object.keys(deduped[0] ?? {})));
@@ -21736,8 +21761,7 @@ async function dangerouslyClearTracing(client, schema) {
21736
21761
  const span = qualifiedTable(schema, TABLE_SPAN_EVENTS);
21737
21762
  await client.none(`TRUNCATE TABLE ${span} RESTART IDENTITY`);
21738
21763
  }
21739
- //#endregion
21740
- //#region src/storage/domains/observability/v-next/index.ts
21764
+ // src/storage/domains/observability/v-next/index.ts
21741
21765
  /**
21742
21766
  * Postgres v-next observability storage domain.
21743
21767
  *
@@ -21825,7 +21849,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
21825
21849
  else if (await detectPartman(this.#client)) mode = "partman";
21826
21850
  else mode = "native";
21827
21851
  const ddlMode = mode === "timescale" ? "timescale" : "partitioned";
21828
- try {
21852
+ if (!await this.#client.oneOrNone("SELECT 1 FROM information_schema.schemata WHERE schema_name = $1", [this.#schema])) try {
21829
21853
  await this.#client.none(schemaDDL(this.#schema));
21830
21854
  } catch (error) {
21831
21855
  if (!isDuplicateSchemaError(error)) throw error;
@@ -22176,8 +22200,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
22176
22200
  }
22177
22201
  }
22178
22202
  };
22179
- //#endregion
22180
- //#region src/storage/domains/prompt-blocks/index.ts
22203
+ // src/storage/domains/prompt-blocks/index.ts
22181
22204
  const SNAPSHOT_FIELDS$3 = [
22182
22205
  "name",
22183
22206
  "description",
@@ -22754,8 +22777,7 @@ var PromptBlocksPG = class PromptBlocksPG extends _mastra_core_storage.PromptBlo
22754
22777
  };
22755
22778
  }
22756
22779
  };
22757
- //#endregion
22758
- //#region src/storage/domains/schedules/index.ts
22780
+ // src/storage/domains/schedules/index.ts
22759
22781
  function getSchemaName$2(schema) {
22760
22782
  return schema ? `"${schema}"` : "\"public\"";
22761
22783
  }
@@ -23123,8 +23145,7 @@ var SchedulesPG = class SchedulesPG extends _mastra_core_storage.SchedulesStorag
23123
23145
  ${limitClause}`, params)).map(rowToTrigger);
23124
23146
  }
23125
23147
  };
23126
- //#endregion
23127
- //#region src/storage/domains/scorer-definitions/index.ts
23148
+ // src/storage/domains/scorer-definitions/index.ts
23128
23149
  const SNAPSHOT_FIELDS$2 = [
23129
23150
  "name",
23130
23151
  "description",
@@ -23724,8 +23745,7 @@ var ScorerDefinitionsPG = class ScorerDefinitionsPG extends _mastra_core_storage
23724
23745
  };
23725
23746
  }
23726
23747
  };
23727
- //#endregion
23728
- //#region src/storage/domains/scores/index.ts
23748
+ // src/storage/domains/scores/index.ts
23729
23749
  /**
23730
23750
  * Appends multi-tenant scope conditions to a query. Mutates `conditions`/`queryParams`.
23731
23751
  * Returns the next positional parameter index.
@@ -24187,8 +24207,7 @@ var ScoresPG = class ScoresPG extends _mastra_core_storage.ScoresStorage {
24187
24207
  }
24188
24208
  }
24189
24209
  };
24190
- //#endregion
24191
- //#region src/storage/domains/skills/index.ts
24210
+ // src/storage/domains/skills/index.ts
24192
24211
  const SNAPSHOT_FIELDS$1 = [
24193
24212
  "name",
24194
24213
  "description",
@@ -24884,8 +24903,7 @@ var SkillsPG = class SkillsPG extends _mastra_core_storage.SkillsStorage {
24884
24903
  };
24885
24904
  }
24886
24905
  };
24887
- //#endregion
24888
- //#region src/storage/domains/thread-state/index.ts
24906
+ // src/storage/domains/thread-state/index.ts
24889
24907
  const COMPOSITE_PRIMARY_KEY = ["threadId", "type"];
24890
24908
  /**
24891
24909
  * PostgreSQL implementation of {@link ThreadStateStorage}.
@@ -25050,8 +25068,7 @@ var ThreadStatePG = class ThreadStatePG extends _mastra_core_storage.ThreadState
25050
25068
  }
25051
25069
  }
25052
25070
  };
25053
- //#endregion
25054
- //#region src/storage/domains/tool-provider-connections/index.ts
25071
+ // src/storage/domains/tool-provider-connections/index.ts
25055
25072
  function normaliseScope(raw) {
25056
25073
  const value = raw == null ? "per-author" : String(raw);
25057
25074
  if (value === "shared") return "shared";
@@ -25306,8 +25323,7 @@ var ToolProviderConnectionsPG = class ToolProviderConnectionsPG extends _mastra_
25306
25323
  }
25307
25324
  }
25308
25325
  };
25309
- //#endregion
25310
- //#region src/storage/domains/workflow-definitions/index.ts
25326
+ // src/storage/domains/workflow-definitions/index.ts
25311
25327
  function rowToDefinition(row) {
25312
25328
  const inputSchema = parseJsonResilient(row.inputSchema);
25313
25329
  const outputSchema = parseJsonResilient(row.outputSchema);
@@ -25507,8 +25523,7 @@ var WorkflowDefinitionsPG = class WorkflowDefinitionsPG extends _mastra_core_sto
25507
25523
  await this.#db.client.none(`DELETE FROM ${tableName} WHERE "id" = $1`, [id]);
25508
25524
  }
25509
25525
  };
25510
- //#endregion
25511
- //#region src/storage/domains/workflows/index.ts
25526
+ // src/storage/domains/workflows/index.ts
25512
25527
  function getSchemaName(schema) {
25513
25528
  return schema ? `"${schema}"` : "\"public\"";
25514
25529
  }
@@ -25645,6 +25660,13 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
25645
25660
  supportsConcurrentUpdates() {
25646
25661
  return true;
25647
25662
  }
25663
+ supportsGuardedSnapshotWrites() {
25664
+ return true;
25665
+ }
25666
+ /** SQL for a snapshot's status. Legacy json/text columns can hold escapes that fail a jsonb cast (#11563). */
25667
+ async #statusExpression(column) {
25668
+ return await this.#db.getColumnType(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, "snapshot") === "jsonb" ? `${column} ->> 'status'` : `regexp_replace(${column}::text, '\\\\u(0000|[Dd][89A-Fa-f][0-9A-Fa-f]{2})', '', 'g')::jsonb ->> 'status'`;
25669
+ }
25648
25670
  parseWorkflowRun(row) {
25649
25671
  let parsedSnapshot = row.snapshot;
25650
25672
  if (typeof parsedSnapshot === "string") try {
@@ -26040,20 +26062,22 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
26040
26062
  }, error);
26041
26063
  }
26042
26064
  }
26043
- async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence }) {
26065
+ async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence, expectedStatus }) {
26044
26066
  try {
26045
26067
  const now = /* @__PURE__ */ new Date();
26046
26068
  const createdAtValue = createdAt ? createdAt : now;
26047
26069
  const updatedAtValue = updatedAt ? updatedAt : now;
26048
26070
  const sanitizedSnapshot = toPgJson(snapshot);
26049
- await withRunFence(this.#db.client, this.#runOwnersTable(), (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "persistWorkflowSnapshot", (q) => q.none(`INSERT INTO ${getTableName({
26071
+ const guard = expectedStatus === void 0 ? "" : ` WHERE ${await this.#statusExpression("t.snapshot")} = ANY($9::text[])`;
26072
+ return await withRunFence(this.#db.client, this.#runOwnersTable(), (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "persistWorkflowSnapshot", (q) => q.oneOrNone(`INSERT INTO ${getTableName({
26050
26073
  indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
26051
26074
  schemaName: getSchemaName(this.#schema)
26052
26075
  })} AS t
26053
26076
  (workflow_name, run_id, "resourceId", snapshot, "createdAt", "updatedAt", "createdAtZ", "updatedAtZ")
26054
26077
  VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
26055
26078
  ON CONFLICT (workflow_name, run_id) DO UPDATE
26056
- SET "resourceId" = COALESCE($3, t."resourceId"), snapshot = $4, "updatedAt" = $6, "updatedAtZ" = $8`, [
26079
+ SET "resourceId" = COALESCE($3, t."resourceId"), snapshot = $4, "updatedAt" = $6, "updatedAtZ" = $8${guard}
26080
+ RETURNING 1 AS written`, [
26057
26081
  workflowName,
26058
26082
  runId,
26059
26083
  resourceId,
@@ -26061,8 +26085,9 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
26061
26085
  createdAtValue,
26062
26086
  updatedAtValue,
26063
26087
  createdAtValue,
26064
- updatedAtValue
26065
- ]));
26088
+ updatedAtValue,
26089
+ ...expectedStatus === void 0 ? [] : [Array.isArray(expectedStatus) ? expectedStatus : [expectedStatus]]
26090
+ ])) !== null;
26066
26091
  } catch (error) {
26067
26092
  if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
26068
26093
  throw new _mastra_core_error.MastraError({
@@ -26072,6 +26097,25 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
26072
26097
  }, error);
26073
26098
  }
26074
26099
  }
26100
+ async loadWorkflowRunStatus({ workflowName, runId }) {
26101
+ try {
26102
+ const statusExpr = await this.#statusExpression("snapshot");
26103
+ return (await this.#db.client.oneOrNone(`SELECT ${statusExpr} AS status FROM ${getTableName({
26104
+ indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
26105
+ schemaName: getSchemaName(this.#schema)
26106
+ })} WHERE "workflow_name" = $1 AND "run_id" = $2 ORDER BY "createdAt" DESC LIMIT 1`, [workflowName, runId]))?.status ?? null;
26107
+ } catch (error) {
26108
+ throw new _mastra_core_error.MastraError({
26109
+ id: (0, _mastra_core_storage.createStorageErrorId)("PG", "LOAD_WORKFLOW_RUN_STATUS", "FAILED"),
26110
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
26111
+ category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
26112
+ details: {
26113
+ workflowName,
26114
+ runId
26115
+ }
26116
+ }, error);
26117
+ }
26118
+ }
26075
26119
  async loadWorkflowSnapshot({ workflowName, runId }) {
26076
26120
  try {
26077
26121
  const result = await this.#db.load({
@@ -26237,8 +26281,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
26237
26281
  }
26238
26282
  }
26239
26283
  };
26240
- //#endregion
26241
- //#region src/storage/domains/workspaces/index.ts
26284
+ // src/storage/domains/workspaces/index.ts
26242
26285
  const SNAPSHOT_FIELDS = [
26243
26286
  "name",
26244
26287
  "description",
@@ -26859,8 +26902,7 @@ var WorkspacesPG = class WorkspacesPG extends _mastra_core_storage.WorkspacesSto
26859
26902
  };
26860
26903
  }
26861
26904
  };
26862
- //#endregion
26863
- //#region src/storage/factory-storage.ts
26905
+ // src/storage/factory-storage.ts
26864
26906
  const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
26865
26907
  const PG_UNIQUE_VIOLATION = "23505";
26866
26908
  const COLUMN_DDL = {
@@ -27152,38 +27194,6 @@ var PgFactoryStorageOps = class {
27152
27194
  * Supports serializable app-table transactions for cross-replica invariant
27153
27195
  * enforcement and `authDatabase()` exposing the shared pool.
27154
27196
  */
27155
- /**
27156
- * A pool-level `error` listener only covers *idle* clients: pg hands ownership
27157
- * of a client to the borrower for the duration of a checkout and takes its own
27158
- * listener off. So a backend restart or network blip that lands on a client
27159
- * mid-transaction reaches an emitter with no listener, and Node escalates that
27160
- * to an uncaughtException that kills the process — the pool handler logs the
27161
- * idle siblings and the borrowed one still brings everything down.
27162
- *
27163
- * Attach a listener once per physical connection instead. `connect` fires when
27164
- * the pool establishes a client, so the client stays covered for its whole life
27165
- * and there is nothing to remove on release.
27166
- *
27167
- * That listener outlives the checkout, so it also sees the failures the pool is
27168
- * already reporting through its own idle listener. Follow `acquire`/`release`
27169
- * to tell the two apart and stay quiet while the client is idle — otherwise one
27170
- * dropped connection is announced twice, the second time as the wrong thing.
27171
- *
27172
- * The pool still discards the failed connection; this only keeps the failure
27173
- * reportable instead of fatal.
27174
- */
27175
- function guardCheckedOutClientErrors(pool, warn = console.warn) {
27176
- const borrowed = /* @__PURE__ */ new WeakSet();
27177
- pool.on("connect", (client) => {
27178
- borrowed.add(client);
27179
- client.on("error", (err) => {
27180
- if (!borrowed.has(client)) return;
27181
- warn(`PgFactoryStorage: client error while checked out (the pool discards this connection): ${err instanceof Error ? err.message : String(err)}`);
27182
- });
27183
- });
27184
- pool.on("acquire", (client) => borrowed.add(client));
27185
- pool.on("release", (_err, client) => borrowed.delete(client));
27186
- }
27187
27197
  var PgFactoryStorage = class extends _mastra_core_storage.FactoryStorage {
27188
27198
  ops;
27189
27199
  #pool;
@@ -27309,8 +27319,7 @@ var PgFactoryStorage = class extends _mastra_core_storage.FactoryStorage {
27309
27319
  }
27310
27320
  }
27311
27321
  };
27312
- //#endregion
27313
- //#region src/storage/index.ts
27322
+ // src/storage/index.ts
27314
27323
  /** Default maximum number of connections in the pool */
27315
27324
  const DEFAULT_MAX_CONNECTIONS = 20;
27316
27325
  /** Default idle timeout in milliseconds */
@@ -27482,6 +27491,7 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
27482
27491
  pool.on("error", (err) => {
27483
27492
  this.logger?.warn?.("PostgresStore: idle pool client error (pool discards the client and reconnects on next checkout)", { err: err instanceof Error ? err.message : err });
27484
27493
  });
27494
+ guardCheckedOutClientErrors(pool, (message) => this.logger?.warn?.(message));
27485
27495
  return pool;
27486
27496
  }
27487
27497
  #buildPool(config) {
@@ -27621,9 +27631,12 @@ var PostgresStoreVNext = class extends PostgresStore {
27621
27631
  const observabilityClient = built.client;
27622
27632
  this.#observabilityPool = built.pool;
27623
27633
  this.#ownsObservabilityPool = built.owned;
27624
- if (built.owned) built.pool.on("error", (err) => {
27625
- this.logger?.warn?.("PostgresStoreVNext: idle observability pool client error (pool discards the client and reconnects on next checkout)", { err: err instanceof Error ? err.message : err });
27626
- });
27634
+ if (built.owned) {
27635
+ guardCheckedOutClientErrors(built.pool, (message) => this.logger?.warn?.(message));
27636
+ built.pool.on("error", (err) => {
27637
+ this.logger?.warn?.("PostgresStoreVNext: idle observability pool client error (pool discards the client and reconnects on next checkout)", { err: err instanceof Error ? err.message : err });
27638
+ });
27639
+ }
27627
27640
  const observability = new ObservabilityStoragePostgresVNext({
27628
27641
  client: observabilityClient,
27629
27642
  schemaName: obsConfig.schemaName ?? config.schemaName,
@@ -27677,8 +27690,7 @@ var PostgresStoreVNext = class extends PostgresStore {
27677
27690
  }
27678
27691
  }
27679
27692
  };
27680
- //#endregion
27681
- //#region src/vector/prompt.ts
27693
+ // src/vector/prompt.ts
27682
27694
  /**
27683
27695
  * Vector store specific prompt that details supported operators and examples.
27684
27696
  * This prompt helps users construct valid filters for PG Vector.
@@ -27780,7 +27792,6 @@ Example Complex Query:
27780
27792
  ]}
27781
27793
  ]
27782
27794
  }`;
27783
- //#endregion
27784
27795
  exports.AgentsPG = AgentsPG;
27785
27796
  exports.BackgroundTasksPG = BackgroundTasksPG;
27786
27797
  exports.BlobsPG = BlobsPG;