@mastra/pg 1.0.0 → 1.1.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.
@@ -376,7 +376,7 @@ The dimension size must match the output dimension of your chosen embedding mode
376
376
 
377
377
  - OpenAI text-embedding-3-small: 1536 dimensions (or custom, e.g., 256)
378
378
  - Cohere embed-multilingual-v3: 1024 dimensions
379
- - Google text-embedding-004: 768 dimensions (or custom)
379
+ - Google gemini-embedding-001: 768 dimensions (or custom)
380
380
 
381
381
  > **Note:**
382
382
  Index dimensions cannot be changed after creation. To use a different model, delete and recreate the index with the new dimension size.
@@ -73,7 +73,7 @@ Filter results based on metadata fields to narrow down the search space. This ap
73
73
 
74
74
  This is useful when you have documents from different sources, time periods, or with specific attributes. Mastra provides a unified MongoDB-style query syntax that works across all supported vector stores.
75
75
 
76
- For detailed information about available operators and syntax, see the [Metadata Filters Reference](https://mastra.ai/reference/v1/rag/metadata-filters).
76
+ For detailed information about available operators and syntax, see the [Metadata Filters Reference](https://mastra.ai/reference/rag/metadata-filters).
77
77
 
78
78
  Basic filtering examples:
79
79
 
@@ -264,7 +264,7 @@ await pineconeQueryTool.execute(
264
264
  );
265
265
  ```
266
266
 
267
- For detailed configuration options and advanced usage, see the [Vector Query Tool Reference](https://mastra.ai/reference/v1/tools/vector-query-tool).
267
+ For detailed configuration options and advanced usage, see the [Vector Query Tool Reference](https://mastra.ai/reference/tools/vector-query-tool).
268
268
 
269
269
  ### Vector Store Prompts
270
270
 
@@ -543,6 +543,6 @@ const relevanceProvider = new ZeroEntropyRelevanceScorer("zerank-1");
543
543
 
544
544
  The re-ranked results combine vector similarity with semantic understanding to improve retrieval quality.
545
545
 
546
- For more details about re-ranking, see the [rerank()](https://mastra.ai/reference/v1/rag/rerankWithScorer) method.
546
+ For more details about re-ranking, see the [rerank()](https://mastra.ai/reference/rag/rerankWithScorer) method.
547
547
 
548
- For graph-based retrieval that follows connections between chunks, see the [GraphRAG](https://mastra.ai/docs/v1/rag/graph-rag) documentation.
548
+ For graph-based retrieval that follows connections between chunks, see the [GraphRAG](https://mastra.ai/docs/rag/graph-rag) documentation.
@@ -357,13 +357,13 @@ const results = await store.query({
357
357
 
358
358
  ## Related
359
359
 
360
- - [Astra](https://mastra.ai/reference/v1/vectors/astra)
361
- - [Chroma](https://mastra.ai/reference/v1/vectors/chroma)
362
- - [Cloudflare Vectorize](https://mastra.ai/reference/v1/vectors/vectorize)
363
- - [libSQL](https://mastra.ai/reference/v1/vectors/libsql)
364
- - [MongoDB](https://mastra.ai/reference/v1/vectors/mongodb)
365
- - [PgStore](https://mastra.ai/reference/v1/vectors/pg)
366
- - [Pinecone](https://mastra.ai/reference/v1/vectors/pinecone)
367
- - [Qdrant](https://mastra.ai/reference/v1/vectors/qdrant)
368
- - [Upstash](https://mastra.ai/reference/v1/vectors/upstash)
369
- - [Amazon S3 Vectors](https://mastra.ai/reference/v1/vectors/s3vectors)
360
+ - [Astra](https://mastra.ai/reference/vectors/astra)
361
+ - [Chroma](https://mastra.ai/reference/vectors/chroma)
362
+ - [Cloudflare Vectorize](https://mastra.ai/reference/vectors/vectorize)
363
+ - [libSQL](https://mastra.ai/reference/vectors/libsql)
364
+ - [MongoDB](https://mastra.ai/reference/vectors/mongodb)
365
+ - [PgStore](https://mastra.ai/reference/vectors/pg)
366
+ - [Pinecone](https://mastra.ai/reference/vectors/pinecone)
367
+ - [Qdrant](https://mastra.ai/reference/vectors/qdrant)
368
+ - [Upstash](https://mastra.ai/reference/vectors/upstash)
369
+ - [Amazon S3 Vectors](https://mastra.ai/reference/vectors/s3vectors)
@@ -15,14 +15,14 @@
15
15
 
16
16
  `MastraCompositeStore` is included in `@mastra/core`:
17
17
 
18
- ```bash
19
- npm install @mastra/core@beta
18
+ ```bash npm2yarn
19
+ npm install @mastra/core@latest
20
20
  ```
21
21
 
22
22
  You'll also need to install the storage providers you want to compose:
23
23
 
24
- ```bash
25
- npm install @mastra/pg@beta @mastra/libsql@beta
24
+ ```bash npm2yarn
25
+ npm install @mastra/pg@latest @mastra/libsql@latest
26
26
  ```
27
27
 
28
28
  ## Storage domains
@@ -159,7 +159,9 @@ const storage = new MastraCompositeStore({
159
159
 
160
160
  ### Specialized storage for observability
161
161
 
162
- Use a time-series database for traces while keeping other data in PostgreSQL:
162
+ Observability data can quickly overwhelm general-purpose databases in production. A single agent interaction can generate hundreds of spans, and high-traffic applications can produce thousands of traces per day.
163
+
164
+ **ClickHouse** is recommended for production observability because it's optimized for high-volume, write-heavy analytics workloads. Use composite storage to route observability to ClickHouse while keeping other data in your primary database:
163
165
 
164
166
  ```typescript
165
167
  import { MastraCompositeStore } from "@mastra/core/storage";
@@ -181,6 +183,10 @@ const storage = new MastraCompositeStore({
181
183
  });
182
184
  ```
183
185
 
186
+ > **Note:**
187
+
188
+ This approach is also required when using storage providers that don't support observability (like Convex, DynamoDB, or Cloudflare). See the [DefaultExporter documentation](https://mastra.ai/docs/observability/tracing/exporters/default#storage-provider-support) for the full list of supported providers.
189
+
184
190
  ---
185
191
 
186
192
  ## Reference: DynamoDB Storage
@@ -189,24 +195,26 @@ const storage = new MastraCompositeStore({
189
195
 
190
196
  The DynamoDB storage implementation provides a scalable and performant NoSQL database solution for Mastra, leveraging a single-table design pattern with [ElectroDB](https://electrodb.dev/).
191
197
 
198
+ > **Observability Not Supported**
199
+ DynamoDB storage **does not support the observability domain**. Traces from the `DefaultExporter` cannot be persisted to DynamoDB, and Mastra Studio's observability features won't work with DynamoDB as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite#specialized-storage-for-observability) to route observability data to a supported provider like ClickHouse or PostgreSQL.
200
+
201
+ > **Item Size Limit**
202
+ DynamoDB enforces a **400 KB maximum item size**. This limit can be exceeded when storing messages with base64-encoded attachments such as images. See [Handling large attachments](https://mastra.ai/docs/memory/storage#handling-large-attachments) for workarounds including uploading attachments to external storage.
203
+
192
204
  ## Features
193
205
 
194
206
  - Efficient single-table design for all Mastra storage needs
195
207
  - Based on ElectroDB for type-safe DynamoDB access
196
208
  - Support for AWS credentials, regions, and endpoints
197
209
  - Compatible with AWS DynamoDB Local for development
198
- - Stores Thread, Message, Trace, Eval, and Workflow data
210
+ - Stores Thread, Message, Eval, and Workflow data
199
211
  - Optimized for serverless environments
200
212
  - Configurable TTL (Time To Live) for automatic data expiration per entity type
201
213
 
202
214
  ## Installation
203
215
 
204
- ```bash
205
- npm install @mastra/dynamodb@beta
206
- # or
207
- pnpm add @mastra/dynamodb@beta
208
- # or
209
- yarn add @mastra/dynamodb@beta
216
+ ```bash npm2yarn
217
+ npm install @mastra/dynamodb@latest
210
218
  ```
211
219
 
212
220
  ## Prerequisites
@@ -440,8 +448,8 @@ The PostgreSQL storage implementation provides a production-ready storage soluti
440
448
 
441
449
  ## Installation
442
450
 
443
- ```bash
444
- npm install @mastra/pg@beta
451
+ ```bash npm2yarn
452
+ npm install @mastra/pg@latest
445
453
  ```
446
454
 
447
455
  ## Usage
@@ -463,22 +471,26 @@ You can instantiate `PostgresStore` in the following ways:
463
471
 
464
472
  ```ts
465
473
  import { PostgresStore } from "@mastra/pg";
474
+ import { Pool } from "pg";
466
475
 
467
- // Using a connection string only
476
+ // Using a connection string
468
477
  const store1 = new PostgresStore({
469
478
  id: 'pg-storage-1',
470
479
  connectionString: "postgresql://user:password@localhost:5432/mydb",
471
480
  });
472
481
 
473
- // Using a connection string with a custom schema name
482
+ // Using a connection string with pool options
474
483
  const store2 = new PostgresStore({
475
484
  id: 'pg-storage-2',
476
485
  connectionString: "postgresql://user:password@localhost:5432/mydb",
477
- schemaName: "custom_schema", // optional
486
+ schemaName: "custom_schema",
487
+ max: 30, // Max pool connections
488
+ idleTimeoutMillis: 60000, // Idle timeout
489
+ ssl: { rejectUnauthorized: false },
478
490
  });
479
491
 
480
492
  // Using individual connection parameters
481
- const store4 = new PostgresStore({
493
+ const store3 = new PostgresStore({
482
494
  id: 'pg-storage-3',
483
495
  host: "localhost",
484
496
  port: 5432,
@@ -487,14 +499,16 @@ const store4 = new PostgresStore({
487
499
  password: "password",
488
500
  });
489
501
 
490
- // Individual parameters with schemaName
491
- const store5 = new PostgresStore({
502
+ // Using a pre-configured pg.Pool (recommended for pool reuse)
503
+ const existingPool = new Pool({
504
+ connectionString: "postgresql://user:password@localhost:5432/mydb",
505
+ max: 20,
506
+ // ... your custom pool configuration
507
+ });
508
+
509
+ const store4 = new PostgresStore({
492
510
  id: 'pg-storage-4',
493
- host: "localhost",
494
- port: 5432,
495
- database: "mydb",
496
- user: "user",
497
- password: "password",
511
+ pool: existingPool,
498
512
  schemaName: "custom_schema", // optional
499
513
  });
500
514
  ```
@@ -513,6 +527,14 @@ The storage implementation handles schema creation and updates automatically. It
513
527
  - `mastra_scorers`: Stores scoring and evaluation data
514
528
  - `mastra_resources`: Stores resource working memory data
515
529
 
530
+ ### Observability
531
+
532
+ PostgreSQL supports observability and can handle low trace volumes. Throughput capacity depends on deployment factors such as hardware, schema design, indexing, and retention policies, and should be validated for your specific environment. For high-volume production environments, consider:
533
+
534
+ - Using the `insert-only` [tracing strategy](https://mastra.ai/docs/observability/tracing/exporters/default#tracing-strategies) to reduce database write operations
535
+ - Setting up table partitioning for efficient data retention
536
+ - Migrating observability to [ClickHouse via composite storage](https://mastra.ai/reference/storage/composite#specialized-storage-for-observability) if you need to scale further
537
+
516
538
  ### Initialization
517
539
 
518
540
  When you pass storage to the Mastra class, `init()` is called automatically before any storage operation:
@@ -552,19 +574,74 @@ const thread = await memoryStore?.getThreadById({ threadId: "..." });
552
574
  > **Note:**
553
575
  If `init()` is not called, tables won't be created and storage operations will fail silently or throw errors.
554
576
 
577
+ ### Using an Existing Pool
578
+
579
+ If you already have a `pg.Pool` in your application (e.g., shared with an ORM or for Row Level Security), you can pass it directly to `PostgresStore`:
580
+
581
+ ```typescript
582
+ import { Pool } from "pg";
583
+ import { PostgresStore } from "@mastra/pg";
584
+
585
+ // Your existing pool (shared across your application)
586
+ const pool = new Pool({
587
+ connectionString: process.env.DATABASE_URL,
588
+ max: 20,
589
+ });
590
+
591
+ const storage = new PostgresStore({
592
+ id: "shared-storage",
593
+ pool: pool,
594
+ });
595
+ ```
596
+
597
+ **Pool lifecycle behavior:**
598
+
599
+ - When you **provide a pool**: Mastra uses your pool but does **not** close it when `store.close()` is called. You manage the pool lifecycle.
600
+ - When Mastra **creates a pool**: Mastra owns the pool and will close it when `store.close()` is called.
601
+
555
602
  ### Direct Database and Pool Access
556
603
 
557
- `PostgresStore` exposes both the underlying database object and the pg-promise instance as public fields:
604
+ `PostgresStore` exposes the underlying database client and pool for advanced use cases:
605
+
606
+ ```typescript
607
+ store.db; // DbClient - query interface with helpers (any, one, tx, etc.)
608
+ store.pool; // pg.Pool - the underlying connection pool
609
+ ```
610
+
611
+ **Using `store.db` for queries:**
558
612
 
559
613
  ```typescript
560
- store.db; // pg-promise database instance
561
- store.pgp; // pg-promise main instance
614
+ // Execute queries with helper methods
615
+ const users = await store.db.any("SELECT * FROM users WHERE active = $1", [true]);
616
+ const user = await store.db.one("SELECT * FROM users WHERE id = $1", [userId]);
617
+ const maybeUser = await store.db.oneOrNone("SELECT * FROM users WHERE email = $1", [email]);
618
+
619
+ // Use transactions
620
+ const result = await store.db.tx(async (t) => {
621
+ await t.none("INSERT INTO logs (message) VALUES ($1)", ["Started"]);
622
+ const data = await t.any("SELECT * FROM items");
623
+ return data;
624
+ });
625
+ ```
626
+
627
+ **Using `store.pool` directly:**
628
+
629
+ ```typescript
630
+ // Get a client for manual connection management
631
+ const client = await store.pool.connect();
632
+ try {
633
+ await client.query("SET LOCAL app.user_id = $1", [userId]);
634
+ const result = await client.query("SELECT * FROM protected_table");
635
+ return result.rows;
636
+ } finally {
637
+ client.release();
638
+ }
562
639
  ```
563
640
 
564
- This enables direct queries and custom transaction management. When using these fields:
641
+ When using these fields:
565
642
 
566
643
  - You are responsible for proper connection and transaction handling.
567
- - Closing the store (`store.close()`) will destroy the associated connection pool.
644
+ - Closing the store (`store.close()`) will destroy the pool only if Mastra created it.
568
645
  - Direct access bypasses any additional logic or validation provided by PostgresStore methods.
569
646
 
570
647
  This approach is intended for advanced scenarios where low-level access is required.
@@ -340,8 +340,8 @@ const response = await agent.generate(
340
340
 
341
341
  For more information on request context, please see:
342
342
 
343
- - [Agent Request Context](https://mastra.ai/docs/v1/server/request-context)
344
- - [Request Context](https://mastra.ai/docs/v1/server/request-context#accessing-values-with-tools)
343
+ - [Agent Request Context](https://mastra.ai/docs/server/request-context)
344
+ - [Request Context](https://mastra.ai/docs/server/request-context#accessing-values-with-tools)
345
345
 
346
346
  ## Usage Without a Mastra Server
347
347
 
@@ -263,8 +263,8 @@ Embeddings are numeric vectors used by memory's `semanticRecall` to retrieve rel
263
263
 
264
264
  Install `fastembed` to get started:
265
265
 
266
- ```bash
267
- npm install @mastra/fastembed@beta
266
+ ```bash npm2yarn
267
+ npm install @mastra/fastembed@latest
268
268
  ```
269
269
 
270
270
  Add the following to your agent:
package/dist/index.cjs CHANGED
@@ -3117,7 +3117,7 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3117
3117
  #skipDefaultIndexes;
3118
3118
  #indexes;
3119
3119
  /** Tables managed by this domain */
3120
- static MANAGED_TABLES = [storage.TABLE_AGENTS];
3120
+ static MANAGED_TABLES = [storage.TABLE_AGENTS, storage.TABLE_AGENT_VERSIONS];
3121
3121
  constructor(config) {
3122
3122
  super();
3123
3123
  const { client, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
@@ -3144,6 +3144,7 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3144
3144
  }
3145
3145
  async init() {
3146
3146
  await this.#db.createTable({ tableName: storage.TABLE_AGENTS, schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENTS] });
3147
+ await this.#db.createTable({ tableName: storage.TABLE_AGENT_VERSIONS, schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENT_VERSIONS] });
3147
3148
  await this.createDefaultIndexes();
3148
3149
  await this.createCustomIndexes();
3149
3150
  }
@@ -3163,6 +3164,7 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3163
3164
  }
3164
3165
  }
3165
3166
  async dangerouslyClearAll() {
3167
+ await this.#db.clearTable({ tableName: storage.TABLE_AGENT_VERSIONS });
3166
3168
  await this.#db.clearTable({ tableName: storage.TABLE_AGENTS });
3167
3169
  }
3168
3170
  parseJson(value, fieldName) {
@@ -3200,11 +3202,14 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3200
3202
  defaultOptions: this.parseJson(row.defaultOptions, "defaultOptions"),
3201
3203
  workflows: this.parseJson(row.workflows, "workflows"),
3202
3204
  agents: this.parseJson(row.agents, "agents"),
3205
+ integrationTools: this.parseJson(row.integrationTools, "integrationTools"),
3203
3206
  inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
3204
3207
  outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
3205
3208
  memory: this.parseJson(row.memory, "memory"),
3206
3209
  scorers: this.parseJson(row.scorers, "scorers"),
3207
3210
  metadata: this.parseJson(row.metadata, "metadata"),
3211
+ ownerId: row.ownerId,
3212
+ activeVersionId: row.activeVersionId,
3208
3213
  createdAt: row.createdAtZ || row.createdAt,
3209
3214
  updatedAt: row.updatedAtZ || row.updatedAt
3210
3215
  };
@@ -3236,10 +3241,12 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3236
3241
  const nowIso = now.toISOString();
3237
3242
  await this.#db.client.none(
3238
3243
  `INSERT INTO ${tableName} (
3239
- id, name, description, instructions, model, tools,
3240
- "defaultOptions", workflows, agents, "inputProcessors", "outputProcessors", memory, scorers, metadata,
3244
+ id, name, description, instructions, model, tools,
3245
+ "defaultOptions", workflows, agents, "integrationTools",
3246
+ "inputProcessors", "outputProcessors", memory, scorers, metadata,
3247
+ "ownerId", "activeVersionId",
3241
3248
  "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
3242
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)`,
3249
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`,
3243
3250
  [
3244
3251
  agent.id,
3245
3252
  agent.name,
@@ -3250,11 +3257,14 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3250
3257
  agent.defaultOptions ? JSON.stringify(agent.defaultOptions) : null,
3251
3258
  agent.workflows ? JSON.stringify(agent.workflows) : null,
3252
3259
  agent.agents ? JSON.stringify(agent.agents) : null,
3260
+ agent.integrationTools ? JSON.stringify(agent.integrationTools) : null,
3253
3261
  agent.inputProcessors ? JSON.stringify(agent.inputProcessors) : null,
3254
3262
  agent.outputProcessors ? JSON.stringify(agent.outputProcessors) : null,
3255
3263
  agent.memory ? JSON.stringify(agent.memory) : null,
3256
3264
  agent.scorers ? JSON.stringify(agent.scorers) : null,
3257
3265
  agent.metadata ? JSON.stringify(agent.metadata) : null,
3266
+ agent.ownerId ?? null,
3267
+ agent.activeVersionId ?? null,
3258
3268
  nowIso,
3259
3269
  nowIso,
3260
3270
  nowIso,
@@ -3342,6 +3352,18 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3342
3352
  setClauses.push(`scorers = $${paramIndex++}`);
3343
3353
  values.push(JSON.stringify(updates.scorers));
3344
3354
  }
3355
+ if (updates.integrationTools !== void 0) {
3356
+ setClauses.push(`"integrationTools" = $${paramIndex++}`);
3357
+ values.push(JSON.stringify(updates.integrationTools));
3358
+ }
3359
+ if (updates.ownerId !== void 0) {
3360
+ setClauses.push(`"ownerId" = $${paramIndex++}`);
3361
+ values.push(updates.ownerId);
3362
+ }
3363
+ if (updates.activeVersionId !== void 0) {
3364
+ setClauses.push(`"activeVersionId" = $${paramIndex++}`);
3365
+ values.push(updates.activeVersionId);
3366
+ }
3345
3367
  if (updates.metadata !== void 0) {
3346
3368
  const mergedMetadata = { ...existingAgent.metadata, ...updates.metadata };
3347
3369
  setClauses.push(`metadata = $${paramIndex++}`);
@@ -3388,6 +3410,7 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3388
3410
  async deleteAgent({ id }) {
3389
3411
  try {
3390
3412
  const tableName = getTableName2({ indexName: storage.TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3413
+ await this.deleteVersionsByAgentId(id);
3391
3414
  await this.#db.client.none(`DELETE FROM ${tableName} WHERE id = $1`, [id]);
3392
3415
  } catch (error$1) {
3393
3416
  throw new error.MastraError(
@@ -3454,6 +3477,234 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3454
3477
  );
3455
3478
  }
3456
3479
  }
3480
+ // ==========================================================================
3481
+ // Agent Version Methods
3482
+ // ==========================================================================
3483
+ async createVersion(input) {
3484
+ try {
3485
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3486
+ const now = /* @__PURE__ */ new Date();
3487
+ const nowIso = now.toISOString();
3488
+ await this.#db.client.none(
3489
+ `INSERT INTO ${tableName} (
3490
+ id, "agentId", "versionNumber", name, snapshot, "changedFields", "changeMessage", "createdAt", "createdAtZ"
3491
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
3492
+ [
3493
+ input.id,
3494
+ input.agentId,
3495
+ input.versionNumber,
3496
+ input.name ?? null,
3497
+ JSON.stringify(input.snapshot),
3498
+ input.changedFields ? JSON.stringify(input.changedFields) : null,
3499
+ input.changeMessage ?? null,
3500
+ nowIso,
3501
+ nowIso
3502
+ ]
3503
+ );
3504
+ return {
3505
+ ...input,
3506
+ createdAt: now
3507
+ };
3508
+ } catch (error$1) {
3509
+ throw new error.MastraError(
3510
+ {
3511
+ id: storage.createStorageErrorId("PG", "CREATE_VERSION", "FAILED"),
3512
+ domain: error.ErrorDomain.STORAGE,
3513
+ category: error.ErrorCategory.THIRD_PARTY,
3514
+ details: { versionId: input.id, agentId: input.agentId }
3515
+ },
3516
+ error$1
3517
+ );
3518
+ }
3519
+ }
3520
+ async getVersion(id) {
3521
+ try {
3522
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3523
+ const result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [id]);
3524
+ if (!result) {
3525
+ return null;
3526
+ }
3527
+ return this.parseVersionRow(result);
3528
+ } catch (error$1) {
3529
+ throw new error.MastraError(
3530
+ {
3531
+ id: storage.createStorageErrorId("PG", "GET_VERSION", "FAILED"),
3532
+ domain: error.ErrorDomain.STORAGE,
3533
+ category: error.ErrorCategory.THIRD_PARTY,
3534
+ details: { versionId: id }
3535
+ },
3536
+ error$1
3537
+ );
3538
+ }
3539
+ }
3540
+ async getVersionByNumber(agentId, versionNumber) {
3541
+ try {
3542
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3543
+ const result = await this.#db.client.oneOrNone(
3544
+ `SELECT * FROM ${tableName} WHERE "agentId" = $1 AND "versionNumber" = $2`,
3545
+ [agentId, versionNumber]
3546
+ );
3547
+ if (!result) {
3548
+ return null;
3549
+ }
3550
+ return this.parseVersionRow(result);
3551
+ } catch (error$1) {
3552
+ throw new error.MastraError(
3553
+ {
3554
+ id: storage.createStorageErrorId("PG", "GET_VERSION_BY_NUMBER", "FAILED"),
3555
+ domain: error.ErrorDomain.STORAGE,
3556
+ category: error.ErrorCategory.THIRD_PARTY,
3557
+ details: { agentId, versionNumber }
3558
+ },
3559
+ error$1
3560
+ );
3561
+ }
3562
+ }
3563
+ async getLatestVersion(agentId) {
3564
+ try {
3565
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3566
+ const result = await this.#db.client.oneOrNone(
3567
+ `SELECT * FROM ${tableName} WHERE "agentId" = $1 ORDER BY "versionNumber" DESC LIMIT 1`,
3568
+ [agentId]
3569
+ );
3570
+ if (!result) {
3571
+ return null;
3572
+ }
3573
+ return this.parseVersionRow(result);
3574
+ } catch (error$1) {
3575
+ throw new error.MastraError(
3576
+ {
3577
+ id: storage.createStorageErrorId("PG", "GET_LATEST_VERSION", "FAILED"),
3578
+ domain: error.ErrorDomain.STORAGE,
3579
+ category: error.ErrorCategory.THIRD_PARTY,
3580
+ details: { agentId }
3581
+ },
3582
+ error$1
3583
+ );
3584
+ }
3585
+ }
3586
+ async listVersions(input) {
3587
+ const { agentId, page = 0, perPage: perPageInput, orderBy } = input;
3588
+ if (page < 0) {
3589
+ throw new error.MastraError(
3590
+ {
3591
+ id: storage.createStorageErrorId("PG", "LIST_VERSIONS", "INVALID_PAGE"),
3592
+ domain: error.ErrorDomain.STORAGE,
3593
+ category: error.ErrorCategory.USER,
3594
+ details: { page }
3595
+ },
3596
+ new Error("page must be >= 0")
3597
+ );
3598
+ }
3599
+ const perPage = storage.normalizePerPage(perPageInput, 20);
3600
+ const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
3601
+ try {
3602
+ const { field, direction } = this.parseVersionOrderBy(orderBy);
3603
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3604
+ const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "agentId" = $1`, [
3605
+ agentId
3606
+ ]);
3607
+ const total = parseInt(countResult.count, 10);
3608
+ if (total === 0) {
3609
+ return {
3610
+ versions: [],
3611
+ total: 0,
3612
+ page,
3613
+ perPage: perPageForResponse,
3614
+ hasMore: false
3615
+ };
3616
+ }
3617
+ const limitValue = perPageInput === false ? total : perPage;
3618
+ const dataResult = await this.#db.client.manyOrNone(
3619
+ `SELECT * FROM ${tableName} WHERE "agentId" = $1 ORDER BY "${field}" ${direction} LIMIT $2 OFFSET $3`,
3620
+ [agentId, limitValue, offset]
3621
+ );
3622
+ const versions = (dataResult || []).map((row) => this.parseVersionRow(row));
3623
+ return {
3624
+ versions,
3625
+ total,
3626
+ page,
3627
+ perPage: perPageForResponse,
3628
+ hasMore: perPageInput === false ? false : offset + perPage < total
3629
+ };
3630
+ } catch (error$1) {
3631
+ throw new error.MastraError(
3632
+ {
3633
+ id: storage.createStorageErrorId("PG", "LIST_VERSIONS", "FAILED"),
3634
+ domain: error.ErrorDomain.STORAGE,
3635
+ category: error.ErrorCategory.THIRD_PARTY,
3636
+ details: { agentId }
3637
+ },
3638
+ error$1
3639
+ );
3640
+ }
3641
+ }
3642
+ async deleteVersion(id) {
3643
+ try {
3644
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3645
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE id = $1`, [id]);
3646
+ } catch (error$1) {
3647
+ throw new error.MastraError(
3648
+ {
3649
+ id: storage.createStorageErrorId("PG", "DELETE_VERSION", "FAILED"),
3650
+ domain: error.ErrorDomain.STORAGE,
3651
+ category: error.ErrorCategory.THIRD_PARTY,
3652
+ details: { versionId: id }
3653
+ },
3654
+ error$1
3655
+ );
3656
+ }
3657
+ }
3658
+ async deleteVersionsByAgentId(agentId) {
3659
+ try {
3660
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3661
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE "agentId" = $1`, [agentId]);
3662
+ } catch (error$1) {
3663
+ throw new error.MastraError(
3664
+ {
3665
+ id: storage.createStorageErrorId("PG", "DELETE_VERSIONS_BY_AGENT_ID", "FAILED"),
3666
+ domain: error.ErrorDomain.STORAGE,
3667
+ category: error.ErrorCategory.THIRD_PARTY,
3668
+ details: { agentId }
3669
+ },
3670
+ error$1
3671
+ );
3672
+ }
3673
+ }
3674
+ async countVersions(agentId) {
3675
+ try {
3676
+ const tableName = getTableName2({ indexName: storage.TABLE_AGENT_VERSIONS, schemaName: getSchemaName2(this.#schema) });
3677
+ const result = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${tableName} WHERE "agentId" = $1`, [
3678
+ agentId
3679
+ ]);
3680
+ return parseInt(result.count, 10);
3681
+ } catch (error$1) {
3682
+ throw new error.MastraError(
3683
+ {
3684
+ id: storage.createStorageErrorId("PG", "COUNT_VERSIONS", "FAILED"),
3685
+ domain: error.ErrorDomain.STORAGE,
3686
+ category: error.ErrorCategory.THIRD_PARTY,
3687
+ details: { agentId }
3688
+ },
3689
+ error$1
3690
+ );
3691
+ }
3692
+ }
3693
+ // ==========================================================================
3694
+ // Private Helper Methods
3695
+ // ==========================================================================
3696
+ parseVersionRow(row) {
3697
+ return {
3698
+ id: row.id,
3699
+ agentId: row.agentId,
3700
+ versionNumber: row.versionNumber,
3701
+ name: row.name,
3702
+ snapshot: this.parseJson(row.snapshot, "snapshot"),
3703
+ changedFields: this.parseJson(row.changedFields, "changedFields"),
3704
+ changeMessage: row.changeMessage,
3705
+ createdAt: row.createdAtZ || row.createdAt
3706
+ };
3707
+ }
3457
3708
  };
3458
3709
  function getSchemaName3(schema) {
3459
3710
  return schema ? `"${schema}"` : '"public"';
@@ -5040,11 +5291,13 @@ var ObservabilityPG = class _ObservabilityPG extends storage.ObservabilityStorag
5040
5291
  perPage,
5041
5292
  hasMore: (page + 1) * perPage < count
5042
5293
  },
5043
- spans: spans.map(
5044
- (span) => transformFromSqlRow({
5045
- tableName: storage.TABLE_SPANS,
5046
- sqlRow: span
5047
- })
5294
+ spans: storage.toTraceSpans(
5295
+ spans.map(
5296
+ (span) => transformFromSqlRow({
5297
+ tableName: storage.TABLE_SPANS,
5298
+ sqlRow: span
5299
+ })
5300
+ )
5048
5301
  )
5049
5302
  };
5050
5303
  } catch (error$1) {