@mastra/pg 1.27.1 → 1.27.2-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.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +179 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +179 -131
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/test-utils.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -10349,6 +10349,12 @@ var MCPServersPG = class MCPServersPG extends MCPServersStorage {
|
|
|
10349
10349
|
* versions that don't export TABLE_OBSERVATIONAL_MEMORY.
|
|
10350
10350
|
*/
|
|
10351
10351
|
const OM_TABLE = "mastra_observational_memory";
|
|
10352
|
+
/**
|
|
10353
|
+
* Newest generation first. Databases written before generation creation was
|
|
10354
|
+
* serialized can hold several rows with the same generation; the earliest-created
|
|
10355
|
+
* one wins so the active record stays stable across reads.
|
|
10356
|
+
*/
|
|
10357
|
+
const OM_GENERATION_ORDER = `"generationCount" DESC, "createdAt" ASC, id ASC`;
|
|
10352
10358
|
const POSTGRES_MAX_BIND_PARAMETERS = 65535;
|
|
10353
10359
|
const MESSAGE_INSERT_BIND_PARAMETERS = 8;
|
|
10354
10360
|
const MAX_MESSAGES_PER_INSERT = Math.floor(POSTGRES_MAX_BIND_PARAMETERS / MESSAGE_INSERT_BIND_PARAMETERS);
|
|
@@ -11950,6 +11956,23 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
11950
11956
|
getOMKey(threadId, resourceId) {
|
|
11951
11957
|
return threadId ? `thread:${threadId}` : `resource:${resourceId}`;
|
|
11952
11958
|
}
|
|
11959
|
+
/**
|
|
11960
|
+
* Runs `fn` in a transaction that holds an advisory lock for one OM lookup key.
|
|
11961
|
+
*
|
|
11962
|
+
* The table has no unique constraint on ("lookupKey", "generationCount"), and
|
|
11963
|
+
* adding one would fail on databases that already contain duplicates. The lock
|
|
11964
|
+
* serializes generation creation across processes instead. It is
|
|
11965
|
+
* transaction-scoped so it also works behind transaction-pooling proxies.
|
|
11966
|
+
*/
|
|
11967
|
+
async #withOMLookupKeyLock(tableName, lookupKey, fn) {
|
|
11968
|
+
return this.#db.client.tx(async (t) => {
|
|
11969
|
+
await t.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [`${tableName}:${lookupKey}`]);
|
|
11970
|
+
return fn(t);
|
|
11971
|
+
});
|
|
11972
|
+
}
|
|
11973
|
+
async #getLatestOMRow(client, tableName, lookupKey) {
|
|
11974
|
+
return client.oneOrNone(`SELECT * FROM ${tableName} WHERE "lookupKey" = $1 ORDER BY ${OM_GENERATION_ORDER} LIMIT 1`, [lookupKey]);
|
|
11975
|
+
}
|
|
11953
11976
|
parseOMRow(row) {
|
|
11954
11977
|
return {
|
|
11955
11978
|
id: row.id,
|
|
@@ -11992,7 +12015,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
11992
12015
|
indexName: OM_TABLE,
|
|
11993
12016
|
schemaName: getSchemaName$3(this.#schema)
|
|
11994
12017
|
});
|
|
11995
|
-
const result = await this.#db.readClient
|
|
12018
|
+
const result = await this.#getLatestOMRow(this.#db.readClient, tableName, lookupKey);
|
|
11996
12019
|
if (!result) return null;
|
|
11997
12020
|
return this.parseOMRow(result);
|
|
11998
12021
|
} catch (error) {
|
|
@@ -12028,7 +12051,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12028
12051
|
paramIndex++;
|
|
12029
12052
|
}
|
|
12030
12053
|
params.push(limit);
|
|
12031
|
-
let sql = `SELECT * FROM ${tableName} WHERE ${conditions.join(" AND ")} ORDER BY
|
|
12054
|
+
let sql = `SELECT * FROM ${tableName} WHERE ${conditions.join(" AND ")} ORDER BY ${OM_GENERATION_ORDER} LIMIT $${paramIndex}`;
|
|
12032
12055
|
paramIndex++;
|
|
12033
12056
|
if (options?.offset != null) {
|
|
12034
12057
|
params.push(options.offset);
|
|
@@ -12083,7 +12106,10 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12083
12106
|
schemaName: getSchemaName$3(this.#schema)
|
|
12084
12107
|
});
|
|
12085
12108
|
const nowStr = now.toISOString();
|
|
12086
|
-
await this.#
|
|
12109
|
+
return await this.#withOMLookupKeyLock(tableName, lookupKey, async (t) => {
|
|
12110
|
+
const existing = await this.#getLatestOMRow(t, tableName, lookupKey);
|
|
12111
|
+
if (existing) return this.parseOMRow(existing);
|
|
12112
|
+
await t.none(`INSERT INTO ${tableName} (
|
|
12087
12113
|
id, "lookupKey", scope, "resourceId", "threadId",
|
|
12088
12114
|
"activeObservations", "activeObservationsPendingUpdate",
|
|
12089
12115
|
"originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
|
|
@@ -12091,36 +12117,37 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12091
12117
|
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
12092
12118
|
"observedTimezone", "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
12093
12119
|
) 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, $25, $26, $27, $28)`, [
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12120
|
+
id,
|
|
12121
|
+
lookupKey,
|
|
12122
|
+
input.scope,
|
|
12123
|
+
input.resourceId,
|
|
12124
|
+
input.threadId || null,
|
|
12125
|
+
"",
|
|
12126
|
+
null,
|
|
12127
|
+
"initial",
|
|
12128
|
+
toPgJson(input.config),
|
|
12129
|
+
0,
|
|
12130
|
+
null,
|
|
12131
|
+
null,
|
|
12132
|
+
null,
|
|
12133
|
+
null,
|
|
12134
|
+
0,
|
|
12135
|
+
0,
|
|
12136
|
+
0,
|
|
12137
|
+
false,
|
|
12138
|
+
false,
|
|
12139
|
+
false,
|
|
12140
|
+
false,
|
|
12141
|
+
0,
|
|
12142
|
+
null,
|
|
12143
|
+
input.observedTimezone || null,
|
|
12144
|
+
nowStr,
|
|
12145
|
+
nowStr,
|
|
12146
|
+
nowStr,
|
|
12147
|
+
nowStr
|
|
12148
|
+
]);
|
|
12149
|
+
return record;
|
|
12150
|
+
});
|
|
12124
12151
|
} catch (error) {
|
|
12125
12152
|
throw new MastraError({
|
|
12126
12153
|
id: createStorageErrorId("PG", "INITIALIZE_OBSERVATIONAL_MEMORY", "FAILED"),
|
|
@@ -12252,78 +12279,16 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12252
12279
|
}
|
|
12253
12280
|
async createReflectionGeneration(input) {
|
|
12254
12281
|
try {
|
|
12255
|
-
const id = crypto.randomUUID();
|
|
12256
|
-
const now = /* @__PURE__ */ new Date();
|
|
12257
12282
|
const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
|
|
12258
|
-
const record = {
|
|
12259
|
-
id,
|
|
12260
|
-
scope: input.currentRecord.scope,
|
|
12261
|
-
threadId: input.currentRecord.threadId,
|
|
12262
|
-
resourceId: input.currentRecord.resourceId,
|
|
12263
|
-
createdAt: now,
|
|
12264
|
-
updatedAt: now,
|
|
12265
|
-
lastObservedAt: input.currentRecord.lastObservedAt,
|
|
12266
|
-
originType: "reflection",
|
|
12267
|
-
generationCount: input.currentRecord.generationCount + 1,
|
|
12268
|
-
activeObservations: input.reflection,
|
|
12269
|
-
totalTokensObserved: input.currentRecord.totalTokensObserved,
|
|
12270
|
-
observationTokenCount: input.tokenCount,
|
|
12271
|
-
pendingMessageTokens: 0,
|
|
12272
|
-
isReflecting: false,
|
|
12273
|
-
isObserving: false,
|
|
12274
|
-
isBufferingObservation: false,
|
|
12275
|
-
isBufferingReflection: false,
|
|
12276
|
-
lastBufferedAtTokens: 0,
|
|
12277
|
-
lastBufferedAtTime: null,
|
|
12278
|
-
config: input.currentRecord.config,
|
|
12279
|
-
metadata: input.currentRecord.metadata,
|
|
12280
|
-
observedTimezone: input.currentRecord.observedTimezone
|
|
12281
|
-
};
|
|
12282
12283
|
const tableName = getTableName$3({
|
|
12283
12284
|
indexName: OM_TABLE,
|
|
12284
12285
|
schemaName: getSchemaName$3(this.#schema)
|
|
12285
12286
|
});
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
"originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
|
|
12292
|
-
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
|
|
12293
|
-
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
12294
|
-
"observedTimezone", metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
12295
|
-
) 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, $25, $26, $27, $28, $29)`, [
|
|
12296
|
-
id,
|
|
12297
|
-
lookupKey,
|
|
12298
|
-
record.scope,
|
|
12299
|
-
record.resourceId,
|
|
12300
|
-
record.threadId || null,
|
|
12301
|
-
input.reflection,
|
|
12302
|
-
null,
|
|
12303
|
-
"reflection",
|
|
12304
|
-
toPgJson(record.config),
|
|
12305
|
-
input.currentRecord.generationCount + 1,
|
|
12306
|
-
lastObservedAtStr,
|
|
12307
|
-
lastObservedAtStr,
|
|
12308
|
-
nowStr,
|
|
12309
|
-
nowStr,
|
|
12310
|
-
record.pendingMessageTokens,
|
|
12311
|
-
Math.round(record.totalTokensObserved),
|
|
12312
|
-
Math.round(record.observationTokenCount),
|
|
12313
|
-
false,
|
|
12314
|
-
false,
|
|
12315
|
-
false,
|
|
12316
|
-
false,
|
|
12317
|
-
0,
|
|
12318
|
-
null,
|
|
12319
|
-
record.observedTimezone || null,
|
|
12320
|
-
record.metadata ? toPgJson(record.metadata) : null,
|
|
12321
|
-
nowStr,
|
|
12322
|
-
nowStr,
|
|
12323
|
-
nowStr,
|
|
12324
|
-
nowStr
|
|
12325
|
-
]);
|
|
12326
|
-
return record;
|
|
12287
|
+
return await this.#withOMLookupKeyLock(tableName, lookupKey, async (t) => {
|
|
12288
|
+
const newer = await this.#getNewerOMGeneration(t, tableName, lookupKey, input.currentRecord.generationCount);
|
|
12289
|
+
if (newer) return newer;
|
|
12290
|
+
return this.#insertReflectionGeneration(t, tableName, lookupKey, input);
|
|
12291
|
+
});
|
|
12327
12292
|
} catch (error) {
|
|
12328
12293
|
throw new MastraError({
|
|
12329
12294
|
id: createStorageErrorId("PG", "CREATE_REFLECTION_GENERATION", "FAILED"),
|
|
@@ -12333,6 +12298,84 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12333
12298
|
}, error);
|
|
12334
12299
|
}
|
|
12335
12300
|
}
|
|
12301
|
+
/**
|
|
12302
|
+
* Returns the active record when another writer already created a generation
|
|
12303
|
+
* after `generationCount`. Reflecting from the older generation again would
|
|
12304
|
+
* add a second record with the same generation.
|
|
12305
|
+
*/
|
|
12306
|
+
async #getNewerOMGeneration(t, tableName, lookupKey, generationCount) {
|
|
12307
|
+
const latest = await this.#getLatestOMRow(t, tableName, lookupKey);
|
|
12308
|
+
return latest && Number(latest.generationCount) > generationCount ? this.parseOMRow(latest) : null;
|
|
12309
|
+
}
|
|
12310
|
+
async #insertReflectionGeneration(t, tableName, lookupKey, input) {
|
|
12311
|
+
const id = crypto.randomUUID();
|
|
12312
|
+
const now = /* @__PURE__ */ new Date();
|
|
12313
|
+
const record = {
|
|
12314
|
+
id,
|
|
12315
|
+
scope: input.currentRecord.scope,
|
|
12316
|
+
threadId: input.currentRecord.threadId,
|
|
12317
|
+
resourceId: input.currentRecord.resourceId,
|
|
12318
|
+
createdAt: now,
|
|
12319
|
+
updatedAt: now,
|
|
12320
|
+
lastObservedAt: input.currentRecord.lastObservedAt,
|
|
12321
|
+
originType: "reflection",
|
|
12322
|
+
generationCount: input.currentRecord.generationCount + 1,
|
|
12323
|
+
activeObservations: input.reflection,
|
|
12324
|
+
totalTokensObserved: input.currentRecord.totalTokensObserved,
|
|
12325
|
+
observationTokenCount: input.tokenCount,
|
|
12326
|
+
pendingMessageTokens: 0,
|
|
12327
|
+
isReflecting: false,
|
|
12328
|
+
isObserving: false,
|
|
12329
|
+
isBufferingObservation: false,
|
|
12330
|
+
isBufferingReflection: false,
|
|
12331
|
+
lastBufferedAtTokens: 0,
|
|
12332
|
+
lastBufferedAtTime: null,
|
|
12333
|
+
config: input.currentRecord.config,
|
|
12334
|
+
metadata: input.currentRecord.metadata,
|
|
12335
|
+
observedTimezone: input.currentRecord.observedTimezone
|
|
12336
|
+
};
|
|
12337
|
+
const nowStr = now.toISOString();
|
|
12338
|
+
const lastObservedAtStr = record.lastObservedAt?.toISOString() || null;
|
|
12339
|
+
await t.none(`INSERT INTO ${tableName} (
|
|
12340
|
+
id, "lookupKey", scope, "resourceId", "threadId",
|
|
12341
|
+
"activeObservations", "activeObservationsPendingUpdate",
|
|
12342
|
+
"originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
|
|
12343
|
+
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
|
|
12344
|
+
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
12345
|
+
"observedTimezone", metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
12346
|
+
) 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, $25, $26, $27, $28, $29)`, [
|
|
12347
|
+
id,
|
|
12348
|
+
lookupKey,
|
|
12349
|
+
record.scope,
|
|
12350
|
+
record.resourceId,
|
|
12351
|
+
record.threadId || null,
|
|
12352
|
+
input.reflection,
|
|
12353
|
+
null,
|
|
12354
|
+
"reflection",
|
|
12355
|
+
toPgJson(record.config),
|
|
12356
|
+
input.currentRecord.generationCount + 1,
|
|
12357
|
+
lastObservedAtStr,
|
|
12358
|
+
lastObservedAtStr,
|
|
12359
|
+
nowStr,
|
|
12360
|
+
nowStr,
|
|
12361
|
+
record.pendingMessageTokens,
|
|
12362
|
+
Math.round(record.totalTokensObserved),
|
|
12363
|
+
Math.round(record.observationTokenCount),
|
|
12364
|
+
false,
|
|
12365
|
+
false,
|
|
12366
|
+
false,
|
|
12367
|
+
false,
|
|
12368
|
+
0,
|
|
12369
|
+
null,
|
|
12370
|
+
record.observedTimezone || null,
|
|
12371
|
+
record.metadata ? toPgJson(record.metadata) : null,
|
|
12372
|
+
nowStr,
|
|
12373
|
+
nowStr,
|
|
12374
|
+
nowStr,
|
|
12375
|
+
nowStr
|
|
12376
|
+
]);
|
|
12377
|
+
return record;
|
|
12378
|
+
}
|
|
12336
12379
|
async setReflectingFlag(id, isReflecting) {
|
|
12337
12380
|
try {
|
|
12338
12381
|
const tableName = getTableName$3({
|
|
@@ -12827,32 +12870,36 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12827
12870
|
indexName: OM_TABLE,
|
|
12828
12871
|
schemaName: getSchemaName$3(this.#schema)
|
|
12829
12872
|
});
|
|
12830
|
-
const
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
|
|
12849
|
-
|
|
12850
|
-
|
|
12851
|
-
|
|
12852
|
-
|
|
12853
|
-
|
|
12854
|
-
|
|
12855
|
-
|
|
12873
|
+
const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
|
|
12874
|
+
return await this.#withOMLookupKeyLock(tableName, lookupKey, async (t) => {
|
|
12875
|
+
const newer = await this.#getNewerOMGeneration(t, tableName, lookupKey, input.currentRecord.generationCount);
|
|
12876
|
+
if (newer) return newer;
|
|
12877
|
+
const record = await t.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [input.currentRecord.id]);
|
|
12878
|
+
if (!record) throw new MastraError({
|
|
12879
|
+
id: createStorageErrorId("PG", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NOT_FOUND"),
|
|
12880
|
+
text: `Observational memory record not found: ${input.currentRecord.id}`,
|
|
12881
|
+
domain: ErrorDomain.STORAGE,
|
|
12882
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
12883
|
+
details: { id: input.currentRecord.id }
|
|
12884
|
+
});
|
|
12885
|
+
const bufferedReflection = record.bufferedReflection || "";
|
|
12886
|
+
const reflectedLineCount = Number(record.reflectedObservationLineCount || 0);
|
|
12887
|
+
if (!bufferedReflection) throw new MastraError({
|
|
12888
|
+
id: createStorageErrorId("PG", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NO_CONTENT"),
|
|
12889
|
+
text: "No buffered reflection to swap",
|
|
12890
|
+
domain: ErrorDomain.STORAGE,
|
|
12891
|
+
category: ErrorCategory.USER,
|
|
12892
|
+
details: { id: input.currentRecord.id }
|
|
12893
|
+
});
|
|
12894
|
+
const unreflectedContent = (record.activeObservations || "").split("\n").slice(reflectedLineCount).join("\n").trim();
|
|
12895
|
+
const newObservations = unreflectedContent ? `${bufferedReflection}\n\n${unreflectedContent}` : bufferedReflection;
|
|
12896
|
+
const newRecord = await this.#insertReflectionGeneration(t, tableName, lookupKey, {
|
|
12897
|
+
currentRecord: input.currentRecord,
|
|
12898
|
+
reflection: newObservations,
|
|
12899
|
+
tokenCount: input.tokenCount
|
|
12900
|
+
});
|
|
12901
|
+
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
12902
|
+
await t.query(`UPDATE ${tableName} SET
|
|
12856
12903
|
"bufferedReflection" = NULL,
|
|
12857
12904
|
"bufferedReflectionTokens" = NULL,
|
|
12858
12905
|
"bufferedReflectionInputTokens" = NULL,
|
|
@@ -12860,11 +12907,12 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12860
12907
|
"updatedAt" = $1,
|
|
12861
12908
|
"updatedAtZ" = $2
|
|
12862
12909
|
WHERE id = $3`, [
|
|
12863
|
-
|
|
12864
|
-
|
|
12865
|
-
|
|
12866
|
-
|
|
12867
|
-
|
|
12910
|
+
nowStr,
|
|
12911
|
+
nowStr,
|
|
12912
|
+
input.currentRecord.id
|
|
12913
|
+
]);
|
|
12914
|
+
return newRecord;
|
|
12915
|
+
});
|
|
12868
12916
|
} catch (error) {
|
|
12869
12917
|
if (error instanceof MastraError) throw error;
|
|
12870
12918
|
throw new MastraError({
|