@mastra/pg 1.31.0 → 1.31.1-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/_types/@internal_core/dist/memory/index.d.ts +102 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +502 -344
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +502 -344
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +3 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -11611,6 +11611,92 @@ var MCPServersPG = class MCPServersPG extends _mastra_core_storage.MCPServersSto
|
|
|
11611
11611
|
}
|
|
11612
11612
|
};
|
|
11613
11613
|
//#endregion
|
|
11614
|
+
//#region ../../packages/_internal-core/dist/memory/index.js
|
|
11615
|
+
/**
|
|
11616
|
+
* Shared rules for observational memory lifecycle writes. Every storage adapter applies
|
|
11617
|
+
* these inside its own atomic section (lock, transaction, or conditional update), so the
|
|
11618
|
+
* decisions are identical across adapters.
|
|
11619
|
+
*/
|
|
11620
|
+
/**
|
|
11621
|
+
* Observational memory columns that lifecycle writes depend on. Storage adapters merge these
|
|
11622
|
+
* into the table schema they get from `@mastra/core`, so the columns exist even when the
|
|
11623
|
+
* installed core predates them.
|
|
11624
|
+
*/
|
|
11625
|
+
const OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS = { supersededBy: {
|
|
11626
|
+
type: "text",
|
|
11627
|
+
nullable: true
|
|
11628
|
+
} };
|
|
11629
|
+
/** `schema` plus {@link OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS}; `undefined` when `schema` is. */
|
|
11630
|
+
function withObservationalMemoryLifecycleColumns(schema) {
|
|
11631
|
+
return schema ? {
|
|
11632
|
+
...schema,
|
|
11633
|
+
...OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS
|
|
11634
|
+
} : void 0;
|
|
11635
|
+
}
|
|
11636
|
+
/**
|
|
11637
|
+
* A buffered chunk stores `lastObservedAt = max message time + 1ms`. It is wholly covered
|
|
11638
|
+
* (every message it observed is already at or before the cursor) iff
|
|
11639
|
+
* `cursor >= chunk.lastObservedAt - 1ms`.
|
|
11640
|
+
*/
|
|
11641
|
+
function isBufferedChunkCoveredByCursor(chunkLastObservedAt, cursor) {
|
|
11642
|
+
if (!cursor) return false;
|
|
11643
|
+
return new Date(cursor).getTime() >= new Date(chunkLastObservedAt).getTime() - 1;
|
|
11644
|
+
}
|
|
11645
|
+
/** The later of two cursors; `undefined` only when both are absent. */
|
|
11646
|
+
function maxObservationCursor(a, b) {
|
|
11647
|
+
if (!a) return b ? new Date(b) : void 0;
|
|
11648
|
+
if (!b) return new Date(a);
|
|
11649
|
+
return new Date(Math.max(new Date(a).getTime(), new Date(b).getTime()));
|
|
11650
|
+
}
|
|
11651
|
+
/**
|
|
11652
|
+
* Decide the new generation's text when a reflection built from `snapshot` commits against
|
|
11653
|
+
* the stored record.
|
|
11654
|
+
*
|
|
11655
|
+
* - Stored text equals the snapshot: the reflection replaces it.
|
|
11656
|
+
* - Stored text extends the snapshot (activation only appends): the appended tail is kept
|
|
11657
|
+
* after the reflection, and its tokens are added.
|
|
11658
|
+
* - Anything else (a non-append rewrite): `null` — the reflection must not be applied.
|
|
11659
|
+
*/
|
|
11660
|
+
function planReflectionGenerationText(input) {
|
|
11661
|
+
const stored = input.storedObservations ?? "";
|
|
11662
|
+
const snapshot = input.snapshotObservations ?? "";
|
|
11663
|
+
if (stored === snapshot) return {
|
|
11664
|
+
mode: "equal",
|
|
11665
|
+
observations: input.reflection,
|
|
11666
|
+
tokenCount: input.tokenCount
|
|
11667
|
+
};
|
|
11668
|
+
if (!stored.startsWith(snapshot)) return null;
|
|
11669
|
+
const tail = stored.slice(snapshot.length).trimStart();
|
|
11670
|
+
if (!tail.trim()) return {
|
|
11671
|
+
mode: "equal",
|
|
11672
|
+
observations: input.reflection,
|
|
11673
|
+
tokenCount: input.tokenCount
|
|
11674
|
+
};
|
|
11675
|
+
return {
|
|
11676
|
+
mode: "append",
|
|
11677
|
+
observations: input.reflection ? `${input.reflection}\n\n${tail}` : tail,
|
|
11678
|
+
tokenCount: input.tokenCount + Math.max(0, (input.storedObservationTokenCount ?? 0) - (input.snapshotObservationTokenCount ?? 0))
|
|
11679
|
+
};
|
|
11680
|
+
}
|
|
11681
|
+
/**
|
|
11682
|
+
* Backs `updateActiveObservations` in adapters that implement `commitActiveObservations`.
|
|
11683
|
+
* Callers of `updateActiveObservations` (which resolves `void`) can't see a commit result, so a
|
|
11684
|
+
* write that was not applied throws instead of resolving as if it had committed.
|
|
11685
|
+
*/
|
|
11686
|
+
function assertActiveObservationsApplied(result, id) {
|
|
11687
|
+
if (result.applied) return;
|
|
11688
|
+
throw new Error(result.reason === "retired" ? `Observational memory record ${id} was superseded by a newer generation; observations were not written` : `Observational memory record ${id} changed since the observations were composed; observations were not written`);
|
|
11689
|
+
}
|
|
11690
|
+
/**
|
|
11691
|
+
* Whether the stored text can still accept a reflection built from `snapshot`
|
|
11692
|
+
* (equal, or only appended to since).
|
|
11693
|
+
*/
|
|
11694
|
+
function isAppendOnlySince(storedObservations, snapshotObservations) {
|
|
11695
|
+
const stored = storedObservations ?? "";
|
|
11696
|
+
const snapshot = snapshotObservations ?? "";
|
|
11697
|
+
return stored === snapshot || stored.startsWith(snapshot);
|
|
11698
|
+
}
|
|
11699
|
+
//#endregion
|
|
11614
11700
|
//#region src/storage/db/run-fencing.ts
|
|
11615
11701
|
/**
|
|
11616
11702
|
* Epoch milliseconds on the database clock. `clock_timestamp()` rather than
|
|
@@ -11656,6 +11742,8 @@ const OM_TABLE = "mastra_observational_memory";
|
|
|
11656
11742
|
* one wins so the active record stays stable across reads.
|
|
11657
11743
|
*/
|
|
11658
11744
|
const OM_GENERATION_ORDER = `"generationCount" DESC, "createdAt" ASC, id ASC`;
|
|
11745
|
+
/** Lifecycle writes aimed at a retired record follow it to the head at most this many times. */
|
|
11746
|
+
const OM_MAX_HEAD_HOPS = 3;
|
|
11659
11747
|
const POSTGRES_MAX_BIND_PARAMETERS = 65535;
|
|
11660
11748
|
const MESSAGE_INSERT_BIND_PARAMETERS = 8;
|
|
11661
11749
|
const MAX_MESSAGES_PER_INSERT = Math.floor(POSTGRES_MAX_BIND_PARAMETERS / MESSAGE_INSERT_BIND_PARAMETERS);
|
|
@@ -11683,7 +11771,8 @@ const OM_MIGRATION_COLUMNS = [
|
|
|
11683
11771
|
"isBufferingReflection",
|
|
11684
11772
|
"lastBufferedAtTokens",
|
|
11685
11773
|
"lastBufferedAtTime",
|
|
11686
|
-
"metadata"
|
|
11774
|
+
"metadata",
|
|
11775
|
+
"supersededBy"
|
|
11687
11776
|
];
|
|
11688
11777
|
/**
|
|
11689
11778
|
* The OM schema is imported statically above: the peer dependency range
|
|
@@ -11693,7 +11782,10 @@ const OM_MIGRATION_COLUMNS = [
|
|
|
11693
11782
|
* bundle to a shim that always throws, and the silent catch meant the
|
|
11694
11783
|
* published ESM build skipped creating the OM table entirely (#18954).
|
|
11695
11784
|
*/
|
|
11696
|
-
const _omTableSchema =
|
|
11785
|
+
const _omTableSchema = {
|
|
11786
|
+
..._mastra_core_storage.OBSERVATIONAL_MEMORY_TABLE_SCHEMA,
|
|
11787
|
+
[OM_TABLE]: withObservationalMemoryLifecycleColumns(_mastra_core_storage.OBSERVATIONAL_MEMORY_TABLE_SCHEMA?.[OM_TABLE])
|
|
11788
|
+
};
|
|
11697
11789
|
function getSchemaName$3(schema) {
|
|
11698
11790
|
return schema ? `"${schema}"` : "\"public\"";
|
|
11699
11791
|
}
|
|
@@ -11717,6 +11809,14 @@ function inPlaceholders(count, startIndex = 1) {
|
|
|
11717
11809
|
function toUtcISOString(date) {
|
|
11718
11810
|
return date.toISOString();
|
|
11719
11811
|
}
|
|
11812
|
+
/**
|
|
11813
|
+
* Read a `timestamp without time zone` column written from a UTC ISO string. Postgres drops the
|
|
11814
|
+
* zone on input, so the stored wall time is UTC; node-postgres parses it as local time.
|
|
11815
|
+
*/
|
|
11816
|
+
function utcFromTimestampWithoutTimeZone(value) {
|
|
11817
|
+
if (value instanceof Date) return new Date(Date.UTC(value.getFullYear(), value.getMonth(), value.getDate(), value.getHours(), value.getMinutes(), value.getSeconds(), value.getMilliseconds()));
|
|
11818
|
+
return new Date(/[zZ]|[+-]\d{2}:?\d{2}$/.test(value) ? value : `${value.replace(" ", "T")}Z`);
|
|
11819
|
+
}
|
|
11720
11820
|
function dedupeMessagesForSave(messages) {
|
|
11721
11821
|
const deduped = /* @__PURE__ */ new Map();
|
|
11722
11822
|
for (const message of messages) {
|
|
@@ -11831,6 +11931,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11831
11931
|
schemaName: getSchemaName$3(this.#schema)
|
|
11832
11932
|
});
|
|
11833
11933
|
await this.#db.createIndexFromStatement("idx_om_lookup_key", `CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON ${omTableName} ("lookupKey")`);
|
|
11934
|
+
await this.#backfillSupersededBy(omTableName);
|
|
11834
11935
|
}
|
|
11835
11936
|
await this.#db.createTable({
|
|
11836
11937
|
tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
@@ -13428,6 +13529,115 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13428
13529
|
async #getLatestOMRow(client, tableName, lookupKey) {
|
|
13429
13530
|
return client.oneOrNone(`SELECT * FROM ${tableName} WHERE "lookupKey" = $1 ORDER BY ${OM_GENERATION_ORDER} LIMIT 1`, [lookupKey]);
|
|
13430
13531
|
}
|
|
13532
|
+
#omTableName() {
|
|
13533
|
+
return getTableName$3({
|
|
13534
|
+
indexName: OM_TABLE,
|
|
13535
|
+
schemaName: getSchemaName$3(this.#schema)
|
|
13536
|
+
});
|
|
13537
|
+
}
|
|
13538
|
+
/** Row-locks one OM record by primary key for the rest of the transaction. */
|
|
13539
|
+
async #lockOMRow(t, tableName, id) {
|
|
13540
|
+
return t.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1 FOR UPDATE`, [id]);
|
|
13541
|
+
}
|
|
13542
|
+
/**
|
|
13543
|
+
* The live, row-locked record a lifecycle write aimed at `row` lands on: `row` itself while
|
|
13544
|
+
* live, otherwise the head of its lookup key (locked, then re-checked — a rollover may retire
|
|
13545
|
+
* it between the head read and the lock).
|
|
13546
|
+
*/
|
|
13547
|
+
async #resolveLiveOMRow(t, tableName, row) {
|
|
13548
|
+
let current = row;
|
|
13549
|
+
for (let hop = 0; current.supersededBy; hop++) {
|
|
13550
|
+
const head = hop < OM_MAX_HEAD_HOPS ? await this.#getLatestOMRow(t, tableName, current.lookupKey) : null;
|
|
13551
|
+
const locked = head && head.id !== current.id ? await this.#lockOMRow(t, tableName, head.id) : null;
|
|
13552
|
+
if (!locked) throw new _mastra_core_error.MastraError({
|
|
13553
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "RESOLVE_OBSERVATIONAL_MEMORY_HEAD", "FAILED"),
|
|
13554
|
+
text: `Observational memory record ${row.id} is superseded but no live head was found`,
|
|
13555
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
13556
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
13557
|
+
details: { id: row.id }
|
|
13558
|
+
});
|
|
13559
|
+
current = locked;
|
|
13560
|
+
}
|
|
13561
|
+
return current;
|
|
13562
|
+
}
|
|
13563
|
+
/**
|
|
13564
|
+
* Retire every live row that sorts after its key's canonical head, marking it superseded by
|
|
13565
|
+
* the head. Rows retired by older adapter versions (which never set `supersededBy`) become
|
|
13566
|
+
* frozen. One statement: the head's ordering key is part of the condition, and a row the
|
|
13567
|
+
* statement waits on (a head being retired by a concurrent rollover) is re-checked against
|
|
13568
|
+
* `"supersededBy" IS NULL` after that rollover commits.
|
|
13569
|
+
*/
|
|
13570
|
+
async #backfillSupersededBy(tableName) {
|
|
13571
|
+
await this.#db.client.none(`UPDATE ${tableName} AS r SET "supersededBy" = h.id
|
|
13572
|
+
FROM (
|
|
13573
|
+
SELECT DISTINCT ON ("lookupKey") "lookupKey", id, "generationCount", "createdAt"
|
|
13574
|
+
FROM ${tableName}
|
|
13575
|
+
WHERE "lookupKey" IN (
|
|
13576
|
+
SELECT "lookupKey" FROM ${tableName} WHERE "supersededBy" IS NULL GROUP BY "lookupKey" HAVING COUNT(*) > 1
|
|
13577
|
+
)
|
|
13578
|
+
ORDER BY "lookupKey", ${OM_GENERATION_ORDER}
|
|
13579
|
+
) AS h
|
|
13580
|
+
WHERE r."lookupKey" = h."lookupKey"
|
|
13581
|
+
AND r."supersededBy" IS NULL
|
|
13582
|
+
AND (
|
|
13583
|
+
r."generationCount" < h."generationCount"
|
|
13584
|
+
OR (r."generationCount" = h."generationCount" AND r."createdAt" > h."createdAt")
|
|
13585
|
+
OR (r."generationCount" = h."generationCount" AND r."createdAt" = h."createdAt" AND r.id > h.id)
|
|
13586
|
+
)`);
|
|
13587
|
+
}
|
|
13588
|
+
/**
|
|
13589
|
+
* Create the next generation from the stored (live, row-locked) record and retire the stored
|
|
13590
|
+
* record in the same transaction. Carried columns are copied in SQL from the stored row, so
|
|
13591
|
+
* nothing round-trips through a client-side timezone conversion. Buffered chunks move to the
|
|
13592
|
+
* new generation; the cursor, buffering markers, flags, and counters carry over; buffered
|
|
13593
|
+
* reflection state does not.
|
|
13594
|
+
*/
|
|
13595
|
+
async #rollOverOMRow(t, tableName, storedId, observations, tokenCount, newRecordId) {
|
|
13596
|
+
const id = newRecordId ?? crypto.randomUUID();
|
|
13597
|
+
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
13598
|
+
const inserted = await t.one(`INSERT INTO ${tableName} (
|
|
13599
|
+
id, "lookupKey", scope, "resourceId", "threadId",
|
|
13600
|
+
"activeObservations", "activeObservationsPendingUpdate",
|
|
13601
|
+
"originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
|
|
13602
|
+
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount", "bufferedObservationChunks",
|
|
13603
|
+
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
13604
|
+
"observedTimezone", metadata, "supersededBy", "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
13605
|
+
)
|
|
13606
|
+
SELECT
|
|
13607
|
+
$1, "lookupKey", scope, "resourceId", "threadId",
|
|
13608
|
+
$2, NULL,
|
|
13609
|
+
'reflection', config, "generationCount" + 1, "lastObservedAt", "lastObservedAtZ", $4, $5,
|
|
13610
|
+
"pendingMessageTokens", "totalTokensObserved", $3, "bufferedObservationChunks",
|
|
13611
|
+
false, false, "isBufferingObservation", false, "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
13612
|
+
"observedTimezone", metadata, NULL, $6, $7, $8, $9
|
|
13613
|
+
FROM ${tableName} WHERE id = $10
|
|
13614
|
+
RETURNING *`, [
|
|
13615
|
+
id,
|
|
13616
|
+
observations,
|
|
13617
|
+
Math.round(tokenCount),
|
|
13618
|
+
nowStr,
|
|
13619
|
+
nowStr,
|
|
13620
|
+
nowStr,
|
|
13621
|
+
nowStr,
|
|
13622
|
+
nowStr,
|
|
13623
|
+
nowStr,
|
|
13624
|
+
storedId
|
|
13625
|
+
]);
|
|
13626
|
+
if ((await t.query(`UPDATE ${tableName} SET "supersededBy" = $1, "bufferedObservationChunks" = NULL, "updatedAt" = $2, "updatedAtZ" = $3
|
|
13627
|
+
WHERE id = $4 AND "supersededBy" IS NULL`, [
|
|
13628
|
+
id,
|
|
13629
|
+
nowStr,
|
|
13630
|
+
nowStr,
|
|
13631
|
+
storedId
|
|
13632
|
+
])).rowCount !== 1) throw new _mastra_core_error.MastraError({
|
|
13633
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "CREATE_REFLECTION_GENERATION", "RETIRE_FAILED"),
|
|
13634
|
+
text: `Failed to retire observational memory record ${storedId}`,
|
|
13635
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
13636
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
13637
|
+
details: { id: storedId }
|
|
13638
|
+
});
|
|
13639
|
+
return this.parseOMRow(inserted);
|
|
13640
|
+
}
|
|
13431
13641
|
parseOMRow(row) {
|
|
13432
13642
|
return {
|
|
13433
13643
|
id: row.id,
|
|
@@ -13456,11 +13666,12 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13456
13666
|
isBufferingObservation: row.isBufferingObservation === true || row.isBufferingObservation === "true",
|
|
13457
13667
|
isBufferingReflection: row.isBufferingReflection === true || row.isBufferingReflection === "true",
|
|
13458
13668
|
lastBufferedAtTokens: typeof row.lastBufferedAtTokens === "number" ? row.lastBufferedAtTokens : parseInt(String(row.lastBufferedAtTokens ?? "0"), 10) || 0,
|
|
13459
|
-
lastBufferedAtTime: row.lastBufferedAtTime ?
|
|
13669
|
+
lastBufferedAtTime: row.lastBufferedAtTime ? utcFromTimestampWithoutTimeZone(row.lastBufferedAtTime) : null,
|
|
13460
13670
|
config: row.config ? typeof row.config === "string" ? JSON.parse(row.config) : row.config : {},
|
|
13461
13671
|
metadata: row.metadata ? typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata : void 0,
|
|
13462
13672
|
observedMessageIds: row.observedMessageIds ? typeof row.observedMessageIds === "string" ? JSON.parse(row.observedMessageIds) : row.observedMessageIds : void 0,
|
|
13463
|
-
observedTimezone: row.observedTimezone || void 0
|
|
13673
|
+
observedTimezone: row.observedTimezone || void 0,
|
|
13674
|
+
supersededBy: row.supersededBy ?? null
|
|
13464
13675
|
};
|
|
13465
13676
|
}
|
|
13466
13677
|
async getObservationalMemory(threadId, resourceId) {
|
|
@@ -13470,7 +13681,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13470
13681
|
indexName: OM_TABLE,
|
|
13471
13682
|
schemaName: getSchemaName$3(this.#schema)
|
|
13472
13683
|
});
|
|
13473
|
-
const result = await this.#getLatestOMRow(this.#db.
|
|
13684
|
+
const result = await this.#getLatestOMRow(this.#db.client, tableName, lookupKey);
|
|
13474
13685
|
if (!result) return null;
|
|
13475
13686
|
return this.parseOMRow(result);
|
|
13476
13687
|
} catch (error) {
|
|
@@ -13553,9 +13764,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13553
13764
|
}
|
|
13554
13765
|
async initializeObservationalMemory(input) {
|
|
13555
13766
|
try {
|
|
13767
|
+
const lookupKey = this.getOMKey(input.threadId, input.resourceId);
|
|
13556
13768
|
const id = crypto.randomUUID();
|
|
13557
13769
|
const now = /* @__PURE__ */ new Date();
|
|
13558
|
-
const lookupKey = this.getOMKey(input.threadId, input.resourceId);
|
|
13559
13770
|
const record = {
|
|
13560
13771
|
id,
|
|
13561
13772
|
scope: input.scope,
|
|
@@ -13577,7 +13788,8 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13577
13788
|
lastBufferedAtTokens: 0,
|
|
13578
13789
|
lastBufferedAtTime: null,
|
|
13579
13790
|
config: input.config,
|
|
13580
|
-
observedTimezone: input.observedTimezone
|
|
13791
|
+
observedTimezone: input.observedTimezone,
|
|
13792
|
+
supersededBy: null
|
|
13581
13793
|
};
|
|
13582
13794
|
const tableName = getTableName$3({
|
|
13583
13795
|
indexName: OM_TABLE,
|
|
@@ -13657,8 +13869,8 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13657
13869
|
"reflectedObservationLineCount",
|
|
13658
13870
|
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection",
|
|
13659
13871
|
"lastBufferedAtTokens", "lastBufferedAtTime",
|
|
13660
|
-
"observedTimezone", metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
13661
|
-
) 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, $30, $31, $32, $33, $34, $35)`, [
|
|
13872
|
+
"observedTimezone", metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ", "supersededBy"
|
|
13873
|
+
) 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, $30, $31, $32, $33, $34, $35, $36)`, [
|
|
13662
13874
|
record.id,
|
|
13663
13875
|
lookupKey,
|
|
13664
13876
|
record.scope,
|
|
@@ -13693,7 +13905,8 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13693
13905
|
record.createdAt.toISOString(),
|
|
13694
13906
|
record.createdAt.toISOString(),
|
|
13695
13907
|
record.updatedAt.toISOString(),
|
|
13696
|
-
record.updatedAt.toISOString()
|
|
13908
|
+
record.updatedAt.toISOString(),
|
|
13909
|
+
record.supersededBy ?? null
|
|
13697
13910
|
]);
|
|
13698
13911
|
} catch (error) {
|
|
13699
13912
|
throw new _mastra_core_error.MastraError({
|
|
@@ -13709,41 +13922,55 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13709
13922
|
}
|
|
13710
13923
|
}
|
|
13711
13924
|
async updateActiveObservations(input) {
|
|
13925
|
+
assertActiveObservationsApplied(await this.commitActiveObservations(input), input.id);
|
|
13926
|
+
}
|
|
13927
|
+
async commitActiveObservations(input) {
|
|
13712
13928
|
try {
|
|
13713
|
-
const
|
|
13714
|
-
const
|
|
13715
|
-
indexName: OM_TABLE,
|
|
13716
|
-
schemaName: getSchemaName$3(this.#schema)
|
|
13717
|
-
});
|
|
13718
|
-
const lastObservedAtStr = input.lastObservedAt.toISOString();
|
|
13719
|
-
const nowStr = now.toISOString();
|
|
13929
|
+
const tableName = this.#omTableName();
|
|
13930
|
+
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
13720
13931
|
const observedMessageIdsJson = input.observedMessageIds ? toPgJson(input.observedMessageIds) : null;
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
input.
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13932
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, void 0);
|
|
13933
|
+
return await this.#db.client.tx(async (t) => {
|
|
13934
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "commitActiveObservations");
|
|
13935
|
+
const row = await this.#lockOMRow(t, tableName, input.id);
|
|
13936
|
+
if (!row) throw new _mastra_core_error.MastraError({
|
|
13937
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_ACTIVE_OBSERVATIONS", "NOT_FOUND"),
|
|
13938
|
+
text: `Observational memory record not found: ${input.id}`,
|
|
13939
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
13940
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
13941
|
+
details: { id: input.id }
|
|
13942
|
+
});
|
|
13943
|
+
if (row.supersededBy) return {
|
|
13944
|
+
applied: false,
|
|
13945
|
+
reason: "retired"
|
|
13946
|
+
};
|
|
13947
|
+
if (input.expectedActiveObservations !== void 0 && input.expectedActiveObservations !== (row.activeObservations || "")) return {
|
|
13948
|
+
applied: false,
|
|
13949
|
+
reason: "conflict"
|
|
13950
|
+
};
|
|
13951
|
+
const lastObservedAtStr = maxObservationCursor(row.lastObservedAtZ, input.lastObservedAt).toISOString();
|
|
13952
|
+
await t.none(`UPDATE ${tableName} SET
|
|
13953
|
+
"activeObservations" = $1,
|
|
13954
|
+
"lastObservedAt" = $2,
|
|
13955
|
+
"lastObservedAtZ" = $3,
|
|
13956
|
+
"pendingMessageTokens" = 0,
|
|
13957
|
+
"observationTokenCount" = $4,
|
|
13958
|
+
"totalTokensObserved" = "totalTokensObserved" + $5,
|
|
13959
|
+
"observedMessageIds" = $6,
|
|
13960
|
+
"updatedAt" = $7,
|
|
13961
|
+
"updatedAtZ" = $8
|
|
13962
|
+
WHERE id = $9`, [
|
|
13963
|
+
input.observations,
|
|
13964
|
+
lastObservedAtStr,
|
|
13965
|
+
lastObservedAtStr,
|
|
13966
|
+
Math.round(input.tokenCount),
|
|
13967
|
+
Math.round(input.tokenCount),
|
|
13968
|
+
observedMessageIdsJson,
|
|
13969
|
+
nowStr,
|
|
13970
|
+
nowStr,
|
|
13971
|
+
input.id
|
|
13972
|
+
]);
|
|
13973
|
+
return { applied: true };
|
|
13747
13974
|
});
|
|
13748
13975
|
} catch (error) {
|
|
13749
13976
|
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
@@ -13757,18 +13984,27 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13757
13984
|
}
|
|
13758
13985
|
async createReflectionGeneration(input) {
|
|
13759
13986
|
try {
|
|
13760
|
-
const
|
|
13761
|
-
const
|
|
13762
|
-
|
|
13763
|
-
schemaName: getSchemaName$3(this.#schema)
|
|
13764
|
-
});
|
|
13987
|
+
const { currentRecord } = input;
|
|
13988
|
+
const lookupKey = this.getOMKey(currentRecord.threadId, currentRecord.resourceId);
|
|
13989
|
+
const tableName = this.#omTableName();
|
|
13765
13990
|
return await this.#withOMLookupKeyLock(tableName, lookupKey, async (t) => {
|
|
13766
|
-
const
|
|
13767
|
-
if (
|
|
13768
|
-
return this.#
|
|
13991
|
+
const row = await this.#lockOMRow(t, tableName, currentRecord.id);
|
|
13992
|
+
if (!row) return currentRecord;
|
|
13993
|
+
if (row.supersededBy) return this.parseOMRow(await this.#resolveLiveOMRow(t, tableName, row));
|
|
13994
|
+
const stored = this.parseOMRow(row);
|
|
13995
|
+
const plan = planReflectionGenerationText({
|
|
13996
|
+
storedObservations: stored.activeObservations,
|
|
13997
|
+
storedObservationTokenCount: stored.observationTokenCount,
|
|
13998
|
+
snapshotObservations: currentRecord.activeObservations,
|
|
13999
|
+
snapshotObservationTokenCount: currentRecord.observationTokenCount,
|
|
14000
|
+
reflection: input.reflection,
|
|
14001
|
+
tokenCount: input.tokenCount
|
|
14002
|
+
});
|
|
14003
|
+
if (!plan) return stored;
|
|
14004
|
+
return this.#rollOverOMRow(t, tableName, stored.id, plan.observations, plan.tokenCount, input.newRecordId);
|
|
13769
14005
|
}, "createReflectionGeneration");
|
|
13770
14006
|
} catch (error) {
|
|
13771
|
-
if (
|
|
14007
|
+
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
13772
14008
|
throw new _mastra_core_error.MastraError({
|
|
13773
14009
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "CREATE_REFLECTION_GENERATION", "FAILED"),
|
|
13774
14010
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -13777,84 +14013,6 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13777
14013
|
}, error);
|
|
13778
14014
|
}
|
|
13779
14015
|
}
|
|
13780
|
-
/**
|
|
13781
|
-
* Returns the active record when another writer already created a generation
|
|
13782
|
-
* after `generationCount`. Reflecting from the older generation again would
|
|
13783
|
-
* add a second record with the same generation.
|
|
13784
|
-
*/
|
|
13785
|
-
async #getNewerOMGeneration(t, tableName, lookupKey, generationCount) {
|
|
13786
|
-
const latest = await this.#getLatestOMRow(t, tableName, lookupKey);
|
|
13787
|
-
return latest && Number(latest.generationCount) > generationCount ? this.parseOMRow(latest) : null;
|
|
13788
|
-
}
|
|
13789
|
-
async #insertReflectionGeneration(t, tableName, lookupKey, input) {
|
|
13790
|
-
const id = crypto.randomUUID();
|
|
13791
|
-
const now = /* @__PURE__ */ new Date();
|
|
13792
|
-
const record = {
|
|
13793
|
-
id,
|
|
13794
|
-
scope: input.currentRecord.scope,
|
|
13795
|
-
threadId: input.currentRecord.threadId,
|
|
13796
|
-
resourceId: input.currentRecord.resourceId,
|
|
13797
|
-
createdAt: now,
|
|
13798
|
-
updatedAt: now,
|
|
13799
|
-
lastObservedAt: input.currentRecord.lastObservedAt,
|
|
13800
|
-
originType: "reflection",
|
|
13801
|
-
generationCount: input.currentRecord.generationCount + 1,
|
|
13802
|
-
activeObservations: input.reflection,
|
|
13803
|
-
totalTokensObserved: input.currentRecord.totalTokensObserved,
|
|
13804
|
-
observationTokenCount: input.tokenCount,
|
|
13805
|
-
pendingMessageTokens: 0,
|
|
13806
|
-
isReflecting: false,
|
|
13807
|
-
isObserving: false,
|
|
13808
|
-
isBufferingObservation: false,
|
|
13809
|
-
isBufferingReflection: false,
|
|
13810
|
-
lastBufferedAtTokens: 0,
|
|
13811
|
-
lastBufferedAtTime: null,
|
|
13812
|
-
config: input.currentRecord.config,
|
|
13813
|
-
metadata: input.currentRecord.metadata,
|
|
13814
|
-
observedTimezone: input.currentRecord.observedTimezone
|
|
13815
|
-
};
|
|
13816
|
-
const nowStr = now.toISOString();
|
|
13817
|
-
const lastObservedAtStr = record.lastObservedAt?.toISOString() || null;
|
|
13818
|
-
await t.none(`INSERT INTO ${tableName} (
|
|
13819
|
-
id, "lookupKey", scope, "resourceId", "threadId",
|
|
13820
|
-
"activeObservations", "activeObservationsPendingUpdate",
|
|
13821
|
-
"originType", config, "generationCount", "lastObservedAt", "lastObservedAtZ", "lastReflectionAt", "lastReflectionAtZ",
|
|
13822
|
-
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
|
|
13823
|
-
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
13824
|
-
"observedTimezone", metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
13825
|
-
) 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)`, [
|
|
13826
|
-
id,
|
|
13827
|
-
lookupKey,
|
|
13828
|
-
record.scope,
|
|
13829
|
-
record.resourceId,
|
|
13830
|
-
record.threadId || null,
|
|
13831
|
-
input.reflection,
|
|
13832
|
-
null,
|
|
13833
|
-
"reflection",
|
|
13834
|
-
toPgJson(record.config),
|
|
13835
|
-
input.currentRecord.generationCount + 1,
|
|
13836
|
-
lastObservedAtStr,
|
|
13837
|
-
lastObservedAtStr,
|
|
13838
|
-
nowStr,
|
|
13839
|
-
nowStr,
|
|
13840
|
-
record.pendingMessageTokens,
|
|
13841
|
-
Math.round(record.totalTokensObserved),
|
|
13842
|
-
Math.round(record.observationTokenCount),
|
|
13843
|
-
false,
|
|
13844
|
-
false,
|
|
13845
|
-
false,
|
|
13846
|
-
false,
|
|
13847
|
-
0,
|
|
13848
|
-
null,
|
|
13849
|
-
record.observedTimezone || null,
|
|
13850
|
-
record.metadata ? toPgJson(record.metadata) : null,
|
|
13851
|
-
nowStr,
|
|
13852
|
-
nowStr,
|
|
13853
|
-
nowStr,
|
|
13854
|
-
nowStr
|
|
13855
|
-
]);
|
|
13856
|
-
return record;
|
|
13857
|
-
}
|
|
13858
14016
|
async setReflectingFlag(id, isReflecting) {
|
|
13859
14017
|
try {
|
|
13860
14018
|
const tableName = getTableName$3({
|
|
@@ -13927,41 +14085,35 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13927
14085
|
}
|
|
13928
14086
|
async setBufferingObservationFlag(id, isBuffering, lastBufferedAtTokens) {
|
|
13929
14087
|
try {
|
|
13930
|
-
const tableName =
|
|
13931
|
-
indexName: OM_TABLE,
|
|
13932
|
-
schemaName: getSchemaName$3(this.#schema)
|
|
13933
|
-
});
|
|
14088
|
+
const tableName = this.#omTableName();
|
|
13934
14089
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
14090
|
+
await this.#db.client.tx(async (t) => {
|
|
14091
|
+
const row = await this.#lockOMRow(t, tableName, id);
|
|
14092
|
+
if (!row) throw new _mastra_core_error.MastraError({
|
|
14093
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SET_BUFFERING_OBSERVATION_FLAG", "NOT_FOUND"),
|
|
14094
|
+
text: `Observational memory record not found: ${id}`,
|
|
14095
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
14096
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
14097
|
+
details: {
|
|
14098
|
+
id,
|
|
14099
|
+
isBuffering,
|
|
14100
|
+
lastBufferedAtTokens: lastBufferedAtTokens ?? null
|
|
14101
|
+
}
|
|
14102
|
+
});
|
|
14103
|
+
const target = await this.#resolveLiveOMRow(t, tableName, row);
|
|
14104
|
+
if (lastBufferedAtTokens !== void 0) await t.none(`UPDATE ${tableName} SET "isBufferingObservation" = $1, "lastBufferedAtTokens" = $2, "updatedAt" = $3, "updatedAtZ" = $4 WHERE id = $5`, [
|
|
13940
14105
|
isBuffering,
|
|
13941
14106
|
Math.round(lastBufferedAtTokens),
|
|
13942
14107
|
nowStr,
|
|
13943
14108
|
nowStr,
|
|
13944
|
-
id
|
|
13945
|
-
];
|
|
13946
|
-
|
|
13947
|
-
query = `UPDATE ${tableName} SET "isBufferingObservation" = $1, "updatedAt" = $2, "updatedAtZ" = $3 WHERE id = $4`;
|
|
13948
|
-
values = [
|
|
14109
|
+
target.id
|
|
14110
|
+
]);
|
|
14111
|
+
else await t.none(`UPDATE ${tableName} SET "isBufferingObservation" = $1, "updatedAt" = $2, "updatedAtZ" = $3 WHERE id = $4`, [
|
|
13949
14112
|
isBuffering,
|
|
13950
14113
|
nowStr,
|
|
13951
14114
|
nowStr,
|
|
13952
|
-
id
|
|
13953
|
-
];
|
|
13954
|
-
}
|
|
13955
|
-
if ((await this.#db.client.query(query, values)).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
13956
|
-
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SET_BUFFERING_OBSERVATION_FLAG", "NOT_FOUND"),
|
|
13957
|
-
text: `Observational memory record not found: ${id}`,
|
|
13958
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
13959
|
-
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
13960
|
-
details: {
|
|
13961
|
-
id,
|
|
13962
|
-
isBuffering,
|
|
13963
|
-
lastBufferedAtTokens: lastBufferedAtTokens ?? null
|
|
13964
|
-
}
|
|
14115
|
+
target.id
|
|
14116
|
+
]);
|
|
13965
14117
|
});
|
|
13966
14118
|
} catch (error) {
|
|
13967
14119
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
@@ -14034,29 +14186,27 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
14034
14186
|
}
|
|
14035
14187
|
async setPendingMessageTokens(id, tokenCount) {
|
|
14036
14188
|
try {
|
|
14037
|
-
const tableName =
|
|
14038
|
-
indexName: OM_TABLE,
|
|
14039
|
-
schemaName: getSchemaName$3(this.#schema)
|
|
14040
|
-
});
|
|
14189
|
+
const tableName = this.#omTableName();
|
|
14041
14190
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
14054
|
-
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14191
|
+
await this.#db.client.tx(async (t) => {
|
|
14192
|
+
const row = await this.#lockOMRow(t, tableName, id);
|
|
14193
|
+
if (!row) throw new _mastra_core_error.MastraError({
|
|
14194
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SET_PENDING_MESSAGE_TOKENS", "NOT_FOUND"),
|
|
14195
|
+
text: `Observational memory record not found: ${id}`,
|
|
14196
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
14197
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
14198
|
+
details: {
|
|
14199
|
+
id,
|
|
14200
|
+
tokenCount
|
|
14201
|
+
}
|
|
14202
|
+
});
|
|
14203
|
+
const target = await this.#resolveLiveOMRow(t, tableName, row);
|
|
14204
|
+
await t.none(`UPDATE ${tableName} SET "pendingMessageTokens" = $1, "updatedAt" = $2, "updatedAtZ" = $3 WHERE id = $4`, [
|
|
14205
|
+
Math.round(tokenCount),
|
|
14206
|
+
nowStr,
|
|
14207
|
+
nowStr,
|
|
14208
|
+
target.id
|
|
14209
|
+
]);
|
|
14060
14210
|
});
|
|
14061
14211
|
} catch (error) {
|
|
14062
14212
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
@@ -14106,11 +14256,11 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
14106
14256
|
}
|
|
14107
14257
|
}
|
|
14108
14258
|
async updateBufferedObservations(input) {
|
|
14259
|
+
await this.appendBufferedObservations(input);
|
|
14260
|
+
}
|
|
14261
|
+
async appendBufferedObservations(input) {
|
|
14109
14262
|
try {
|
|
14110
|
-
const tableName =
|
|
14111
|
-
indexName: OM_TABLE,
|
|
14112
|
-
schemaName: getSchemaName$3(this.#schema)
|
|
14113
|
-
});
|
|
14263
|
+
const tableName = this.#omTableName();
|
|
14114
14264
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
14115
14265
|
const newChunk = {
|
|
14116
14266
|
id: `ombuf-${globalThis.crypto.randomUUID()}`,
|
|
@@ -14127,32 +14277,42 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
14127
14277
|
extractedValues: input.chunk.extractedValues,
|
|
14128
14278
|
extractionFailures: input.chunk.extractionFailures
|
|
14129
14279
|
};
|
|
14130
|
-
const
|
|
14131
|
-
|
|
14132
|
-
|
|
14133
|
-
|
|
14134
|
-
|
|
14135
|
-
|
|
14136
|
-
|
|
14137
|
-
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
lastBufferedAtTime
|
|
14147
|
-
|
|
14148
|
-
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14280
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, void 0);
|
|
14281
|
+
return await this.#db.client.tx(async (t) => {
|
|
14282
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "appendBufferedObservations");
|
|
14283
|
+
const row = await this.#lockOMRow(t, tableName, input.id);
|
|
14284
|
+
if (!row) throw new _mastra_core_error.MastraError({
|
|
14285
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
|
|
14286
|
+
text: `Observational memory record not found: ${input.id}`,
|
|
14287
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
14288
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
14289
|
+
details: { id: input.id }
|
|
14290
|
+
});
|
|
14291
|
+
const target = this.parseOMRow(await this.#resolveLiveOMRow(t, tableName, row));
|
|
14292
|
+
if ((Array.isArray(target.bufferedObservationChunks) ? target.bufferedObservationChunks : []).some((existing) => existing.cycleId === input.chunk.cycleId) || isBufferedChunkCoveredByCursor(input.chunk.lastObservedAt, target.lastObservedAt)) return {
|
|
14293
|
+
persisted: false,
|
|
14294
|
+
recordId: target.id
|
|
14295
|
+
};
|
|
14296
|
+
const lastBufferedAtTime = input.lastBufferedAtTime ? input.lastBufferedAtTime.toISOString() : null;
|
|
14297
|
+
await t.none(`UPDATE ${tableName} SET
|
|
14298
|
+
"bufferedObservationChunks" = CASE
|
|
14299
|
+
WHEN jsonb_typeof("bufferedObservationChunks") = 'array' THEN "bufferedObservationChunks" || $1::jsonb
|
|
14300
|
+
ELSE $1::jsonb
|
|
14301
|
+
END,
|
|
14302
|
+
"lastBufferedAtTime" = GREATEST("lastBufferedAtTime", $2::timestamp),
|
|
14303
|
+
"updatedAt" = $3,
|
|
14304
|
+
"updatedAtZ" = $4
|
|
14305
|
+
WHERE id = $5`, [
|
|
14306
|
+
toPgJson([newChunk]),
|
|
14307
|
+
lastBufferedAtTime,
|
|
14308
|
+
nowStr,
|
|
14309
|
+
nowStr,
|
|
14310
|
+
target.id
|
|
14311
|
+
]);
|
|
14312
|
+
return {
|
|
14313
|
+
persisted: true,
|
|
14314
|
+
recordId: target.id
|
|
14315
|
+
};
|
|
14156
14316
|
});
|
|
14157
14317
|
} catch (error) {
|
|
14158
14318
|
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
@@ -14171,73 +14331,86 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
14171
14331
|
schemaName: getSchemaName$3(this.#schema)
|
|
14172
14332
|
});
|
|
14173
14333
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
14174
|
-
const
|
|
14175
|
-
|
|
14176
|
-
|
|
14177
|
-
|
|
14178
|
-
|
|
14179
|
-
|
|
14180
|
-
|
|
14181
|
-
|
|
14182
|
-
|
|
14183
|
-
|
|
14184
|
-
|
|
14185
|
-
|
|
14186
|
-
|
|
14187
|
-
|
|
14188
|
-
|
|
14189
|
-
|
|
14190
|
-
|
|
14191
|
-
|
|
14192
|
-
|
|
14193
|
-
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14334
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, void 0);
|
|
14335
|
+
return await this.#db.client.tx(async (t) => {
|
|
14336
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "swapBufferedToActive");
|
|
14337
|
+
const record = await this.#lockOMRow(t, tableName, input.id);
|
|
14338
|
+
if (!record) throw new _mastra_core_error.MastraError({
|
|
14339
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SWAP_BUFFERED_TO_ACTIVE", "NOT_FOUND"),
|
|
14340
|
+
text: `Observational memory record not found: ${input.id}`,
|
|
14341
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
14342
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
14343
|
+
details: { id: input.id }
|
|
14344
|
+
});
|
|
14345
|
+
const emptyResult = {
|
|
14346
|
+
chunksActivated: 0,
|
|
14347
|
+
messageTokensActivated: 0,
|
|
14348
|
+
observationTokensActivated: 0,
|
|
14349
|
+
messagesActivated: 0,
|
|
14350
|
+
activatedCycleIds: [],
|
|
14351
|
+
activatedMessageIds: []
|
|
14352
|
+
};
|
|
14353
|
+
if (record.supersededBy) return {
|
|
14354
|
+
...emptyResult,
|
|
14355
|
+
retired: true
|
|
14356
|
+
};
|
|
14357
|
+
let persistedChunks = [];
|
|
14358
|
+
if (record.bufferedObservationChunks) try {
|
|
14359
|
+
const parsed = typeof record.bufferedObservationChunks === "string" ? JSON.parse(record.bufferedObservationChunks) : record.bufferedObservationChunks;
|
|
14360
|
+
persistedChunks = Array.isArray(parsed) ? parsed : [];
|
|
14361
|
+
} catch {
|
|
14362
|
+
persistedChunks = [];
|
|
14363
|
+
}
|
|
14364
|
+
const refreshedWeights = new Map((Array.isArray(input.bufferedChunks) ? input.bufferedChunks : []).map((c) => [c.id, c.messageTokens]));
|
|
14365
|
+
const chunks = persistedChunks.map((c) => refreshedWeights.has(c.id) ? {
|
|
14366
|
+
...c,
|
|
14367
|
+
messageTokens: refreshedWeights.get(c.id)
|
|
14368
|
+
} : c);
|
|
14369
|
+
if (chunks.length === 0) return emptyResult;
|
|
14370
|
+
const retentionFloor = input.messageTokensThreshold * (1 - input.activationRatio);
|
|
14371
|
+
const targetMessageTokens = Math.max(0, input.currentPendingTokens - retentionFloor);
|
|
14372
|
+
let cumulativeMessageTokens = 0;
|
|
14373
|
+
let chunksToActivate = 0;
|
|
14374
|
+
let bestOverBoundary = 0;
|
|
14375
|
+
let bestOverTokens = 0;
|
|
14376
|
+
let bestUnderBoundary = 0;
|
|
14377
|
+
let bestUnderTokens = 0;
|
|
14378
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
14379
|
+
cumulativeMessageTokens += chunks[i].messageTokens ?? 0;
|
|
14380
|
+
const boundary = i + 1;
|
|
14381
|
+
if (cumulativeMessageTokens >= targetMessageTokens) {
|
|
14382
|
+
if (bestOverBoundary === 0 || cumulativeMessageTokens < bestOverTokens) {
|
|
14383
|
+
bestOverBoundary = boundary;
|
|
14384
|
+
bestOverTokens = cumulativeMessageTokens;
|
|
14385
|
+
}
|
|
14386
|
+
} else if (cumulativeMessageTokens > bestUnderTokens) {
|
|
14387
|
+
bestUnderBoundary = boundary;
|
|
14388
|
+
bestUnderTokens = cumulativeMessageTokens;
|
|
14212
14389
|
}
|
|
14213
|
-
} else if (cumulativeMessageTokens > bestUnderTokens) {
|
|
14214
|
-
bestUnderBoundary = boundary;
|
|
14215
|
-
bestUnderTokens = cumulativeMessageTokens;
|
|
14216
14390
|
}
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
if ((await this.#fenced(void 0, "swapBufferedToActive", (q) => q.query(`UPDATE ${tableName} SET
|
|
14391
|
+
const maxOvershoot = retentionFloor * .95;
|
|
14392
|
+
const overshoot = bestOverTokens - targetMessageTokens;
|
|
14393
|
+
const remainingAfterOver = input.currentPendingTokens - bestOverTokens;
|
|
14394
|
+
const remainingAfterUnder = input.currentPendingTokens - bestUnderTokens;
|
|
14395
|
+
const minRemaining = Math.min(1e3, retentionFloor);
|
|
14396
|
+
if (input.forceMaxActivation && bestOverBoundary > 0 && remainingAfterOver >= minRemaining) chunksToActivate = bestOverBoundary;
|
|
14397
|
+
else if (bestOverBoundary > 0 && overshoot <= maxOvershoot && remainingAfterOver >= minRemaining) chunksToActivate = bestOverBoundary;
|
|
14398
|
+
else if (bestUnderBoundary > 0 && remainingAfterUnder >= minRemaining) chunksToActivate = bestUnderBoundary;
|
|
14399
|
+
else if (bestOverBoundary > 0) chunksToActivate = bestOverBoundary;
|
|
14400
|
+
else chunksToActivate = 1;
|
|
14401
|
+
const activatedChunks = chunks.slice(0, chunksToActivate);
|
|
14402
|
+
const remainingChunks = persistedChunks.slice(chunksToActivate);
|
|
14403
|
+
const activatedContent = activatedChunks.map((c) => c.observations).join("\n\n");
|
|
14404
|
+
const activatedTokens = Math.round(activatedChunks.reduce((sum, c) => sum + c.tokenCount, 0));
|
|
14405
|
+
const activatedMessageTokens = Math.round(activatedChunks.reduce((sum, c) => sum + (c.messageTokens ?? 0), 0));
|
|
14406
|
+
const activatedMessageCount = activatedChunks.reduce((sum, c) => sum + c.messageIds.length, 0);
|
|
14407
|
+
const activatedCycleIds = activatedChunks.map((c) => c.cycleId).filter((id) => !!id);
|
|
14408
|
+
const activatedMessageIds = activatedChunks.flatMap((c) => c.messageIds ?? []);
|
|
14409
|
+
const latestChunk = activatedChunks[activatedChunks.length - 1];
|
|
14410
|
+
const lastObservedAt = input.lastObservedAt ?? (latestChunk?.lastObservedAt ? new Date(latestChunk.lastObservedAt) : /* @__PURE__ */ new Date());
|
|
14411
|
+
const lastObservedAtStr = maxObservationCursor(record.lastObservedAtZ, lastObservedAt).toISOString();
|
|
14412
|
+
const boundary = `\n\n--- message boundary (${lastObservedAt.toISOString()}) ---\n\n`;
|
|
14413
|
+
if ((await t.query(`UPDATE ${tableName} SET
|
|
14241
14414
|
"activeObservations" = CASE
|
|
14242
14415
|
WHEN "activeObservations" IS NOT NULL AND "activeObservations" != ''
|
|
14243
14416
|
THEN "activeObservations" || $10 || $1
|
|
@@ -14251,45 +14424,40 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
14251
14424
|
"updatedAt" = $7,
|
|
14252
14425
|
"updatedAtZ" = $8
|
|
14253
14426
|
WHERE id = $9
|
|
14427
|
+
AND "supersededBy" IS NULL
|
|
14254
14428
|
AND "bufferedObservationChunks" IS NOT NULL
|
|
14255
14429
|
AND "bufferedObservationChunks"::text != '[]'`, [
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
messageCount: c.messageIds.length,
|
|
14288
|
-
observations: c.observations
|
|
14289
|
-
})),
|
|
14290
|
-
suggestedContinuation: latestChunkHints?.suggestedContinuation ?? void 0,
|
|
14291
|
-
currentTask: latestChunkHints?.currentTask ?? void 0
|
|
14292
|
-
};
|
|
14430
|
+
activatedContent,
|
|
14431
|
+
activatedTokens,
|
|
14432
|
+
activatedMessageTokens,
|
|
14433
|
+
remainingChunks.length > 0 ? toPgJson(remainingChunks) : null,
|
|
14434
|
+
lastObservedAtStr,
|
|
14435
|
+
lastObservedAtStr,
|
|
14436
|
+
nowStr,
|
|
14437
|
+
nowStr,
|
|
14438
|
+
input.id,
|
|
14439
|
+
boundary
|
|
14440
|
+
])).rowCount === 0) return emptyResult;
|
|
14441
|
+
const latestChunkHints = activatedChunks[activatedChunks.length - 1];
|
|
14442
|
+
return {
|
|
14443
|
+
chunksActivated: activatedChunks.length,
|
|
14444
|
+
messageTokensActivated: activatedMessageTokens,
|
|
14445
|
+
observationTokensActivated: activatedTokens,
|
|
14446
|
+
messagesActivated: activatedMessageCount,
|
|
14447
|
+
activatedCycleIds,
|
|
14448
|
+
activatedMessageIds,
|
|
14449
|
+
observations: activatedContent,
|
|
14450
|
+
perChunk: activatedChunks.map((c) => ({
|
|
14451
|
+
cycleId: c.cycleId ?? "",
|
|
14452
|
+
messageTokens: c.messageTokens ?? 0,
|
|
14453
|
+
observationTokens: c.tokenCount,
|
|
14454
|
+
messageCount: c.messageIds.length,
|
|
14455
|
+
observations: c.observations
|
|
14456
|
+
})),
|
|
14457
|
+
suggestedContinuation: latestChunkHints?.suggestedContinuation ?? void 0,
|
|
14458
|
+
currentTask: latestChunkHints?.currentTask ?? void 0
|
|
14459
|
+
};
|
|
14460
|
+
});
|
|
14293
14461
|
} catch (error) {
|
|
14294
14462
|
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
14295
14463
|
throw new _mastra_core_error.MastraError({
|
|
@@ -14345,50 +14513,40 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
14345
14513
|
}
|
|
14346
14514
|
async swapBufferedReflectionToActive(input) {
|
|
14347
14515
|
try {
|
|
14348
|
-
const
|
|
14349
|
-
|
|
14350
|
-
|
|
14351
|
-
});
|
|
14352
|
-
const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
|
|
14516
|
+
const { currentRecord } = input;
|
|
14517
|
+
const tableName = this.#omTableName();
|
|
14518
|
+
const lookupKey = this.getOMKey(currentRecord.threadId, currentRecord.resourceId);
|
|
14353
14519
|
return await this.#withOMLookupKeyLock(tableName, lookupKey, async (t) => {
|
|
14354
|
-
const
|
|
14355
|
-
if (
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
|
|
14359
|
-
text: `Observational memory record not found: ${input.currentRecord.id}`,
|
|
14360
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
14361
|
-
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
14362
|
-
details: { id: input.currentRecord.id }
|
|
14363
|
-
});
|
|
14364
|
-
const bufferedReflection = record.bufferedReflection || "";
|
|
14365
|
-
const reflectedLineCount = Number(record.reflectedObservationLineCount || 0);
|
|
14520
|
+
const row = await this.#lockOMRow(t, tableName, currentRecord.id);
|
|
14521
|
+
if (!row) return currentRecord;
|
|
14522
|
+
if (row.supersededBy) return this.parseOMRow(await this.#resolveLiveOMRow(t, tableName, row));
|
|
14523
|
+
const stored = this.parseOMRow(row);
|
|
14524
|
+
const bufferedReflection = stored.bufferedReflection || "";
|
|
14366
14525
|
if (!bufferedReflection) throw new _mastra_core_error.MastraError({
|
|
14367
14526
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NO_CONTENT"),
|
|
14368
14527
|
text: "No buffered reflection to swap",
|
|
14369
14528
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
14370
14529
|
category: _mastra_core_error.ErrorCategory.USER,
|
|
14371
|
-
details: { id:
|
|
14530
|
+
details: { id: currentRecord.id }
|
|
14372
14531
|
});
|
|
14373
|
-
|
|
14532
|
+
if (!isAppendOnlySince(stored.activeObservations, currentRecord.activeObservations)) return stored;
|
|
14533
|
+
const reflectedLineCount = stored.reflectedObservationLineCount ?? 0;
|
|
14534
|
+
const unreflectedContent = (stored.activeObservations || "").split("\n").slice(reflectedLineCount).join("\n").trim();
|
|
14374
14535
|
const newObservations = unreflectedContent ? `${bufferedReflection}\n\n${unreflectedContent}` : bufferedReflection;
|
|
14375
|
-
const
|
|
14376
|
-
|
|
14377
|
-
reflection: newObservations,
|
|
14378
|
-
tokenCount: input.tokenCount
|
|
14379
|
-
});
|
|
14536
|
+
const tokenCount = input.tokenCount + Math.max(0, (stored.observationTokenCount ?? 0) - (currentRecord.observationTokenCount ?? 0));
|
|
14537
|
+
const newRecord = await this.#rollOverOMRow(t, tableName, stored.id, newObservations, tokenCount, input.newRecordId);
|
|
14380
14538
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
14381
|
-
await t.
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
|
|
14385
|
-
|
|
14386
|
-
|
|
14387
|
-
|
|
14388
|
-
|
|
14539
|
+
await t.none(`UPDATE ${tableName} SET
|
|
14540
|
+
"bufferedReflection" = NULL,
|
|
14541
|
+
"bufferedReflectionTokens" = NULL,
|
|
14542
|
+
"bufferedReflectionInputTokens" = NULL,
|
|
14543
|
+
"reflectedObservationLineCount" = NULL,
|
|
14544
|
+
"updatedAt" = $1,
|
|
14545
|
+
"updatedAtZ" = $2
|
|
14546
|
+
WHERE id = $3`, [
|
|
14389
14547
|
nowStr,
|
|
14390
14548
|
nowStr,
|
|
14391
|
-
|
|
14549
|
+
stored.id
|
|
14392
14550
|
]);
|
|
14393
14551
|
return newRecord;
|
|
14394
14552
|
}, "swapBufferedReflectionToActive");
|