@mastra/pg 1.1.0-alpha.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,113 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Restructured stored agents to use a thin metadata record with versioned configuration snapshots. ([#12488](https://github.com/mastra-ai/mastra/pull/12488))
8
+
9
+ The agent record now only stores metadata fields (id, status, activeVersionId, authorId, metadata, timestamps). All configuration fields (name, instructions, model, tools, etc.) live exclusively in version snapshot rows, enabling full version history and rollback.
10
+
11
+ **Key changes:**
12
+ - Stored Agent records are now thin metadata-only (StorageAgentType)
13
+ - All config lives in version snapshots (StorageAgentSnapshotType)
14
+ - New resolved type (StorageResolvedAgentType) merges agent record + active version config
15
+ - Renamed `ownerId` to `authorId` for multi-tenant filtering
16
+ - Changed `memory` field type from `string` to `Record<string, unknown>`
17
+ - Added `status` field ('draft' | 'published') to agent records
18
+ - Flattened CreateAgent/UpdateAgent input types (config fields at top level, no nested snapshot)
19
+ - Version config columns are top-level in the agent_versions table (no single snapshot jsonb column)
20
+ - List endpoints return resolved agents (thin record + active version config)
21
+ - Auto-versioning on update with retention limits and race condition handling
22
+
23
+ - Added dynamic agent management with CRUD operations and version tracking ([#12038](https://github.com/mastra-ai/mastra/pull/12038))
24
+
25
+ **New Features:**
26
+ - Create, edit, and delete agents directly from the Mastra Studio UI
27
+ - Full version history for agents with compare and restore capabilities
28
+ - Visual diff viewer to compare agent configurations across versions
29
+ - Agent creation modal with comprehensive configuration options (model selection, instructions, tools, workflows, sub-agents, memory)
30
+ - AI-powered instruction enhancement
31
+
32
+ **Storage:**
33
+ - New storage interfaces for stored agents and agent versions
34
+ - PostgreSQL, LibSQL, and MongoDB implementations included
35
+ - In-memory storage for development and testing
36
+
37
+ **API:**
38
+ - RESTful endpoints for agent CRUD operations
39
+ - Version management endpoints (create, list, activate, restore, delete, compare)
40
+ - Automatic versioning on agent updates when enabled
41
+
42
+ **Client SDK:**
43
+ - JavaScript client with full support for stored agents and versions
44
+ - Type-safe methods for all CRUD and version operations
45
+
46
+ **Usage Example:**
47
+
48
+ ```typescript
49
+ // Server-side: Configure storage
50
+ import { Mastra } from '@mastra/core';
51
+ import { PgAgentsStorage } from '@mastra/pg';
52
+
53
+ const mastra = new Mastra({
54
+ agents: { agentOne },
55
+ storage: {
56
+ agents: new PgAgentsStorage({
57
+ connectionString: process.env.DATABASE_URL,
58
+ }),
59
+ },
60
+ });
61
+
62
+ // Client-side: Use the SDK
63
+ import { MastraClient } from '@mastra/client-js';
64
+
65
+ const client = new MastraClient({ baseUrl: 'http://localhost:3000' });
66
+
67
+ // Create a stored agent
68
+ const agent = await client.createStoredAgent({
69
+ name: 'Customer Support Agent',
70
+ description: 'Handles customer inquiries',
71
+ model: { provider: 'ANTHROPIC', name: 'claude-sonnet-4-5' },
72
+ instructions: 'You are a helpful customer support agent...',
73
+ tools: ['search', 'email'],
74
+ });
75
+
76
+ // Create a version snapshot
77
+ await client.storedAgent(agent.id).createVersion({
78
+ name: 'v1.0 - Initial release',
79
+ changeMessage: 'First production version',
80
+ });
81
+
82
+ // Compare versions
83
+ const diff = await client.storedAgent(agent.id).compareVersions('version-1', 'version-2');
84
+ ```
85
+
86
+ **Why:**
87
+ This feature enables teams to manage agents dynamically without code changes, making it easier to iterate on agent configurations and maintain a complete audit trail of changes.
88
+
89
+ - Added `status` field to `listTraces` response. The status field indicates the trace state: `success` (completed without error), `error` (has error), or `running` (still in progress). This makes it easier to filter and display traces by their current state without having to derive it from the `error` and `endedAt` fields. ([#12213](https://github.com/mastra-ai/mastra/pull/12213))
90
+
91
+ ### Patch Changes
92
+
93
+ - Stored agent edits no longer fail silently. PATCH requests now save changes correctly. ([#12504](https://github.com/mastra-ai/mastra/pull/12504))
94
+
95
+ - Fix PATCH request JSON-body handling in `@mastra/client-js` so stored agent edit flows work correctly. Fix stored agent schema migration in `@mastra/libsql` and `@mastra/pg` to drop and recreate the versions table when the old snapshot-based schema is detected, clean up stale draft records from partial create failures, and remove lingering legacy tables. Restores create and edit flows for stored agents. ([#12504](https://github.com/mastra-ai/mastra/pull/12504))
96
+
97
+ - Updated dependencies [[`90fc0e5`](https://github.com/mastra-ai/mastra/commit/90fc0e5717cb280c2d4acf4f0410b510bb4c0a72), [`1cf5d2e`](https://github.com/mastra-ai/mastra/commit/1cf5d2ea1b085be23e34fb506c80c80a4e6d9c2b), [`b99ceac`](https://github.com/mastra-ai/mastra/commit/b99ceace2c830dbdef47c8692d56a91954aefea2), [`deea43e`](https://github.com/mastra-ai/mastra/commit/deea43eb1366d03a864c5e597d16a48592b9893f), [`833ae96`](https://github.com/mastra-ai/mastra/commit/833ae96c3e34370e58a1e979571c41f39a720592), [`943772b`](https://github.com/mastra-ai/mastra/commit/943772b4378f625f0f4e19ea2b7c392bd8e71786), [`b5c711b`](https://github.com/mastra-ai/mastra/commit/b5c711b281dd1fb81a399a766bc9f86c55efc13e), [`3efbe5a`](https://github.com/mastra-ai/mastra/commit/3efbe5ae20864c4f3143457f4f3ee7dc2fa5ca76), [`1e49e7a`](https://github.com/mastra-ai/mastra/commit/1e49e7ab5f173582154cb26b29d424de67d09aef), [`751eaab`](https://github.com/mastra-ai/mastra/commit/751eaab4e0d3820a94e4c3d39a2ff2663ded3d91), [`69d8156`](https://github.com/mastra-ai/mastra/commit/69d81568bcf062557c24471ce26812446bec465d), [`60d9d89`](https://github.com/mastra-ai/mastra/commit/60d9d899e44b35bc43f1bcd967a74e0ce010b1af), [`5c544c8`](https://github.com/mastra-ai/mastra/commit/5c544c8d12b08ab40d64d8f37b3c4215bee95b87), [`771ad96`](https://github.com/mastra-ai/mastra/commit/771ad962441996b5c43549391a3e6a02c6ddedc2), [`2b0936b`](https://github.com/mastra-ai/mastra/commit/2b0936b0c9a43eeed9bef63e614d7e02ee803f7e), [`3b04f30`](https://github.com/mastra-ai/mastra/commit/3b04f3010604f3cdfc8a0674731700ad66471cee), [`97e26de`](https://github.com/mastra-ai/mastra/commit/97e26deaebd9836647a67b96423281d66421ca07), [`ac9ec66`](https://github.com/mastra-ai/mastra/commit/ac9ec6672779b2e6d4344e415481d1a6a7d4911a), [`10523f4`](https://github.com/mastra-ai/mastra/commit/10523f4882d9b874b40ce6e3715f66dbcd4947d2), [`cb72d20`](https://github.com/mastra-ai/mastra/commit/cb72d2069d7339bda8a0e76d4f35615debb07b84), [`42856b1`](https://github.com/mastra-ai/mastra/commit/42856b1c8aeea6371c9ee77ae2f5f5fe34400933), [`66f33ff`](https://github.com/mastra-ai/mastra/commit/66f33ff68620018513e499c394411d1d39b3aa5c), [`ab3c190`](https://github.com/mastra-ai/mastra/commit/ab3c1901980a99910ca9b96a7090c22e24060113), [`d4f06c8`](https://github.com/mastra-ai/mastra/commit/d4f06c85ffa5bb0da38fb82ebf3b040cc6b4ec4e), [`0350626`](https://github.com/mastra-ai/mastra/commit/03506267ec41b67add80d994c0c0fcce93bbc75f), [`bc9fa00`](https://github.com/mastra-ai/mastra/commit/bc9fa00859c5c4a796d53a0a5cae46ab4a3072e4), [`f46a478`](https://github.com/mastra-ai/mastra/commit/f46a4782f595949c696569e891f81c8d26338508), [`90fc0e5`](https://github.com/mastra-ai/mastra/commit/90fc0e5717cb280c2d4acf4f0410b510bb4c0a72), [`f05a3a5`](https://github.com/mastra-ai/mastra/commit/f05a3a5cf2b9a9c2d40c09cb8c762a4b6cd5d565), [`a291da9`](https://github.com/mastra-ai/mastra/commit/a291da9363efd92dafd8775dccb4f2d0511ece7a), [`c5d71da`](https://github.com/mastra-ai/mastra/commit/c5d71da1c680ce5640b1a7f8ca0e024a4ab1cfed), [`07042f9`](https://github.com/mastra-ai/mastra/commit/07042f9f89080f38b8f72713ba1c972d5b1905b8), [`0423442`](https://github.com/mastra-ai/mastra/commit/0423442b7be2dfacba95890bea8f4a810db4d603)]:
98
+ - @mastra/core@1.1.0
99
+
100
+ ## 1.1.0-alpha.2
101
+
102
+ ### Patch Changes
103
+
104
+ - Stored agent edits no longer fail silently. PATCH requests now save changes correctly. ([#12504](https://github.com/mastra-ai/mastra/pull/12504))
105
+
106
+ - Fix PATCH request JSON-body handling in `@mastra/client-js` so stored agent edit flows work correctly. Fix stored agent schema migration in `@mastra/libsql` and `@mastra/pg` to drop and recreate the versions table when the old snapshot-based schema is detected, clean up stale draft records from partial create failures, and remove lingering legacy tables. Restores create and edit flows for stored agents. ([#12504](https://github.com/mastra-ai/mastra/pull/12504))
107
+
108
+ - Updated dependencies:
109
+ - @mastra/core@1.1.0-alpha.2
110
+
3
111
  ## 1.1.0-alpha.1
4
112
 
5
113
  ### Minor Changes
@@ -33,4 +33,4 @@ docs/
33
33
  ## Version
34
34
 
35
35
  Package: @mastra/pg
36
- Version: 1.1.0-alpha.1
36
+ Version: 1.1.0
@@ -5,7 +5,7 @@ description: Documentation for @mastra/pg. Includes links to type definitions an
5
5
 
6
6
  # @mastra/pg Documentation
7
7
 
8
- > **Version**: 1.1.0-alpha.1
8
+ > **Version**: 1.1.0
9
9
  > **Package**: @mastra/pg
10
10
 
11
11
  ## Quick Navigation
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0-alpha.1",
2
+ "version": "1.1.0",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -3143,10 +3143,124 @@ var AgentsPG = class _AgentsPG extends storage.AgentsStorage {
3143
3143
  }
3144
3144
  }
3145
3145
  async init() {
3146
+ await this.#migrateFromLegacySchema();
3147
+ await this.#migrateVersionsSchema();
3146
3148
  await this.#db.createTable({ tableName: storage.TABLE_AGENTS, schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENTS] });
3147
3149
  await this.#db.createTable({ tableName: storage.TABLE_AGENT_VERSIONS, schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENT_VERSIONS] });
3150
+ await this.#db.alterTable({
3151
+ tableName: storage.TABLE_AGENTS,
3152
+ schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENTS],
3153
+ ifNotExists: ["status", "authorId"]
3154
+ });
3148
3155
  await this.createDefaultIndexes();
3149
3156
  await this.createCustomIndexes();
3157
+ await this.#cleanupStaleDrafts();
3158
+ }
3159
+ /**
3160
+ * Migrates from the legacy flat agent schema (where config fields like name, instructions, model
3161
+ * were stored directly on mastra_agents) to the new versioned schema (thin agent record + versions table).
3162
+ */
3163
+ async #migrateFromLegacySchema() {
3164
+ const fullTableName = getTableName2({ indexName: storage.TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3165
+ const fullVersionsTableName = getTableName2({
3166
+ indexName: storage.TABLE_AGENT_VERSIONS,
3167
+ schemaName: getSchemaName2(this.#schema)
3168
+ });
3169
+ const legacyTableName = getTableName2({
3170
+ indexName: `${storage.TABLE_AGENTS}_legacy`,
3171
+ schemaName: getSchemaName2(this.#schema)
3172
+ });
3173
+ const hasLegacyColumns = await this.#db.hasColumn(storage.TABLE_AGENTS, "name");
3174
+ if (hasLegacyColumns) {
3175
+ await this.#db.client.none(`ALTER TABLE ${fullTableName} RENAME TO "${storage.TABLE_AGENTS}_legacy"`);
3176
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
3177
+ }
3178
+ const legacyExists = await this.#db.hasColumn(`${storage.TABLE_AGENTS}_legacy`, "name");
3179
+ if (!legacyExists) return;
3180
+ const oldAgents = await this.#db.client.manyOrNone(`SELECT * FROM ${legacyTableName}`);
3181
+ await this.#db.createTable({ tableName: storage.TABLE_AGENTS, schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENTS] });
3182
+ await this.#db.createTable({ tableName: storage.TABLE_AGENT_VERSIONS, schema: storage.TABLE_SCHEMAS[storage.TABLE_AGENT_VERSIONS] });
3183
+ for (const row of oldAgents) {
3184
+ const agentId = row.id;
3185
+ if (!agentId) continue;
3186
+ const versionId = crypto.randomUUID();
3187
+ const now = /* @__PURE__ */ new Date();
3188
+ await this.#db.client.none(
3189
+ `INSERT INTO ${fullTableName} (id, status, "activeVersionId", "authorId", metadata, "createdAt", "updatedAt")
3190
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
3191
+ ON CONFLICT (id) DO NOTHING`,
3192
+ [
3193
+ agentId,
3194
+ "published",
3195
+ versionId,
3196
+ row.ownerId ?? row.authorId ?? null,
3197
+ row.metadata ? JSON.stringify(row.metadata) : null,
3198
+ row.createdAt ?? now,
3199
+ row.updatedAt ?? now
3200
+ ]
3201
+ );
3202
+ await this.#db.client.none(
3203
+ `INSERT INTO ${fullVersionsTableName}
3204
+ (id, "agentId", "versionNumber", name, description, instructions, model, tools,
3205
+ "defaultOptions", workflows, agents, "integrationTools", "inputProcessors",
3206
+ "outputProcessors", memory, scorers, "changedFields", "changeMessage", "createdAt")
3207
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19)
3208
+ ON CONFLICT (id) DO NOTHING`,
3209
+ [
3210
+ versionId,
3211
+ agentId,
3212
+ 1,
3213
+ row.name ?? agentId,
3214
+ row.description ?? null,
3215
+ row.instructions ?? "",
3216
+ row.model ? JSON.stringify(row.model) : "{}",
3217
+ row.tools ? JSON.stringify(row.tools) : null,
3218
+ row.defaultOptions ? JSON.stringify(row.defaultOptions) : null,
3219
+ row.workflows ? JSON.stringify(row.workflows) : null,
3220
+ row.agents ? JSON.stringify(row.agents) : null,
3221
+ row.integrationTools ? JSON.stringify(row.integrationTools) : null,
3222
+ row.inputProcessors ? JSON.stringify(row.inputProcessors) : null,
3223
+ row.outputProcessors ? JSON.stringify(row.outputProcessors) : null,
3224
+ row.memory ? JSON.stringify(row.memory) : null,
3225
+ row.scorers ? JSON.stringify(row.scorers) : null,
3226
+ null,
3227
+ "Migrated from legacy schema",
3228
+ row.createdAt ?? now
3229
+ ]
3230
+ );
3231
+ }
3232
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
3233
+ }
3234
+ /**
3235
+ * Migrates the agent_versions table from the old snapshot-based schema (single `snapshot` JSON column)
3236
+ * to the new flat schema (individual config columns). This handles the case where the agents table
3237
+ * was already migrated but the versions table still has the old schema.
3238
+ */
3239
+ async #migrateVersionsSchema() {
3240
+ const hasSnapshotColumn = await this.#db.hasColumn(storage.TABLE_AGENT_VERSIONS, "snapshot");
3241
+ if (!hasSnapshotColumn) return;
3242
+ const fullVersionsTableName = getTableName2({
3243
+ indexName: storage.TABLE_AGENT_VERSIONS,
3244
+ schemaName: getSchemaName2(this.#schema)
3245
+ });
3246
+ const legacyTableName = getTableName2({
3247
+ indexName: `${storage.TABLE_AGENTS}_legacy`,
3248
+ schemaName: getSchemaName2(this.#schema)
3249
+ });
3250
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
3251
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
3252
+ }
3253
+ /**
3254
+ * Removes stale draft agent records that have no activeVersionId.
3255
+ * These are left behind when createAgent partially fails (inserts thin record
3256
+ * but fails to create the version due to schema mismatch).
3257
+ */
3258
+ async #cleanupStaleDrafts() {
3259
+ try {
3260
+ const fullTableName = getTableName2({ indexName: storage.TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3261
+ await this.#db.client.none(`DELETE FROM ${fullTableName} WHERE status = 'draft' AND "activeVersionId" IS NULL`);
3262
+ } catch {
3263
+ }
3150
3264
  }
3151
3265
  /**
3152
3266
  * Creates custom user-defined indexes for this domain's tables.