@mastra/pg 1.1.0 → 1.2.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
@@ -3346,20 +3346,24 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3346
3346
  changedFields: Object.keys(snapshotConfig),
3347
3347
  changeMessage: "Initial version"
3348
3348
  });
3349
- await this.#db.client.none(
3350
- `UPDATE ${agentsTable} SET "activeVersionId" = $1, status = $2, "updatedAt" = $3, "updatedAtZ" = $4 WHERE id = $5`,
3351
- [versionId, "published", nowIso, nowIso, agent.id]
3352
- );
3353
3349
  return {
3354
3350
  id: agent.id,
3355
- status: "published",
3356
- activeVersionId: versionId,
3351
+ status: "draft",
3352
+ activeVersionId: void 0,
3357
3353
  authorId: agent.authorId,
3358
3354
  metadata: agent.metadata,
3359
3355
  createdAt: now,
3360
3356
  updatedAt: now
3361
3357
  };
3362
3358
  } catch (error) {
3359
+ try {
3360
+ const agentsTable = getTableName2({ indexName: TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3361
+ await this.#db.client.none(
3362
+ `DELETE FROM ${agentsTable} WHERE id = $1 AND status = 'draft' AND "activeVersionId" IS NULL`,
3363
+ [agent.id]
3364
+ );
3365
+ } catch {
3366
+ }
3363
3367
  throw new MastraError(
3364
3368
  {
3365
3369
  id: createStorageErrorId("PG", "CREATE_AGENT", "FAILED"),
@@ -3384,23 +3388,77 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3384
3388
  details: { agentId: id }
3385
3389
  });
3386
3390
  }
3391
+ const { authorId, activeVersionId, metadata, ...configFields } = updates;
3392
+ const configFieldNames = [
3393
+ "name",
3394
+ "description",
3395
+ "instructions",
3396
+ "model",
3397
+ "tools",
3398
+ "defaultOptions",
3399
+ "workflows",
3400
+ "agents",
3401
+ "integrationTools",
3402
+ "inputProcessors",
3403
+ "outputProcessors",
3404
+ "memory",
3405
+ "scorers"
3406
+ ];
3407
+ const hasConfigUpdate = configFieldNames.some((field) => field in configFields);
3408
+ if (hasConfigUpdate) {
3409
+ const latestVersion = await this.getLatestVersion(id);
3410
+ if (!latestVersion) {
3411
+ throw new MastraError({
3412
+ id: createStorageErrorId("PG", "UPDATE_AGENT", "NO_VERSIONS"),
3413
+ domain: ErrorDomain.STORAGE,
3414
+ category: ErrorCategory.SYSTEM,
3415
+ text: `No versions found for agent ${id}`,
3416
+ details: { agentId: id }
3417
+ });
3418
+ }
3419
+ const {
3420
+ id: _versionId,
3421
+ agentId: _agentId,
3422
+ versionNumber: _versionNumber,
3423
+ changedFields: _changedFields,
3424
+ changeMessage: _changeMessage,
3425
+ createdAt: _createdAt,
3426
+ ...latestConfig
3427
+ } = latestVersion;
3428
+ const newConfig = {
3429
+ ...latestConfig,
3430
+ ...configFields
3431
+ };
3432
+ const changedFields = configFieldNames.filter(
3433
+ (field) => field in configFields && configFields[field] !== latestConfig[field]
3434
+ );
3435
+ if (changedFields.length > 0) {
3436
+ const newVersionId = crypto.randomUUID();
3437
+ const newVersionNumber = latestVersion.versionNumber + 1;
3438
+ await this.createVersion({
3439
+ id: newVersionId,
3440
+ agentId: id,
3441
+ versionNumber: newVersionNumber,
3442
+ ...newConfig,
3443
+ changedFields,
3444
+ changeMessage: `Updated ${changedFields.join(", ")}`
3445
+ });
3446
+ }
3447
+ }
3387
3448
  const setClauses = [];
3388
3449
  const values = [];
3389
3450
  let paramIndex = 1;
3390
- if (updates.authorId !== void 0) {
3451
+ if (authorId !== void 0) {
3391
3452
  setClauses.push(`"authorId" = $${paramIndex++}`);
3392
- values.push(updates.authorId);
3453
+ values.push(authorId);
3393
3454
  }
3394
- if (updates.activeVersionId !== void 0) {
3455
+ if (activeVersionId !== void 0) {
3395
3456
  setClauses.push(`"activeVersionId" = $${paramIndex++}`);
3396
- values.push(updates.activeVersionId);
3397
- setClauses.push(`status = $${paramIndex++}`);
3398
- values.push("published");
3457
+ values.push(activeVersionId);
3399
3458
  }
3400
- if (updates.metadata !== void 0) {
3401
- const mergedMetadata = { ...existingAgent.metadata, ...updates.metadata };
3459
+ if (metadata !== void 0) {
3402
3460
  setClauses.push(`metadata = $${paramIndex++}`);
3403
- values.push(JSON.stringify(mergedMetadata));
3461
+ values.push(JSON.stringify(metadata));
3404
3462
  }
3405
3463
  const now = (/* @__PURE__ */ new Date()).toISOString();
3406
3464
  setClauses.push(`"updatedAt" = $${paramIndex++}`);
@@ -3510,6 +3568,124 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3510
3568
  );
3511
3569
  }
3512
3570
  }
3571
+ async listAgentsResolved(args) {
3572
+ const { page = 0, perPage: perPageInput, orderBy } = args || {};
3573
+ const { field, direction } = this.parseOrderBy(orderBy);
3574
+ if (page < 0) {
3575
+ throw new MastraError(
3576
+ {
3577
+ id: createStorageErrorId("PG", "LIST_AGENTS_RESOLVED", "INVALID_PAGE"),
3578
+ domain: ErrorDomain.STORAGE,
3579
+ category: ErrorCategory.USER,
3580
+ details: { page }
3581
+ },
3582
+ new Error("page must be >= 0")
3583
+ );
3584
+ }
3585
+ const perPage = normalizePerPage(perPageInput, 100);
3586
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
3587
+ try {
3588
+ const agentsTableName = getTableName2({ indexName: TABLE_AGENTS, schemaName: getSchemaName2(this.#schema) });
3589
+ const versionsTableName = getTableName2({
3590
+ indexName: TABLE_AGENT_VERSIONS,
3591
+ schemaName: getSchemaName2(this.#schema)
3592
+ });
3593
+ const countResult = await this.#db.client.one(`SELECT COUNT(*) as count FROM ${agentsTableName}`);
3594
+ const total = parseInt(countResult.count, 10);
3595
+ if (total === 0) {
3596
+ return {
3597
+ agents: [],
3598
+ total: 0,
3599
+ page,
3600
+ perPage: perPageForResponse,
3601
+ hasMore: false
3602
+ };
3603
+ }
3604
+ const limitValue = perPageInput === false ? total : perPage;
3605
+ const query = `
3606
+ WITH latest_versions AS (
3607
+ SELECT v.*
3608
+ FROM ${versionsTableName} v
3609
+ INNER JOIN (
3610
+ SELECT "agentId", MAX("versionNumber") as max_version
3611
+ FROM ${versionsTableName}
3612
+ GROUP BY "agentId"
3613
+ ) lv ON v."agentId" = lv."agentId" AND v."versionNumber" = lv.max_version
3614
+ )
3615
+ SELECT
3616
+ a.*,
3617
+ COALESCE(av.id, lv.id) as version_id,
3618
+ COALESCE(av."versionNumber", lv."versionNumber") as version_number,
3619
+ COALESCE(av.name, lv.name) as version_name,
3620
+ COALESCE(av.description, lv.description) as version_description,
3621
+ COALESCE(av.instructions, lv.instructions) as version_instructions,
3622
+ COALESCE(av.model, lv.model) as version_model,
3623
+ COALESCE(av.tools, lv.tools) as version_tools,
3624
+ COALESCE(av."defaultOptions", lv."defaultOptions") as version_defaultOptions,
3625
+ COALESCE(av.workflows, lv.workflows) as version_workflows,
3626
+ COALESCE(av.agents, lv.agents) as version_agents,
3627
+ COALESCE(av."integrationTools", lv."integrationTools") as version_integrationTools,
3628
+ COALESCE(av."inputProcessors", lv."inputProcessors") as version_inputProcessors,
3629
+ COALESCE(av."outputProcessors", lv."outputProcessors") as version_outputProcessors,
3630
+ COALESCE(av.memory, lv.memory) as version_memory,
3631
+ COALESCE(av.scorers, lv.scorers) as version_scorers
3632
+ FROM ${agentsTableName} a
3633
+ LEFT JOIN ${versionsTableName} av ON a."activeVersionId" = av.id
3634
+ LEFT JOIN latest_versions lv ON a.id = lv."agentId"
3635
+ ORDER BY a."${field}" ${direction}
3636
+ LIMIT $1 OFFSET $2
3637
+ `;
3638
+ const dataResult = await this.#db.client.manyOrNone(query, [limitValue, offset]);
3639
+ const resolvedAgents = (dataResult || []).map((row) => {
3640
+ const agent = this.parseRow({
3641
+ id: row.id,
3642
+ status: row.status,
3643
+ activeVersionId: row.activeVersionId,
3644
+ authorId: row.authorId,
3645
+ metadata: row.metadata,
3646
+ createdAt: row.createdAt,
3647
+ createdAtZ: row.createdAtZ,
3648
+ updatedAt: row.updatedAt,
3649
+ updatedAtZ: row.updatedAtZ
3650
+ });
3651
+ if (row.version_id) {
3652
+ return {
3653
+ ...agent,
3654
+ name: row.version_name,
3655
+ description: row.version_description,
3656
+ instructions: row.version_instructions,
3657
+ model: this.parseJson(row.version_model, "model"),
3658
+ tools: this.parseJson(row.version_tools, "tools"),
3659
+ defaultOptions: this.parseJson(row.version_defaultOptions, "defaultOptions"),
3660
+ workflows: this.parseJson(row.version_workflows, "workflows"),
3661
+ agents: this.parseJson(row.version_agents, "agents"),
3662
+ integrationTools: this.parseJson(row.version_integrationTools, "integrationTools"),
3663
+ inputProcessors: this.parseJson(row.version_inputProcessors, "inputProcessors"),
3664
+ outputProcessors: this.parseJson(row.version_outputProcessors, "outputProcessors"),
3665
+ memory: this.parseJson(row.version_memory, "memory"),
3666
+ scorers: this.parseJson(row.version_scorers, "scorers")
3667
+ };
3668
+ }
3669
+ return agent;
3670
+ });
3671
+ return {
3672
+ agents: resolvedAgents,
3673
+ total,
3674
+ page,
3675
+ perPage: perPageForResponse,
3676
+ hasMore: perPageInput === false ? false : offset + perPage < total
3677
+ };
3678
+ } catch (error) {
3679
+ throw new MastraError(
3680
+ {
3681
+ id: createStorageErrorId("PG", "LIST_AGENTS_RESOLVED", "FAILED"),
3682
+ domain: ErrorDomain.STORAGE,
3683
+ category: ErrorCategory.THIRD_PARTY
3684
+ },
3685
+ error
3686
+ );
3687
+ }
3688
+ }
3513
3689
  // ==========================================================================
3514
3690
  // Agent Version Methods
3515
3691
  // ==========================================================================
@@ -3766,6 +3942,7 @@ var AgentsPG = class _AgentsPG extends AgentsStorage {
3766
3942
  };
3767
3943
  }
3768
3944
  };
3945
+ var OM_TABLE = "mastra_observational_memory";
3769
3946
  function getSchemaName3(schema) {
3770
3947
  return schema ? `"${schema}"` : '"public"';
3771
3948
  }
@@ -3777,12 +3954,13 @@ function inPlaceholders(count, startIndex = 1) {
3777
3954
  return Array.from({ length: count }, (_, i) => `$${i + startIndex}`).join(", ");
3778
3955
  }
3779
3956
  var MemoryPG = class _MemoryPG extends MemoryStorage {
3957
+ supportsObservationalMemory = true;
3780
3958
  #db;
3781
3959
  #schema;
3782
3960
  #skipDefaultIndexes;
3783
3961
  #indexes;
3784
3962
  /** Tables managed by this domain */
3785
- static MANAGED_TABLES = [TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES];
3963
+ static MANAGED_TABLES = [TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, OM_TABLE];
3786
3964
  constructor(config) {
3787
3965
  super();
3788
3966
  const { client, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
@@ -3795,11 +3973,30 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
3795
3973
  await this.#db.createTable({ tableName: TABLE_THREADS, schema: TABLE_SCHEMAS[TABLE_THREADS] });
3796
3974
  await this.#db.createTable({ tableName: TABLE_MESSAGES, schema: TABLE_SCHEMAS[TABLE_MESSAGES] });
3797
3975
  await this.#db.createTable({ tableName: TABLE_RESOURCES, schema: TABLE_SCHEMAS[TABLE_RESOURCES] });
3976
+ let omSchema;
3977
+ try {
3978
+ const { OBSERVATIONAL_MEMORY_TABLE_SCHEMA } = await import('@mastra/core/storage');
3979
+ omSchema = OBSERVATIONAL_MEMORY_TABLE_SCHEMA?.[OM_TABLE];
3980
+ } catch {
3981
+ }
3982
+ if (omSchema) {
3983
+ await this.#db.createTable({
3984
+ tableName: OM_TABLE,
3985
+ schema: omSchema
3986
+ });
3987
+ }
3798
3988
  await this.#db.alterTable({
3799
3989
  tableName: TABLE_MESSAGES,
3800
3990
  schema: TABLE_SCHEMAS[TABLE_MESSAGES],
3801
3991
  ifNotExists: ["resourceId"]
3802
3992
  });
3993
+ if (omSchema) {
3994
+ const omTableName = getTableName3({
3995
+ indexName: OM_TABLE,
3996
+ schemaName: getSchemaName3(this.#schema)
3997
+ });
3998
+ await this.#db.client.none(`CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON ${omTableName} ("lookupKey")`);
3999
+ }
3803
4000
  await this.createDefaultIndexes();
3804
4001
  await this.createCustomIndexes();
3805
4002
  }
@@ -4174,8 +4371,8 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4174
4371
  SELECT ${selectColumns}
4175
4372
  FROM ${tableName} m
4176
4373
  WHERE m.thread_id = (SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx})
4177
- AND m."createdAt" <= (SELECT "createdAt" FROM ${tableName} WHERE id = $${paramIdx})
4178
- ORDER BY m."createdAt" DESC
4374
+ AND COALESCE(m."createdAtZ", m."createdAt") <= (SELECT COALESCE("createdAtZ", "createdAt") FROM ${tableName} WHERE id = $${paramIdx})
4375
+ ORDER BY COALESCE(m."createdAtZ", m."createdAt") DESC
4179
4376
  LIMIT $${paramIdx + 1}
4180
4377
  )`);
4181
4378
  params.push(id, withPreviousMessages + 1);
@@ -4185,8 +4382,8 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4185
4382
  SELECT ${selectColumns}
4186
4383
  FROM ${tableName} m
4187
4384
  WHERE m.thread_id = (SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx})
4188
- AND m."createdAt" > (SELECT "createdAt" FROM ${tableName} WHERE id = $${paramIdx})
4189
- ORDER BY m."createdAt" ASC
4385
+ AND COALESCE(m."createdAtZ", m."createdAt") > (SELECT COALESCE("createdAtZ", "createdAt") FROM ${tableName} WHERE id = $${paramIdx})
4386
+ ORDER BY COALESCE(m."createdAtZ", m."createdAt") ASC
4190
4387
  LIMIT $${paramIdx + 1}
4191
4388
  )`);
