@mastra/pg 0.15.2 → 0.15.3-alpha.1

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,23 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 0.15.3-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Postgresql Storage Query Index Performance: Adds index operations and automatic indexing for Postgresql ([#7757](https://github.com/mastra-ai/mastra/pull/7757))
8
+
9
+ - Updated dependencies [[`60c9cec`](https://github.com/mastra-ai/mastra/commit/60c9cec7048a79a87440f7840c383875bd710d93), [`897995e`](https://github.com/mastra-ai/mastra/commit/897995e630d572fe2891e7ede817938cabb43251)]:
10
+ - @mastra/core@0.16.4-alpha.2
11
+
12
+ ## 0.15.3-alpha.0
13
+
14
+ ### Patch Changes
15
+
16
+ - Add resource id to workflow run snapshots ([#7740](https://github.com/mastra-ai/mastra/pull/7740))
17
+
18
+ - Updated dependencies [[`547c621`](https://github.com/mastra-ai/mastra/commit/547c62104af3f7a551b3754e9cbdf0a3fbba15e4)]:
19
+ - @mastra/core@0.16.4-alpha.1
20
+
3
21
  ## 0.15.2
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -160,6 +160,129 @@ Example filter:
160
160
  - `getMessages(threadId)`: Get all messages for a thread
161
161
  - `deleteMessages(messageIds)`: Delete specific messages
162
162
 
163
+ ## Index Management
164
+
165
+ The PostgreSQL store provides comprehensive index management capabilities to optimize query performance.
166
+
167
+ ### Automatic Performance Indexes
168
+
169
+ PostgreSQL storage automatically creates composite indexes during initialization for common query patterns:
170
+
171
+ - `mastra_threads_resourceid_createdat_idx`: (resourceId, createdAt DESC)
172
+ - `mastra_messages_thread_id_createdat_idx`: (thread_id, createdAt DESC)
173
+ - `mastra_traces_name_starttime_idx`: (name, startTime DESC)
174
+ - `mastra_evals_agent_name_created_at_idx`: (agent_name, created_at DESC)
175
+
176
+ These indexes significantly improve performance for filtered queries with sorting.
177
+
178
+ ### Creating Custom Indexes
179
+
180
+ Create additional indexes to optimize specific query patterns:
181
+
182
+ ```typescript
183
+ // Basic index for common queries
184
+ await store.createIndex({
185
+ name: 'idx_threads_resource',
186
+ table: 'mastra_threads',
187
+ columns: ['resourceId'],
188
+ });
189
+
190
+ // Composite index with sort order for filtering + sorting
191
+ await store.createIndex({
192
+ name: 'idx_messages_composite',
193
+ table: 'mastra_messages',
194
+ columns: ['thread_id', 'createdAt DESC'],
195
+ });
196
+
197
+ // GIN index for JSONB columns (fast JSON queries)
198
+ await store.createIndex({
199
+ name: 'idx_traces_attributes',
200
+ table: 'mastra_traces',
201
+ columns: ['attributes'],
202
+ method: 'gin',
203
+ });
204
+ ```
205
+
206
+ For more advanced use cases, you can also use:
207
+
208
+ - `unique: true` for unique constraints
209
+ - `where: 'condition'` for partial indexes
210
+ - `method: 'brin'` for time-series data
211
+ - `storage: { fillfactor: 90 }` for update-heavy tables
212
+ - `concurrent: true` for non-blocking creation (default)
213
+
214
+ ### Managing Indexes
215
+
216
+ ```typescript
217
+ // List all indexes
218
+ const allIndexes = await store.listIndexes();
219
+
220
+ // List indexes for specific table
221
+ const threadIndexes = await store.listIndexes('mastra_threads');
222
+
223
+ // Get detailed statistics for an index
224
+ const stats = await store.describeIndex('idx_threads_resource');
225
+ console.log(stats);
226
+ // {
227
+ // name: 'idx_threads_resource',
228
+ // table: 'mastra_threads',
229
+ // columns: ['resourceId', 'createdAt'],
230
+ // unique: false,
231
+ // size: '128 KB',
232
+ // definition: 'CREATE INDEX idx_threads_resource...',
233
+ // method: 'btree',
234
+ // scans: 1542, // Number of index scans
235
+ // tuples_read: 45230, // Tuples read via index
236
+ // tuples_fetched: 12050 // Tuples fetched via index
237
+ // }
238
+
239
+ // Drop an index
240
+ await store.dropIndex('idx_threads_status');
241
+ ```
242
+
243
+ ### Index Types and Use Cases
244
+
245
+ | Index Type | Best For | Storage | Speed |
246
+ | ------------------- | --------------------------------------- | ---------- | -------------------------- |
247
+ | **btree** (default) | Range queries, sorting, general purpose | Moderate | Fast |
248
+ | **hash** | Equality comparisons only | Small | Very fast for `=` |
249
+ | **gin** | JSONB, arrays, full-text search | Large | Fast for contains |
250
+ | **gist** | Geometric data, full-text search | Moderate | Fast for nearest-neighbor |
251
+ | **spgist** | Non-balanced data, text patterns | Small | Fast for specific patterns |
252
+ | **brin** | Large tables with natural ordering | Very small | Fast for ranges |
253
+
254
+ ### Index Options
255
+
256
+ - `name` (required): Index name
257
+ - `table` (required): Table name
258
+ - `columns` (required): Array of column names (can include DESC/ASC)
259
+ - `unique`: Create unique index (default: false)
260
+ - `concurrent`: Non-blocking index creation (default: true)
261
+ - `where`: Partial index condition
262
+ - `method`: Index type ('btree' | 'hash' | 'gin' | 'gist' | 'spgist' | 'brin')
263
+ - `opclass`: Operator class for GIN/GIST indexes
264
+ - `storage`: Storage parameters (e.g., { fillfactor: 90 })
265
+ - `tablespace`: Tablespace name for index placement
266
+
267
+ ### Monitoring Index Performance
268
+
269
+ ```typescript
270
+ // Check index usage statistics
271
+ const stats = await store.describeIndex('idx_threads_resource');
272
+
273
+ // Identify unused indexes
274
+ if (stats.scans === 0) {
275
+ console.log(`Index ${stats.name} is unused - consider removing`);
276
+ await store.dropIndex(stats.name);
277
+ }
278
+
279
+ // Monitor index efficiency
280
+ const efficiency = stats.tuples_fetched / stats.tuples_read;
281
+ if (efficiency < 0.5) {
282
+ console.log(`Index ${stats.name} has low efficiency: ${efficiency}`);
283
+ }
284
+ ```
285
+
163
286
  ## Related Links
164
287
 
165
288
  - [pgvector Documentation](https://github.com/pgvector/pgvector)
package/dist/index.cjs CHANGED
@@ -2374,6 +2374,303 @@ var StoreOperationsPG = class extends storage.StoreOperations {
2374
2374
  );
2375
2375
  }
2376
2376
  }
2377
+ /**
2378
+ * Create a new index on a table
2379
+ */
2380
+ async createIndex(options) {
2381
+ try {
2382
+ const {
2383
+ name,
2384
+ table,
2385
+ columns,
2386
+ unique = false,
2387
+ concurrent = true,
2388
+ where,
2389
+ method = "btree",
2390
+ opclass,
2391
+ storage,
2392
+ tablespace
2393
+ } = options;
2394
+ const schemaName = this.schemaName || "public";
2395
+ const fullTableName = getTableName({
2396
+ indexName: table,
2397
+ schemaName: getSchemaName(this.schemaName)
2398
+ });
2399
+ const indexExists = await this.client.oneOrNone(
2400
+ `SELECT 1 FROM pg_indexes
2401
+ WHERE indexname = $1
2402
+ AND schemaname = $2`,
2403
+ [name, schemaName]
2404
+ );
2405
+ if (indexExists) {
2406
+ return;
2407
+ }
2408
+ const uniqueStr = unique ? "UNIQUE " : "";
2409
+ const concurrentStr = concurrent ? "CONCURRENTLY " : "";
2410
+ const methodStr = method !== "btree" ? `USING ${method} ` : "";
2411
+ const columnsStr = columns.map((col) => {
2412
+ if (col.includes(" DESC") || col.includes(" ASC")) {
2413
+ const [colName, ...modifiers] = col.split(" ");
2414
+ if (!colName) {
2415
+ throw new Error(`Invalid column specification: ${col}`);
2416
+ }
2417
+ const quotedCol2 = `"${utils.parseSqlIdentifier(colName, "column name")}" ${modifiers.join(" ")}`;
2418
+ return opclass ? `${quotedCol2} ${opclass}` : quotedCol2;
2419
+ }
2420
+ const quotedCol = `"${utils.parseSqlIdentifier(col, "column name")}"`;
2421
+ return opclass ? `${quotedCol} ${opclass}` : quotedCol;
2422
+ }).join(", ");
2423
+ const whereStr = where ? ` WHERE ${where}` : "";
2424
+ const tablespaceStr = tablespace ? ` TABLESPACE ${tablespace}` : "";
2425
+ let withStr = "";
2426
+ if (storage && Object.keys(storage).length > 0) {
2427
+ const storageParams = Object.entries(storage).map(([key, value]) => `${key} = ${value}`).join(", ");
2428
+ withStr = ` WITH (${storageParams})`;
2429
+ }
2430
+ const sql = `CREATE ${uniqueStr}INDEX ${concurrentStr}${name} ON ${fullTableName} ${methodStr}(${columnsStr})${withStr}${tablespaceStr}${whereStr}`;
2431
+ await this.client.none(sql);
2432
+ } catch (error$1) {
2433
+ if (error$1 instanceof Error && error$1.message.includes("CONCURRENTLY")) {
2434
+ const retryOptions = { ...options, concurrent: false };
2435
+ return this.createIndex(retryOptions);
2436
+ }
2437
+ throw new error.MastraError(
2438
+ {
2439
+ id: "MASTRA_STORAGE_PG_INDEX_CREATE_FAILED",
2440
+ domain: error.ErrorDomain.STORAGE,
2441
+ category: error.ErrorCategory.THIRD_PARTY,
2442
+ details: {
2443
+ indexName: options.name,
2444
+ tableName: options.table
2445
+ }
2446
+ },
2447
+ error$1
2448
+ );
2449
+ }
2450
+ }
2451
+ /**
2452
+ * Drop an existing index
2453
+ */
2454
+ async dropIndex(indexName) {
2455
+ try {
2456
+ const schemaName = this.schemaName || "public";
2457
+ const indexExists = await this.client.oneOrNone(
2458
+ `SELECT 1 FROM pg_indexes
2459
+ WHERE indexname = $1
2460
+ AND schemaname = $2`,
2461
+ [indexName, schemaName]
2462
+ );
2463
+ if (!indexExists) {
2464
+ return;
2465
+ }
2466
+ const sql = `DROP INDEX IF EXISTS ${getSchemaName(this.schemaName)}.${indexName}`;
2467
+ await this.client.none(sql);
2468
+ } catch (error$1) {
2469
+ throw new error.MastraError(
2470
+ {
2471
+ id: "MASTRA_STORAGE_PG_INDEX_DROP_FAILED",
2472
+ domain: error.ErrorDomain.STORAGE,
2473
+ category: error.ErrorCategory.THIRD_PARTY,
2474
+ details: {
2475
+ indexName
2476
+ }
2477
+ },
2478
+ error$1
2479
+ );
2480
+ }
2481
+ }
2482
+ /**
2483
+ * List indexes for a specific table or all tables
2484
+ */
2485
+ async listIndexes(tableName) {
2486
+ try {
2487
+ const schemaName = this.schemaName || "public";
2488
+ let query;
2489
+ let params;
2490
+ if (tableName) {
2491
+ query = `
2492
+ SELECT
2493
+ i.indexname as name,
2494
+ i.tablename as table,
2495
+ i.indexdef as definition,
2496
+ ix.indisunique as is_unique,
2497
+ pg_size_pretty(pg_relation_size(c.oid)) as size,
2498
+ array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns
2499
+ FROM pg_indexes i
2500
+ JOIN pg_class c ON c.relname = i.indexname AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = i.schemaname)
2501
+ JOIN pg_index ix ON ix.indexrelid = c.oid
2502
+ JOIN pg_attribute a ON a.attrelid = ix.indrelid AND a.attnum = ANY(ix.indkey)
2503
+ WHERE i.schemaname = $1
2504
+ AND i.tablename = $2
2505
+ GROUP BY i.indexname, i.tablename, i.indexdef, ix.indisunique, c.oid
2506
+ `;
2507
+ params = [schemaName, tableName];
2508
+ } else {
2509
+ query = `
2510
+ SELECT
2511
+ i.indexname as name,
2512
+ i.tablename as table,
2513
+ i.indexdef as definition,
2514
+ ix.indisunique as is_unique,
2515
+ pg_size_pretty(pg_relation_size(c.oid)) as size,
2516
+ array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns
2517
+ FROM pg_indexes i
2518
+ JOIN pg_class c ON c.relname = i.indexname AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = i.schemaname)
2519
+ JOIN pg_index ix ON ix.indexrelid = c.oid
2520
+ JOIN pg_attribute a ON a.attrelid = ix.indrelid AND a.attnum = ANY(ix.indkey)
2521
+ WHERE i.schemaname = $1
2522
+ GROUP BY i.indexname, i.tablename, i.indexdef, ix.indisunique, c.oid
2523
+ `;
2524
+ params = [schemaName];
2525
+ }
2526
+ const results = await this.client.manyOrNone(query, params);
2527
+ return results.map((row) => {
2528
+ let columns = [];
2529
+ if (typeof row.columns === "string" && row.columns.startsWith("{") && row.columns.endsWith("}")) {
2530
+ const arrayContent = row.columns.slice(1, -1);
2531
+ columns = arrayContent ? arrayContent.split(",") : [];
2532
+ } else if (Array.isArray(row.columns)) {
2533
+ columns = row.columns;
2534
+ }
2535
+ return {
2536
+ name: row.name,
2537
+ table: row.table,
2538
+ columns,
2539
+ unique: row.is_unique || false,
2540
+ size: row.size || "0",
2541
+ definition: row.definition || ""
2542
+ };
2543
+ });
2544
+ } catch (error$1) {
2545
+ throw new error.MastraError(
2546
+ {
2547
+ id: "MASTRA_STORAGE_PG_INDEX_LIST_FAILED",
2548
+ domain: error.ErrorDomain.STORAGE,
2549
+ category: error.ErrorCategory.THIRD_PARTY,
2550
+ details: tableName ? {
2551
+ tableName
2552
+ } : {}
2553
+ },
2554
+ error$1
2555
+ );
2556
+ }
2557
+ }
2558
+ /**
2559
+ * Creates automatic indexes for optimal query performance
2560
+ * These composite indexes cover both filtering and sorting in single index
2561
+ */
2562
+ async createAutomaticIndexes() {
2563
+ try {
2564
+ const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
2565
+ const indexes = [
2566
+ // Composite index for threads (filter + sort)
2567
+ {
2568
+ name: `${schemaPrefix}mastra_threads_resourceid_createdat_idx`,
2569
+ table: storage.TABLE_THREADS,
2570
+ columns: ["resourceId", "createdAt DESC"]
2571
+ },
2572
+ // Composite index for messages (filter + sort)
2573
+ {
2574
+ name: `${schemaPrefix}mastra_messages_thread_id_createdat_idx`,
2575
+ table: storage.TABLE_MESSAGES,
2576
+ columns: ["thread_id", "createdAt DESC"]
2577
+ },
2578
+ // Composite index for traces (filter + sort)
2579
+ {
2580
+ name: `${schemaPrefix}mastra_traces_name_starttime_idx`,
2581
+ table: storage.TABLE_TRACES,
2582
+ columns: ["name", "startTime DESC"]
2583
+ },
2584
+ // Composite index for evals (filter + sort)
2585
+ {
2586
+ name: `${schemaPrefix}mastra_evals_agent_name_created_at_idx`,
2587
+ table: storage.TABLE_EVALS,
2588
+ columns: ["agent_name", "created_at DESC"]
2589
+ }
2590
+ ];
2591
+ for (const indexOptions of indexes) {
2592
+ try {
2593
+ await this.createIndex(indexOptions);
2594
+ } catch (error) {
2595
+ this.logger?.warn?.(`Failed to create index ${indexOptions.name}:`, error);
2596
+ }
2597
+ }
2598
+ } catch (error$1) {
2599
+ throw new error.MastraError(
2600
+ {
2601
+ id: "MASTRA_STORAGE_PG_STORE_CREATE_PERFORMANCE_INDEXES_FAILED",
2602
+ domain: error.ErrorDomain.STORAGE,
2603
+ category: error.ErrorCategory.THIRD_PARTY
2604
+ },
2605
+ error$1
2606
+ );
2607
+ }
2608
+ }
2609
+ /**
2610
+ * Get detailed statistics for a specific index
2611
+ */
2612
+ async describeIndex(indexName) {
2613
+ try {
2614
+ const schemaName = this.schemaName || "public";
2615
+ const query = `
2616
+ SELECT
2617
+ i.indexname as name,
2618
+ i.tablename as table,
2619
+ i.indexdef as definition,
2620
+ ix.indisunique as is_unique,
2621
+ pg_size_pretty(pg_relation_size(c.oid)) as size,
2622
+ array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns,
2623
+ am.amname as method,
2624
+ s.idx_scan as scans,
2625
+ s.idx_tup_read as tuples_read,
2626
+ s.idx_tup_fetch as tuples_fetched
2627
+ FROM pg_indexes i
2628
+ JOIN pg_class c ON c.relname = i.indexname AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = i.schemaname)
2629
+ JOIN pg_index ix ON ix.indexrelid = c.oid
2630
+ JOIN pg_attribute a ON a.attrelid = ix.indrelid AND a.attnum = ANY(ix.indkey)
2631
+ JOIN pg_am am ON c.relam = am.oid
2632
+ LEFT JOIN pg_stat_user_indexes s ON s.indexrelname = i.indexname AND s.schemaname = i.schemaname
2633
+ WHERE i.schemaname = $1
2634
+ AND i.indexname = $2
2635
+ GROUP BY i.indexname, i.tablename, i.indexdef, ix.indisunique, c.oid, am.amname, s.idx_scan, s.idx_tup_read, s.idx_tup_fetch
2636
+ `;
2637
+ const result = await this.client.oneOrNone(query, [schemaName, indexName]);
2638
+ if (!result) {
2639
+ throw new Error(`Index "${indexName}" not found in schema "${schemaName}"`);
2640
+ }
2641
+ let columns = [];
2642
+ if (typeof result.columns === "string" && result.columns.startsWith("{") && result.columns.endsWith("}")) {
2643
+ const arrayContent = result.columns.slice(1, -1);
2644
+ columns = arrayContent ? arrayContent.split(",") : [];
2645
+ } else if (Array.isArray(result.columns)) {
2646
+ columns = result.columns;
2647
+ }
2648
+ return {
2649
+ name: result.name,
2650
+ table: result.table,
2651
+ columns,
2652
+ unique: result.is_unique || false,
2653
+ size: result.size || "0",
2654
+ definition: result.definition || "",
2655
+ method: result.method || "btree",
2656
+ scans: parseInt(result.scans) || 0,
2657
+ tuples_read: parseInt(result.tuples_read) || 0,
2658
+ tuples_fetched: parseInt(result.tuples_fetched) || 0
2659
+ };
2660
+ } catch (error$1) {
2661
+ throw new error.MastraError(
2662
+ {
2663
+ id: "MASTRA_STORAGE_PG_INDEX_DESCRIBE_FAILED",
2664
+ domain: error.ErrorDomain.STORAGE,
2665
+ category: error.ErrorCategory.THIRD_PARTY,
2666
+ details: {
2667
+ indexName
2668
+ }
2669
+ },
2670
+ error$1
2671
+ );
2672
+ }
2673
+ }
2377
2674
  };
2378
2675
  function transformScoreRow(row) {
2379
2676
  return {
@@ -2808,16 +3105,17 @@ var WorkflowsPG = class extends storage.WorkflowsStorage {
2808
3105
  async persistWorkflowSnapshot({
2809
3106
  workflowName,
2810
3107
  runId,
3108
+ resourceId,
2811
3109
  snapshot
2812
3110
  }) {
2813
3111
  try {
2814
3112
  const now = (/* @__PURE__ */ new Date()).toISOString();
2815
3113
  await this.client.none(
2816
- `INSERT INTO ${getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: this.schema })} (workflow_name, run_id, snapshot, "createdAt", "updatedAt")
2817
- VALUES ($1, $2, $3, $4, $5)
3114
+ `INSERT INTO ${getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: this.schema })} (workflow_name, run_id, "resourceId", snapshot, "createdAt", "updatedAt")
3115
+ VALUES ($1, $2, $3, $4, $5, $6)
2818
3116
  ON CONFLICT (workflow_name, run_id) DO UPDATE
2819
- SET snapshot = $3, "updatedAt" = $5`,
2820
- [workflowName, runId, JSON.stringify(snapshot), now, now]
3117
+ SET "resourceId" = $3, snapshot = $4, "updatedAt" = $6`,
3118
+ [workflowName, runId, resourceId, JSON.stringify(snapshot), now, now]
2821
3119
  );
2822
3120
  } catch (error$1) {
2823
3121
  throw new error.MastraError(
@@ -2979,37 +3277,68 @@ var PostgresStore = class extends storage.MastraStorage {
2979
3277
  isConnected = false;
2980
3278
  stores;
2981
3279
  constructor(config) {
3280
+ const isConnectionStringConfig = (cfg) => {
3281
+ return "connectionString" in cfg;
3282
+ };
3283
+ const isHostConfig = (cfg) => {
3284
+ return "host" in cfg && "database" in cfg && "user" in cfg && "password" in cfg;
3285
+ };
3286
+ const isCloudSqlConfig = (cfg) => {
3287
+ return "stream" in cfg || "password" in cfg && typeof cfg.password === "function";
3288
+ };
2982
3289
  try {
2983
- if ("connectionString" in config) {
3290
+ if (isConnectionStringConfig(config)) {
2984
3291
  if (!config.connectionString || typeof config.connectionString !== "string" || config.connectionString.trim() === "") {
2985
3292
  throw new Error(
2986
3293
  "PostgresStore: connectionString must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults."
2987
3294
  );
2988
3295
  }
2989
- } else {
3296
+ } else if (isCloudSqlConfig(config)) ; else if (isHostConfig(config)) {
2990
3297
  const required = ["host", "database", "user", "password"];
2991
3298
  for (const key of required) {
2992
- if (!(key in config) || typeof config[key] !== "string" || config[key].trim() === "") {
3299
+ if (!config[key] || typeof config[key] !== "string" || config[key].trim() === "") {
2993
3300
  throw new Error(
2994
3301
  `PostgresStore: ${key} must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults.`
2995
3302
  );
2996
3303
  }
2997
3304
  }
3305
+ } else {
3306
+ throw new Error(
3307
+ "PostgresStore: invalid config. Provide either {connectionString}, {host,port,database,user,password}, or a pg ClientConfig (e.g., Cloud SQL connector with `stream`)."
3308
+ );
2998
3309
  }
2999
3310
  super({ name: "PostgresStore" });
3000
3311
  this.schema = config.schemaName || "public";
3001
- this.#config = {
3002
- max: config.max,
3003
- idleTimeoutMillis: config.idleTimeoutMillis,
3004
- ...`connectionString` in config ? { connectionString: config.connectionString } : {
3312
+ if (isConnectionStringConfig(config)) {
3313
+ this.#config = {
3314
+ connectionString: config.connectionString,
3315
+ max: config.max,
3316
+ idleTimeoutMillis: config.idleTimeoutMillis
3317
+ };
3318
+ } else if (isCloudSqlConfig(config)) {
3319
+ this.#config = {
3320
+ ...config,
3321
+ max: config.max,
3322
+ idleTimeoutMillis: config.idleTimeoutMillis
3323
+ };
3324
+ } else if (isHostConfig(config)) {
3325
+ this.#config = {
3005
3326
  host: config.host,
3006
3327
  port: config.port,
3007
3328
  database: config.database,
3008
3329
  user: config.user,
3009
3330
  password: config.password,
3010
- ssl: config.ssl
3011
- }
3012
- };
3331
+ ssl: config.ssl,
3332
+ max: config.max,
3333
+ idleTimeoutMillis: config.idleTimeoutMillis
3334
+ };
3335
+ } else {
3336
+ this.#config = {
3337
+ ...config,
3338
+ max: config.max,
3339
+ idleTimeoutMillis: config.idleTimeoutMillis
3340
+ };
3341
+ }
3013
3342
  this.stores = {};
3014
3343
  } catch (e) {
3015
3344
  throw new error.MastraError(
@@ -3045,6 +3374,11 @@ var PostgresStore = class extends storage.MastraStorage {
3045
3374
  memory
3046
3375
  };
3047
3376
  await super.init();
3377
+ try {
3378
+ await operations.createAutomaticIndexes();
3379
+ } catch (indexError) {
3380
+ console.warn("Failed to create indexes:", indexError);
3381
+ }
3048
3382
  } catch (error$1) {
3049
3383
  this.isConnected = false;
3050
3384
  throw new error.MastraError(
@@ -3075,7 +3409,9 @@ var PostgresStore = class extends storage.MastraStorage {
3075
3409
  resourceWorkingMemory: true,
3076
3410
  hasColumn: true,
3077
3411
  createTable: true,
3078
- deleteMessages: true
3412
+ deleteMessages: true,
3413
+ aiTracing: false,
3414
+ indexManagement: true
3079
3415
  };
3080
3416
  }
3081
3417
  /** @deprecated use getEvals instead */
@@ -3211,9 +3547,10 @@ var PostgresStore = class extends storage.MastraStorage {
3211
3547
  async persistWorkflowSnapshot({
3212
3548
  workflowName,
3213
3549
  runId,
3550
+ resourceId,
3214
3551
  snapshot
3215
3552
  }) {
3216
- return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
3553
+ return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
3217
3554
  }
3218
3555
  async loadWorkflowSnapshot({
3219
3556
  workflowName,