@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/dist/index.js CHANGED
@@ -3119,10 +3119,124 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3119
3119
  }
3120
3120
  }
3121
3121
  async init() {
3122
+ await this.#migrateFromLegacySchema();
3123
+ await this.#migrateVersionsSchema();
3122
3124
  await this.#db.createTable({ tableName: TABLE_AGENTS, schema: TABLE_SCHEMAS[TABLE_AGENTS] });
3123
3125
  await this.#db.createTable({ tableName: TABLE_AGENT_VERSIONS, schema: TABLE_SCHEMAS[TABLE_AGENT_VERSIONS] });
3126
+ await this.#db.alterTable({
3127
+ tableName: TABLE_AGENTS,
3128
+ schema: TABLE_SCHEMAS[TABLE_AGENTS],
3129
+ ifNotExists: ["status", "authorId"]
3130
+ });
3124
3131
  await this.createDefaultIndexes();
3125
3132
  await this.createCustomIndexes();
3133
+ await this.#cleanupStaleDrafts();
3134
+ }
3135
+ /**
3136
+ * Migrates from the legacy flat agent schema (where config fields like name, instructions, model
3137
+ * were stored directly on mastra_agents) to the new versioned schema (thin agent record + versions table).
3138
+ */
3139
+ async #migrateFromLegacySchema() {
3140
+ const fullTableName = getTableName2({ indexName: TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3141
+ const fullVersionsTableName = getTableName2({
3142
+ indexName: TABLE_AGENT_VERSIONS,
3143
+ schemaName: getSchemaName2(this.#schema)
3144
+ });
3145
+ const legacyTableName = getTableName2({
3146
+ indexName: `${TABLE_AGENTS}_legacy`,
3147
+ schemaName: getSchemaName2(this.#schema)
3148
+ });
3149
+ const hasLegacyColumns = await this.#db.hasColumn(TABLE_AGENTS, "name");
3150
+ if (hasLegacyColumns) {
3151
+ await this.#db.client.none(`ALTER TABLE ${fullTableName} RENAME TO "${TABLE_AGENTS}_legacy"`);
3152
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
3153
+ }
3154
+ const legacyExists = await this.#db.hasColumn(`${TABLE_AGENTS}_legacy`, "name");
3155
+ if (!legacyExists) return;
3156
+ const oldAgents = await this.#db.client.manyOrNone(`SELECT * FROM ${legacyTableName}`);
3157
+ await this.#db.createTable({ tableName: TABLE_AGENTS, schema: TABLE_SCHEMAS[TABLE_AGENTS] });
3158
+ await this.#db.createTable({ tableName: TABLE_AGENT_VERSIONS, schema: TABLE_SCHEMAS[TABLE_AGENT_VERSIONS] });
3159
+ for (const row of oldAgents) {
3160
+ const agentId = row.id;
3161
+ if (!agentId) continue;
3162
+ const versionId = crypto.randomUUID();
3163
+ const now = /* @__PURE__ */ new Date();
3164
+ await this.#db.client.none(
3165
+ `INSERT INTO ${fullTableName} (id, status, "activeVersionId", "authorId", metadata, "createdAt", "updatedAt")
3166
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
3167
+ ON CONFLICT (id) DO NOTHING`,
3168
+ [
3169
+ agentId,
3170
+ "published",
3171
+ versionId,
3172
+ row.ownerId ?? row.authorId ?? null,
3173
+ row.metadata ? JSON.stringify(row.metadata) : null,
3174
+ row.createdAt ?? now,
3175
+ row.updatedAt ?? now
3176
+ ]
3177
+ );
3178
+ await this.#db.client.none(
3179
+ `INSERT INTO ${fullVersionsTableName}
3180
+ (id, "agentId", "versionNumber", name, description, instructions, model, tools,
3181
+ "defaultOptions", workflows, agents, "integrationTools", "inputProcessors",
3182
+ "outputProcessors", memory, scorers, "changedFields", "changeMessage", "createdAt")
3183
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19)
3184
+ ON CONFLICT (id) DO NOTHING`,
3185
+ [
3186
+ versionId,
3187
+ agentId,
3188
+ 1,
3189
+ row.name ?? agentId,
3190
+ row.description ?? null,
3191
+ row.instructions ?? "",
3192
+ row.model ? JSON.stringify(row.model) : "{}",
3193
+ row.tools ? JSON.stringify(row.tools) : null,
3194
+ row.defaultOptions ? JSON.stringify(row.defaultOptions) : null,
3195
+ row.workflows ? JSON.stringify(row.workflows) : null,
3196
+ row.agents ? JSON.stringify(row.agents) : null,
3197
+ row.integrationTools ? JSON.stringify(row.integrationTools) : null,
3198
+ row.inputProcessors ? JSON.stringify(row.inputProcessors) : null,
3199
+ row.outputProcessors ? JSON.stringify(row.outputProcessors) : null,
3200
+ row.memory ? JSON.stringify(row.memory) : null,
3201
+ row.scorers ? JSON.stringify(row.scorers) : null,
3202
+ null,
3203
+ "Migrated from legacy schema",
3204
+ row.createdAt ?? now
3205
+ ]
3206
+ );
3207
+ }
3208
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
3209
+ }
3210
+ /**
3211
+ * Migrates the agent_versions table from the old snapshot-based schema (single `snapshot` JSON column)
3212
+ * to the new flat schema (individual config columns). This handles the case where the agents table
3213
+ * was already migrated but the versions table still has the old schema.
3214
+ */
3215
+ async #migrateVersionsSchema() {
3216
+ const hasSnapshotColumn = await this.#db.hasColumn(TABLE_AGENT_VERSIONS, "snapshot");
3217
+ if (!hasSnapshotColumn) return;
3218
+ const fullVersionsTableName = getTableName2({
3219
+ indexName: TABLE_AGENT_VERSIONS,
3220
+ schemaName: getSchemaName2(this.#schema)
3221
+ });
3222
+ const legacyTableName = getTableName2({
3223
+ indexName: `${TABLE_AGENTS}_legacy`,
3224
+ schemaName: getSchemaName2(this.#schema)
3225
+ });
3226
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
3227
+ await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
3228
+ }
3229
+ /**
3230
+ * Removes stale draft agent records that have no activeVersionId.
3231
+ * These are left behind when createAgent partially fails (inserts thin record
3232
+ * but fails to create the version due to schema mismatch).
3233
+ */
3234
+ async #cleanupStaleDrafts() {
3235
+ try {
3236
+ const fullTableName = getTableName2({ indexName: TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3237
+ await this.#db.client.none(`DELETE FROM ${fullTableName} WHERE status = 'draft' AND "activeVersionId" IS NULL`);
3238
+ } catch {
3239
+ }
3126
3240
  }
3127
3241
  /**
3128
3242
  * Creates custom user-defined indexes for this domain's tables.