4192
4389
  params.push(id, withNextMessages);
@@ -4303,12 +4500,12 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4303
4500
  }
4304
4501
  if (filter?.dateRange?.start) {
4305
4502
  const startOp = filter.dateRange.startExclusive ? ">" : ">=";
4306
- conditions.push(`"createdAt" ${startOp} $${paramIndex++}`);
4503
+ conditions.push(`COALESCE("createdAtZ", "createdAt") ${startOp} $${paramIndex++}`);
4307
4504
  queryParams.push(filter.dateRange.start);
4308
4505
  }
4309
4506
  if (filter?.dateRange?.end) {
4310
4507
  const endOp = filter.dateRange.endExclusive ? "<" : "<=";
4311
- conditions.push(`"createdAt" ${endOp} $${paramIndex++}`);
4508
+ conditions.push(`COALESCE("createdAtZ", "createdAt") ${endOp} $${paramIndex++}`);
4312
4509
  queryParams.push(filter.dateRange.end);
4313
4510
  }
4314
4511
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
@@ -4394,6 +4591,133 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4394
4591
  };
4395
4592
  }
4396
4593
  }
4594
+ async listMessagesByResourceId(args) {
4595
+ const { resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
4596
+ const hasResourceId = resourceId !== void 0 && resourceId !== null && resourceId.trim() !== "";
4597
+ if (!hasResourceId) {
4598
+ throw new MastraError(
4599
+ {
4600
+ id: createStorageErrorId("PG", "LIST_MESSAGES_BY_RESOURCE_ID", "INVALID_QUERY"),
4601
+ domain: ErrorDomain.STORAGE,
4602
+ category: ErrorCategory.USER,
4603
+ details: {
4604
+ resourceId: resourceId ?? ""
4605
+ }
4606
+ },
4607
+ new Error("resourceId is required")
4608
+ );
4609
+ }
4610
+ if (page < 0) {
4611
+ throw new MastraError({
4612
+ id: createStorageErrorId("PG", "LIST_MESSAGES_BY_RESOURCE_ID", "INVALID_PAGE"),
4613
+ domain: ErrorDomain.STORAGE,
4614
+ category: ErrorCategory.USER,
4615
+ text: "Page number must be non-negative",
4616
+ details: {
4617
+ resourceId,
4618
+ page
4619
+ }
4620
+ });
4621
+ }
4622
+ const perPage = normalizePerPage(perPageInput, 40);
4623
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
4624
+ try {
4625
+ const { field, direction } = this.parseOrderBy(orderBy, "ASC");
4626
+ const orderByStatement = `ORDER BY "${field}" ${direction}`;
4627
+ const selectStatement = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId"`;
4628
+ const tableName = getTableName3({ indexName: TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) });
4629
+ const conditions = [];
4630
+ const queryParams = [];
4631
+ let paramIndex = 1;
4632
+ conditions.push(`"resourceId" = $${paramIndex++}`);
4633
+ queryParams.push(resourceId);
4634
+ if (filter?.dateRange?.start) {
4635
+ const startOp = filter.dateRange.startExclusive ? ">" : ">=";
4636
+ conditions.push(`"createdAt" ${startOp} $${paramIndex++}`);
4637
+ queryParams.push(filter.dateRange.start);
4638
+ }
4639
+ if (filter?.dateRange?.end) {
4640
+ const endOp = filter.dateRange.endExclusive ? "<" : "<=";
4641
+ conditions.push(`"createdAt" ${endOp} $${paramIndex++}`);
4642
+ queryParams.push(filter.dateRange.end);
4643
+ }
4644
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
4645
+ const countQuery = `SELECT COUNT(*) FROM ${tableName} ${whereClause}`;
4646
+ const countResult = await this.#db.client.one(countQuery, queryParams);
4647
+ const total = parseInt(countResult.count, 10);
4648
+ const limitValue = perPageInput === false ? total : perPage;
4649
+ const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
4650
+ const rows = await this.#db.client.manyOrNone(dataQuery, [...queryParams, limitValue, offset]);
4651
+ const messages = [...rows || []];
4652
+ if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
4653
+ return {
4654
+ messages: [],
4655
+ total: 0,
4656
+ page,
4657
+ perPage: perPageForResponse,
4658
+ hasMore: false
4659
+ };
4660
+ }
4661
+ const messageIds = new Set(messages.map((m) => m.id));
4662
+ if (include && include.length > 0) {
4663
+ const includeMessages = await this._getIncludedMessages({ include });
4664
+ if (includeMessages) {
4665
+ for (const includeMsg of includeMessages) {
4666
+ if (!messageIds.has(includeMsg.id)) {
4667
+ messages.push(includeMsg);
4668
+ messageIds.add(includeMsg.id);
4669
+ }
4670
+ }
4671
+ }
4672
+ }
4673
+ const messagesWithParsedContent = messages.map((row) => this.parseRow(row));
4674
+ const list = new MessageList().add(messagesWithParsedContent, "memory");
4675
+ let finalMessages = list.get.all.db();
4676
+ finalMessages = finalMessages.sort((a, b) => {
4677
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
4678
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
4679
+ if (aValue == null && bValue == null) return a.id.localeCompare(b.id);
4680
+ if (aValue == null) return 1;
4681
+ if (bValue == null) return -1;
4682
+ if (aValue === bValue) {
4683
+ return a.id.localeCompare(b.id);
4684
+ }
4685
+ if (typeof aValue === "number" && typeof bValue === "number") {
4686
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
4687
+ }
4688
+ return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
4689
+ });
4690
+ const hasMore = perPageInput !== false && offset + perPage < total;
4691
+ return {
4692
+ messages: finalMessages,
4693
+ total,
4694
+ page,
4695
+ perPage: perPageForResponse,
4696
+ hasMore
4697
+ };
4698
+ } catch (error) {
4699
+ const mastraError = new MastraError(
4700
+ {
4701
+ id: createStorageErrorId("PG", "LIST_MESSAGES_BY_RESOURCE_ID", "FAILED"),
4702
+ domain: ErrorDomain.STORAGE,
4703
+ category: ErrorCategory.THIRD_PARTY,
4704
+ details: {
4705
+ resourceId: resourceId ?? ""
4706
+ }
4707
+ },
4708
+ error
4709
+ );
4710
+ this.logger?.error?.(mastraError.toString());
4711
+ this.logger?.trackException(mastraError);
4712
+ return {
4713
+ messages: [],
4714
+ total: 0,
4715
+ page,
4716
+ perPage: perPageForResponse,
4717
+ hasMore: false
4718
+ };
4719
+ }
4720
+ }
4397
4721
  async saveMessages({ messages }) {
4398
4722
  if (messages.length === 0) return { messages: [] };
4399
4723
  const threadId = messages[0]?.threadId;
@@ -4725,11 +5049,11 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4725
5049
  const messageParams = [sourceThreadId];
4726
5050
  let paramIndex = 2;
4727
5051
  if (options?.messageFilter?.startDate) {
4728
- messageQuery += ` AND "createdAt" >= $${paramIndex++}`;
5052
+ messageQuery += ` AND COALESCE("createdAtZ", "createdAt") >= $${paramIndex++}`;
4729
5053
  messageParams.push(options.messageFilter.startDate);
4730
5054
  }
4731
5055
  if (options?.messageFilter?.endDate) {
4732
- messageQuery += ` AND "createdAt" <= $${paramIndex++}`;
5056
+ messageQuery += ` AND COALESCE("createdAtZ", "createdAt") <= $${paramIndex++}`;
4733
5057
  messageParams.push(options.messageFilter.endDate);
4734
5058
  }
4735
5059
  if (options?.messageFilter?.messageIds && options.messageFilter.messageIds.length > 0) {
@@ -4837,6 +5161,445 @@ var MemoryPG = class _MemoryPG extends MemoryStorage {
4837
5161
  );
4838
5162
  }
4839
5163
  }
5164
+ // ============================================
5165
+ // Observational Memory Methods
5166
+ // ============================================
5167
+ getOMKey(threadId, resourceId) {
5168
+ return threadId ? `thread:${threadId}` : `resource:${resourceId}`;
5169
+ }
5170
+ parseOMRow(row) {
5171
+ return {
5172
+ id: row.id,
5173
+ scope: row.scope,
5174
+ threadId: row.threadId || null,
5175
+ resourceId: row.resourceId,
5176
+ createdAt: new Date(row.createdAtZ),
5177
+ updatedAt: new Date(row.updatedAtZ),
5178
+ lastObservedAt: row.lastObservedAtZ ? new Date(row.lastObservedAtZ) : void 0,
5179
+ originType: row.originType || "initial",
5180
+ generationCount: Number(row.generationCount || 0),
5181
+ activeObservations: row.activeObservations || "",
5182
+ bufferedObservations: row.activeObservationsPendingUpdate || void 0,
5183
+ totalTokensObserved: Number(row.totalTokensObserved || 0),
5184
+ observationTokenCount: Number(row.observationTokenCount || 0),
5185
+ pendingMessageTokens: Number(row.pendingMessageTokens || 0),
5186
+ isReflecting: Boolean(row.isReflecting),
5187
+ isObserving: Boolean(row.isObserving),
5188
+ config: row.config ? typeof row.config === "string" ? JSON.parse(row.config) : row.config : {},
5189
+ metadata: row.metadata ? typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata : void 0,
5190
+ observedMessageIds: row.observedMessageIds ? typeof row.observedMessageIds === "string" ? JSON.parse(row.observedMessageIds) : row.observedMessageIds : void 0,
5191
+ observedTimezone: row.observedTimezone || void 0
5192
+ };
5193
+ }
5194
+ async getObservationalMemory(threadId, resourceId) {
5195
+ try {
5196
+ const lookupKey = this.getOMKey(threadId, resourceId);
5197
+ const tableName = getTableName3({
5198
+ indexName: OM_TABLE,
5199
+ schemaName: getSchemaName3(this.#schema)
5200
+ });
5201
+ const result = await this.#db.client.oneOrNone(
5202
+ `SELECT * FROM ${tableName} WHERE "lookupKey" = $1 ORDER BY "generationCount" DESC LIMIT 1`,
5203
+ [lookupKey]
5204
+ );
5205
+ if (!result) return null;
5206
+ return this.parseOMRow(result);
5207
+ } catch (error) {
5208
+ throw new MastraError(
5209
+ {
5210
+ id: createStorageErrorId("PG", "GET_OBSERVATIONAL_MEMORY", "FAILED"),
5211
+ domain: ErrorDomain.STORAGE,
5212
+ category: ErrorCategory.THIRD_PARTY,
5213
+ details: { threadId, resourceId }
5214
+ },
5215
+ error
5216
+ );
5217
+ }
5218
+ }
5219
+ async getObservationalMemoryHistory(threadId, resourceId, limit = 10) {
5220
+ try {
5221
+ const lookupKey = this.getOMKey(threadId, resourceId);
5222
+ const tableName = getTableName3({
5223
+ indexName: OM_TABLE,
5224
+ schemaName: getSchemaName3(this.#schema)
5225
+ });
5226
+ const result = await this.#db.client.manyOrNone(
5227
+ `SELECT * FROM ${tableName} WHERE "lookupKey" = $1 ORDER BY "generationCount" DESC LIMIT $2`,
5228
+ [lookupKey, limit]
5229
+ );
5230
+ if (!result) return [];
5231
+ return result.map((row) => this.parseOMRow(row));
5232
+ } catch (error) {
5233
+ throw new MastraError(
5234
+ {
5235
+ id: createStorageErrorId("PG", "GET_OBSERVATIONAL_MEMORY_HISTORY", "FAILED"),
5236
+ domain: ErrorDomain.STORAGE,
5237
+ category: ErrorCategory.THIRD_PARTY,
5238
+ details: { threadId, resourceId, limit }
5239
+ },
5240
+ error
5241
+ );
5242
+ }
5243
+ }
5244
+ async initializeObservationalMemory(input) {
5245
+ try {
5246
+ const id = crypto.randomUUID();
5247
+ const now = /* @__PURE__ */ new Date();
5248
+ const lookupKey = this.getOMKey(input.threadId, input.resourceId);
5249
+ const record = {
5250
+ id,
5251
+ scope: input.scope,
5252
+ threadId: input.threadId,
5253
+ resourceId: input.resourceId,
5254
+ createdAt: now,
5255
+ updatedAt: now,
5256
+ lastObservedAt: void 0,
5257
+ originType: "initial",
5258
+ generationCount: 0,
5259
+ activeObservations: "",
5260
+ totalTokensObserved: 0,
5261
+ observationTokenCount: 0,
5262
+ pendingMessageTokens: 0,
5263
+ isReflecting: false,
5264
+ isObserving: false,
5265
+ config: input.config,
5266
+ observedTimezone: input.observedTimezone
5267
+ };
5268
+ const tableName = getTableName3({
5269
+ indexName: OM_TABLE,
5270
+ schemaName: getSchemaName3(this.#schema)
5271
+ });
5272
+ const nowStr = now.toISOString();
5273
+ await this.#db.client.none(
5274
+ `INSERT INTO ${tableName} (
5275
+ id, "lookupKey", scope, "resourceId", "threadId",
5276
+ "activeObservations", "activeObservationsPendingUpdate",
5277
+ "originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
5278
+ "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
5279
+ "isObserving", "isReflecting", "observedTimezone", "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
5280
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)`,
5281
+ [
5282
+ id,
5283
+ lookupKey,
5284
+ input.scope,
5285
+ input.resourceId,
5286
+ input.threadId || null,
5287
+ "",
5288
+ null,
5289
+ "initial",
5290
+ JSON.stringify(input.config),
5291
+ 0,
5292
+ null,
5293
+ // lastObservedAt
5294
+ null,
5295
+ // lastObservedAtZ
5296
+ null,
5297
+ // lastReflectionAt
5298
+ null,
5299
+ // lastReflectionAtZ
5300
+ 0,
5301
+ 0,
5302
+ 0,
5303
+ false,
5304
+ false,
5305
+ input.observedTimezone || null,
5306
+ nowStr,
5307
+ // createdAt
5308
+ nowStr,
5309
+ // createdAtZ
5310
+ nowStr,
5311
+ // updatedAt
5312
+ nowStr
5313
+ // updatedAtZ
5314
+ ]
5315
+ );
5316
+ return record;
5317
+ } catch (error) {
5318
+ throw new MastraError(
5319
+ {
5320
+ id: createStorageErrorId("PG", "INITIALIZE_OBSERVATIONAL_MEMORY", "FAILED"),
5321
+ domain: ErrorDomain.STORAGE,
5322
+ category: ErrorCategory.THIRD_PARTY,
5323
+ details: { threadId: input.threadId, resourceId: input.resourceId }
5324
+ },
5325
+ error
5326
+ );
5327
+ }
5328
+ }
5329
+ async updateActiveObservations(input) {
5330
+ try {
5331
+ const now = /* @__PURE__ */ new Date();
5332
+ const tableName = getTableName3({
5333
+ indexName: OM_TABLE,
5334
+ schemaName: getSchemaName3(this.#schema)
5335
+ });
5336
+ const lastObservedAtStr = input.lastObservedAt.toISOString();
5337
+ const nowStr = now.toISOString();
5338
+ const observedMessageIdsJson = input.observedMessageIds ? JSON.stringify(input.observedMessageIds) : null;
5339
+ const result = await this.#db.client.query(
5340
+ `UPDATE ${tableName} SET
5341
+ "activeObservations" = $1,
5342
+ "lastObservedAt" = $2,
5343
+ "lastObservedAtZ" = $3,
5344
+ "pendingMessageTokens" = 0,
5345
+ "observationTokenCount" = $4,
5346
+ "totalTokensObserved" = "totalTokensObserved" + $5,
5347
+ "observedMessageIds" = $6,
5348
+ "updatedAt" = $7,
5349
+ "updatedAtZ" = $8
5350
+ WHERE id = $9`,
5351
+ [
5352
+ input.observations,
5353
+ lastObservedAtStr,
5354
+ lastObservedAtStr,
5355
+ input.tokenCount,
5356
+ input.tokenCount,
5357
+ observedMessageIdsJson,
5358
+ nowStr,
5359
+ nowStr,
5360
+ input.id
5361
+ ]
5362
+ );
5363
+ if (result.rowCount === 0) {
5364
+ throw new MastraError({
5365
+ id: createStorageErrorId("PG", "UPDATE_ACTIVE_OBSERVATIONS", "NOT_FOUND"),
5366
+ text: `Observational memory record not found: ${input.id}`,
5367
+ domain: ErrorDomain.STORAGE,
5368
+ category: ErrorCategory.THIRD_PARTY,
5369
+ details: { id: input.id }
5370
+ });
5371
+ }
5372
+ } catch (error) {
5373
+ if (error instanceof MastraError) {
5374
+ throw error;
5375
+ }
5376
+ throw new MastraError(
5377
+ {
5378
+ id: createStorageErrorId("PG", "UPDATE_ACTIVE_OBSERVATIONS", "FAILED"),
5379
+ domain: ErrorDomain.STORAGE,
5380
+ category: ErrorCategory.THIRD_PARTY,
5381
+ details: { id: input.id }
5382
+ },
5383
+ error
5384
+ );
5385
+ }
5386
+ }
5387
+ async createReflectionGeneration(input) {
5388
+ try {
5389
+ const id = crypto.randomUUID();
5390
+ const now = /* @__PURE__ */ new Date();
5391
+ const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
5392
+ const record = {
5393
+ id,
5394
+ scope: input.currentRecord.scope,
5395
+ threadId: input.currentRecord.threadId,
5396
+ resourceId: input.currentRecord.resourceId,
5397
+ createdAt: now,
5398
+ updatedAt: now,
5399
+ lastObservedAt: input.currentRecord.lastObservedAt,
5400
+ originType: "reflection",
5401
+ generationCount: input.currentRecord.generationCount + 1,
5402
+ activeObservations: input.reflection,
5403
+ totalTokensObserved: input.currentRecord.totalTokensObserved,
5404
+ observationTokenCount: input.tokenCount,
5405
+ pendingMessageTokens: 0,
5406
+ isReflecting: false,
5407
+ isObserving: false,
5408
+ config: input.currentRecord.config,
5409
+ metadata: input.currentRecord.metadata,
5410
+ observedTimezone: input.currentRecord.observedTimezone
5411
+ };
5412
+ const tableName = getTableName3({
5413
+ indexName: OM_TABLE,
5414
+ schemaName: getSchemaName3(this.#schema)
5415
+ });
5416
+ const nowStr = now.toISOString();
5417
+ const lastObservedAtStr = record.lastObservedAt?.toISOString() || null;
5418
+ await this.#db.client.none(
5419
+ `INSERT INTO ${tableName} (
5420
+ id, "lookupKey", scope, "resourceId", "threadId",
5421
+ "activeObservations", "activeObservationsPendingUpdate",
5422
+ "originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
5423
+ "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
5424
+ "isObserving", "isReflecting", "observedTimezone", "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
5425
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)`,
5426
+ [
5427
+ id,
5428
+ lookupKey,
5429
+ record.scope,
5430
+ record.resourceId,
5431
+ record.threadId || null,
5432
+ input.reflection,
5433
+ null,
5434
+ "reflection",
5435
+ JSON.stringify(record.config),
5436
+ input.currentRecord.generationCount + 1,
5437
+ lastObservedAtStr,
5438
+ // lastObservedAt
5439
+ lastObservedAtStr,
5440
+ // lastObservedAtZ
5441
+ nowStr,
5442
+ // lastReflectionAt
5443
+ nowStr,
5444
+ // lastReflectionAtZ
5445
+ record.pendingMessageTokens,
5446
+ record.totalTokensObserved,
5447
+ record.observationTokenCount,
5448
+ false,
5449
+ false,
5450
+ record.observedTimezone || null,
5451
+ nowStr,
5452
+ // createdAt
5453
+ nowStr,
5454
+ // createdAtZ
5455
+ nowStr,
5456
+ // updatedAt
5457
+ nowStr
5458
+ // updatedAtZ
5459
+ ]
5460
+ );
5461
+ return record;
5462
+ } catch (error) {
5463
+ throw new MastraError(
5464
+ {
5465
+ id: createStorageErrorId("PG", "CREATE_REFLECTION_GENERATION", "FAILED"),
5466
+ domain: ErrorDomain.STORAGE,
5467
+ category: ErrorCategory.THIRD_PARTY,
5468
+ details: { currentRecordId: input.currentRecord.id }
5469
+ },
5470
+ error
5471
+ );
5472
+ }
5473
+ }
5474
+ async setReflectingFlag(id, isReflecting) {
5475
+ try {
5476
+ const tableName = getTableName3({
5477
+ indexName: OM_TABLE,
5478
+ schemaName: getSchemaName3(this.#schema)
5479
+ });
5480
+ const nowStr = (/* @__PURE__ */ new Date()).toISOString();
5481
+ const result = await this.#db.client.query(
5482
+ `UPDATE ${tableName} SET "isReflecting" = $1, "updatedAt" = $2, "updatedAtZ" = $3 WHERE id = $4`,
5483
+ [isReflecting, nowStr, nowStr, id]
5484
+ );
5485
+ if (result.rowCount === 0) {
5486
+ throw new MastraError({
5487
+ id: createStorageErrorId("PG", "SET_REFLECTING_FLAG", "NOT_FOUND"),
5488
+ text: `Observational memory record not found: ${id}`,
5489
+ domain: ErrorDomain.STORAGE,
5490
+ category: ErrorCategory.THIRD_PARTY,
5491
+ details: { id, isReflecting }
5492
+ });
5493
+ }
5494
+ } catch (error) {
5495
+ if (error instanceof MastraError) {
5496
+ throw error;
5497
+ }
5498
+ throw new MastraError(
5499
+ {
5500
+ id: createStorageErrorId("PG", "SET_REFLECTING_FLAG", "FAILED"),
5501
+ domain: ErrorDomain.STORAGE,
5502
+ category: ErrorCategory.THIRD_PARTY,
5503
+ details: { id, isReflecting }
5504
+ },
5505
+ error
5506
+ );
5507
+ }
5508
+ }
5509
+ async setObservingFlag(id, isObserving) {
5510
+ try {
5511
+ const tableName = getTableName3({
5512
+ indexName: OM_TABLE,
5513
+ schemaName: getSchemaName3(this.#schema)
5514
+ });
5515
+ const nowStr = (/* @__PURE__ */ new Date()).toISOString();
5516
+ const result = await this.#db.client.query(
5517
+ `UPDATE ${tableName} SET "isObserving" = $1, "updatedAt" = $2, "updatedAtZ" = $3 WHERE id = $4`,
5518
+ [isObserving, nowStr, nowStr, id]
5519
+ );
5520
+ if (result.rowCount === 0) {
5521
+ throw new MastraError({
5522
+ id: createStorageErrorId("PG", "SET_OBSERVING_FLAG", "NOT_FOUND"),
5523
+ text: `Observational memory record not found: ${id}`,
5524
+ domain: ErrorDomain.STORAGE,
5525
+ category: ErrorCategory.THIRD_PARTY,
5526
+ details: { id, isObserving }
5527
+ });
5528
+ }
5529
+ } catch (error) {
5530
+ if (error instanceof MastraError) {
5531
+ throw error;
5532
+ }
5533
+ throw new MastraError(
5534
+ {
5535
+ id: createStorageErrorId("PG", "SET_OBSERVING_FLAG", "FAILED"),
5536
+ domain: ErrorDomain.STORAGE,
5537
+ category: ErrorCategory.THIRD_PARTY,
5538
+ details: { id, isObserving }
5539
+ },
5540
+ error
5541
+ );
5542
+ }
5543
+ }
5544
+ async clearObservationalMemory(threadId, resourceId) {
5545
+ try {
5546
+ const lookupKey = this.getOMKey(threadId, resourceId);
5547
+ const tableName = getTableName3({
5548
+ indexName: OM_TABLE,
5549
+ schemaName: getSchemaName3(this.#schema)
5550
+ });
5551
+ await this.#db.client.none(`DELETE FROM ${tableName} WHERE "lookupKey" = $1`, [lookupKey]);
5552
+ } catch (error) {
5553
+ throw new MastraError(
5554
+ {
5555
+ id: createStorageErrorId("PG", "CLEAR_OBSERVATIONAL_MEMORY", "FAILED"),
5556
+ domain: ErrorDomain.STORAGE,
5557
+ category: ErrorCategory.THIRD_PARTY,
5558
+ details: { threadId, resourceId }
5559
+ },
5560
+ error
5561
+ );
5562
+ }
5563
+ }
5564
+ async addPendingMessageTokens(id, tokenCount) {
5565
+ try {
5566
+ const tableName = getTableName3({
5567
+ indexName: OM_TABLE,
5568
+ schemaName: getSchemaName3(this.#schema)
5569
+ });
5570
+ const nowStr = (/* @__PURE__ */ new Date()).toISOString();
5571
+ const result = await this.#db.client.query(
5572
+ `UPDATE ${tableName} SET
5573
+ "pendingMessageTokens" = "pendingMessageTokens" + $1,
5574
+ "updatedAt" = $2,
5575
+ "updatedAtZ" = $3
5576
+ WHERE id = $4`,
5577
+ [tokenCount, nowStr, nowStr, id]
5578
+ );
5579
+ if (result.rowCount === 0) {
5580
+ throw new MastraError({
5581
+ id: createStorageErrorId("PG", "ADD_PENDING_MESSAGE_TOKENS", "NOT_FOUND"),
5582
+ text: `Observational memory record not found: ${id}`,
5583
+ domain: ErrorDomain.STORAGE,
5584
+ category: ErrorCategory.THIRD_PARTY,
5585
+ details: { id, tokenCount }
5586
+ });
5587
+ }
5588
+ } catch (error) {
5589
+ if (error instanceof MastraError) {
5590
+ throw error;
5591
+ }
5592
+ throw new MastraError(
5593
+ {
5594
+ id: createStorageErrorId("PG", "ADD_PENDING_MESSAGE_TOKENS", "FAILED"),
5595
+ domain: ErrorDomain.STORAGE,
5596
+ category: ErrorCategory.THIRD_PARTY,
5597
+ details: { id, tokenCount }
5598
+ },
5599
+ error
5600
+ );
5601
+ }
5602
+ }
4840
5603
  };
4841
5604
  var ObservabilityPG = class _ObservabilityPG extends ObservabilityStorage {
4842
5605
  #db;