@mastra/pg 1.17.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-memory-memory-class.md +1 -1
- package/dist/index.cjs +67 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +70 -54
- package/dist/index.js.map +1 -1
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/factory-storage.d.ts +5 -16
- package/dist/storage/factory-storage.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 1.17.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Improved Factory work-item concurrency by replacing distributed advisory locks with atomic claims, idempotent replay, and serializable relationship transactions. ([#20135](https://github.com/mastra-ai/mastra/pull/20135))
|
|
8
|
+
|
|
9
|
+
- Hardened distributed lock cleanup so clients are destroyed when transaction rollback fails. ([#20135](https://github.com/mastra-ai/mastra/pull/20135))
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`c8d8a01`](https://github.com/mastra-ai/mastra/commit/c8d8a010ee2efe2b7bf4d07707382c34c87b14e4), [`df6a9ce`](https://github.com/mastra-ai/mastra/commit/df6a9ce87214f7aadb2edfe62f67605fe998a0a4), [`73839cb`](https://github.com/mastra-ai/mastra/commit/73839cb58322679c170627d1015669ede5f619aa), [`371cf60`](https://github.com/mastra-ai/mastra/commit/371cf6075cef88ac6919a08d59a82e485397364a), [`8e4dc79`](https://github.com/mastra-ai/mastra/commit/8e4dc793dcf035ea506f9ce79f56d2d501a4be14), [`2db93cc`](https://github.com/mastra-ai/mastra/commit/2db93ccd0b872e4de7853a93383efe0647901df8), [`094ab61`](https://github.com/mastra-ai/mastra/commit/094ab6129a1a3ecf6eeb86decac17d5faea4e02a), [`fe80944`](https://github.com/mastra-ai/mastra/commit/fe80944f3ef6681fea6eae8200fce387b7bb3c2f), [`263d2ca`](https://github.com/mastra-ai/mastra/commit/263d2cac80ba3b03b9c0f008db6f1f1b9eb0278c), [`75f843d`](https://github.com/mastra-ai/mastra/commit/75f843d09f758223e6eeb321321bdcc5c7e779d0), [`e51e166`](https://github.com/mastra-ai/mastra/commit/e51e166c52e220abc9b64554ce37359dca8544b1)]:
|
|
12
|
+
- @mastra/core@1.53.0
|
|
13
|
+
|
|
14
|
+
## 1.17.1-alpha.0
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Improved Factory work-item concurrency by replacing distributed advisory locks with atomic claims, idempotent replay, and serializable relationship transactions. ([#20135](https://github.com/mastra-ai/mastra/pull/20135))
|
|
19
|
+
|
|
20
|
+
- Hardened distributed lock cleanup so clients are destroyed when transaction rollback fails. ([#20135](https://github.com/mastra-ai/mastra/pull/20135))
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`73839cb`](https://github.com/mastra-ai/mastra/commit/73839cb58322679c170627d1015669ede5f619aa), [`8e4dc79`](https://github.com/mastra-ai/mastra/commit/8e4dc793dcf035ea506f9ce79f56d2d501a4be14), [`2db93cc`](https://github.com/mastra-ai/mastra/commit/2db93ccd0b872e4de7853a93383efe0647901df8), [`094ab61`](https://github.com/mastra-ai/mastra/commit/094ab6129a1a3ecf6eeb86decac17d5faea4e02a), [`fe80944`](https://github.com/mastra-ai/mastra/commit/fe80944f3ef6681fea6eae8200fce387b7bb3c2f), [`e51e166`](https://github.com/mastra-ai/mastra/commit/e51e166c52e220abc9b64554ce37359dca8544b1)]:
|
|
23
|
+
- @mastra/core@1.53.0-alpha.4
|
|
24
|
+
|
|
3
25
|
## 1.17.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -47,7 +47,7 @@ export const agent = new Agent({
|
|
|
47
47
|
|
|
48
48
|
**options.observationalMemory** (`boolean | ObservationalMemoryOptions`): Enable Observational Memory for long-context agentic memory. Set to true for defaults, or pass a config object to customize token budgets, models, and scope. See Observational Memory reference for configuration details.
|
|
49
49
|
|
|
50
|
-
**options.generateTitle** (`boolean | { model: DynamicArgument<MastraLanguageModel>; instructions?: DynamicArgument<string> }`): Controls automatic thread title generation from the
|
|
50
|
+
**options.generateTitle** (`boolean | { model: DynamicArgument<MastraLanguageModel>; instructions?: DynamicArgument<string> }`): Controls automatic thread title generation from the conversation transcript. Can be a boolean or an object with custom model and instructions.
|
|
51
51
|
|
|
52
52
|
## Returns
|
|
53
53
|
|
package/dist/index.cjs
CHANGED
|
@@ -9598,6 +9598,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
|
|
|
9598
9598
|
}
|
|
9599
9599
|
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
9600
9600
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
9601
|
+
const metadataFilter = storage.validateStorageMetadataFilter(filter?.metadata);
|
|
9601
9602
|
try {
|
|
9602
9603
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
9603
9604
|
const orderByStatement = `ORDER BY COALESCE("${field}Z", "${field}") ${direction}`;
|
|
@@ -9639,13 +9640,27 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
|
|
|
9639
9640
|
hasMore: false
|
|
9640
9641
|
};
|
|
9641
9642
|
}
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9643
|
+
let total;
|
|
9644
|
+
let messages;
|
|
9645
|
+
if (metadataFilter) {
|
|
9646
|
+
const rows = await this.#db.client.manyOrNone(
|
|
9647
|
+
`${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement}`,
|
|
9648
|
+
queryParams
|
|
9649
|
+
);
|
|
9650
|
+
const filteredRows = (rows || []).filter(
|
|
9651
|
+
(row) => storage.storageMessageMatchesMetadataFilter(row.content, metadataFilter)
|
|
9652
|
+
);
|
|
9653
|
+
total = filteredRows.length;
|
|
9654
|
+
messages = perPageInput === false ? filteredRows : filteredRows.slice(offset, offset + perPage);
|
|
9655
|
+
} else {
|
|
9656
|
+
const countResult = await this.#db.client.one(`SELECT COUNT(*) FROM ${tableName} ${whereClause}`, queryParams);
|
|
9657
|
+
total = parseInt(countResult.count, 10);
|
|
9658
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
9659
|
+
const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
9660
|
+
const rows = await this.#db.client.manyOrNone(dataQuery, [...queryParams, limitValue, offset]);
|
|
9661
|
+
messages = [...rows || []];
|
|
9662
|
+
}
|
|
9663
|
+
const primaryPageCount = messages.length;
|
|
9649
9664
|
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
9650
9665
|
return {
|
|
9651
9666
|
messages: [],
|
|
@@ -9675,7 +9690,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
|
|
|
9675
9690
|
finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
|
|
9676
9691
|
);
|
|
9677
9692
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
9678
|
-
const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
9693
|
+
const hasMore = metadataFilter ? perPageInput !== false && offset + primaryPageCount < total : perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
9679
9694
|
return {
|
|
9680
9695
|
messages: finalMessages,
|
|
9681
9696
|
total,
|
|
@@ -9737,6 +9752,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
|
|
|
9737
9752
|
}
|
|
9738
9753
|
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
9739
9754
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
9755
|
+
const metadataFilter = storage.validateStorageMetadataFilter(filter?.metadata);
|
|
9740
9756
|
try {
|
|
9741
9757
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
9742
9758
|
const orderByStatement = `ORDER BY COALESCE("${field}Z", "${field}") ${direction}`;
|
|
@@ -9782,13 +9798,26 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
|
|
|
9782
9798
|
hasMore: false
|
|
9783
9799
|
};
|
|
9784
9800
|
}
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9801
|
+
let total;
|
|
9802
|
+
let messages;
|
|
9803
|
+
if (metadataFilter) {
|
|
9804
|
+
const rows = await this.#db.client.manyOrNone(
|
|
9805
|
+
`${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement}`,
|
|
9806
|
+
queryParams
|
|
9807
|
+
);
|
|
9808
|
+
const filteredRows = (rows || []).filter(
|
|
9809
|
+
(row) => storage.storageMessageMatchesMetadataFilter(row.content, metadataFilter)
|
|
9810
|
+
);
|
|
9811
|
+
total = filteredRows.length;
|
|
9812
|
+
messages = perPageInput === false ? filteredRows : filteredRows.slice(offset, offset + perPage);
|
|
9813
|
+
} else {
|
|
9814
|
+
const countResult = await this.#db.client.one(`SELECT COUNT(*) FROM ${tableName} ${whereClause}`, queryParams);
|
|
9815
|
+
total = parseInt(countResult.count, 10);
|
|
9816
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
9817
|
+
const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
9818
|
+
const rows = await this.#db.client.manyOrNone(dataQuery, [...queryParams, limitValue, offset]);
|
|
9819
|
+
messages = [...rows || []];
|
|
9820
|
+
}
|
|
9792
9821
|
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
9793
9822
|
return {
|
|
9794
9823
|
messages: [],
|
|
@@ -20250,10 +20279,6 @@ function serializeDefault(value) {
|
|
|
20250
20279
|
if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
|
|
20251
20280
|
return String(value);
|
|
20252
20281
|
}
|
|
20253
|
-
function hashAdvisoryLockKey(key) {
|
|
20254
|
-
const digest = crypto$1.createHash("sha256").update(key).digest();
|
|
20255
|
-
return [digest.readInt32BE(0), digest.readInt32BE(4)];
|
|
20256
|
-
}
|
|
20257
20282
|
var PgFactoryStorageOps = class {
|
|
20258
20283
|
#queryable;
|
|
20259
20284
|
#transactionClient;
|
|
@@ -20548,21 +20573,36 @@ var PgFactoryStorage = class extends storage.FactoryStorage {
|
|
|
20548
20573
|
async initStorage() {
|
|
20549
20574
|
await this.#pool.query("SELECT 1");
|
|
20550
20575
|
}
|
|
20551
|
-
async withTransaction(fn) {
|
|
20552
|
-
const
|
|
20553
|
-
|
|
20554
|
-
await
|
|
20576
|
+
async withTransaction(fn, options) {
|
|
20577
|
+
const maxAttempts = options?.isolationLevel === "serializable" ? 3 : 1;
|
|
20578
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
20579
|
+
const client = await this.#pool.connect();
|
|
20580
|
+
let transactionOpen = false;
|
|
20581
|
+
let releaseError;
|
|
20555
20582
|
try {
|
|
20583
|
+
await client.query(options?.isolationLevel === "serializable" ? "BEGIN ISOLATION LEVEL SERIALIZABLE" : "BEGIN");
|
|
20584
|
+
transactionOpen = true;
|
|
20556
20585
|
const result = await fn(new PgFactoryStorageOps(client, this.#schemas, client));
|
|
20557
20586
|
await client.query("COMMIT");
|
|
20587
|
+
transactionOpen = false;
|
|
20558
20588
|
return result;
|
|
20559
20589
|
} catch (error) {
|
|
20560
|
-
|
|
20561
|
-
|
|
20590
|
+
if (transactionOpen) {
|
|
20591
|
+
try {
|
|
20592
|
+
await client.query("ROLLBACK");
|
|
20593
|
+
transactionOpen = false;
|
|
20594
|
+
} catch (rollbackError) {
|
|
20595
|
+
releaseError = rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError));
|
|
20596
|
+
throw new AggregateError([error, rollbackError], "Factory transaction and rollback both failed");
|
|
20597
|
+
}
|
|
20598
|
+
}
|
|
20599
|
+
const serializationFailure = typeof error === "object" && error !== null && error.code === "40001";
|
|
20600
|
+
if (!serializationFailure || attempt === maxAttempts) throw error;
|
|
20601
|
+
} finally {
|
|
20602
|
+
client.release(releaseError);
|
|
20562
20603
|
}
|
|
20563
|
-
} finally {
|
|
20564
|
-
client.release();
|
|
20565
20604
|
}
|
|
20605
|
+
throw new Error("PgFactoryStorage: serializable transaction retry limit exceeded");
|
|
20566
20606
|
}
|
|
20567
20607
|
async ensureCollections(schemas) {
|
|
20568
20608
|
for (const schema of schemas) {
|
|
@@ -20580,30 +20620,6 @@ var PgFactoryStorage = class extends storage.FactoryStorage {
|
|
|
20580
20620
|
authDatabase() {
|
|
20581
20621
|
return { dialect: "postgres", pool: this.#pool };
|
|
20582
20622
|
}
|
|
20583
|
-
/**
|
|
20584
|
-
* Run `fn` while holding a Postgres transaction-scoped advisory lock for
|
|
20585
|
-
* `key`, serializing callers across replicas. The lock releases when the
|
|
20586
|
-
* transaction ends (commit, rollback, or connection loss), so a crashed
|
|
20587
|
-
* replica can never hold it forever.
|
|
20588
|
-
*/
|
|
20589
|
-
async withDistributedLock(key, fn) {
|
|
20590
|
-
const [k1, k2] = hashAdvisoryLockKey(key);
|
|
20591
|
-
const client = await this.#pool.connect();
|
|
20592
|
-
try {
|
|
20593
|
-
await client.query("BEGIN");
|
|
20594
|
-
await client.query("SELECT pg_advisory_xact_lock($1, $2)", [k1, k2]);
|
|
20595
|
-
try {
|
|
20596
|
-
const result = await fn();
|
|
20597
|
-
await client.query("COMMIT");
|
|
20598
|
-
return result;
|
|
20599
|
-
} catch (error) {
|
|
20600
|
-
await client.query("ROLLBACK");
|
|
20601
|
-
throw error;
|
|
20602
|
-
}
|
|
20603
|
-
} finally {
|
|
20604
|
-
client.release();
|
|
20605
|
-
}
|
|
20606
|
-
}
|
|
20607
20623
|
#columnDdl(name, spec) {
|
|
20608
20624
|
assertIdentifier("column", name);
|
|
20609
20625
|
let ddl = `"${name}" ${COLUMN_DDL[spec.type]}`;
|
|
@@ -21067,6 +21083,5 @@ exports.ToolProviderConnectionsPG = ToolProviderConnectionsPG;
|
|
|
21067
21083
|
exports.WorkflowsPG = WorkflowsPG;
|
|
21068
21084
|
exports.WorkspacesPG = WorkspacesPG;
|
|
21069
21085
|
exports.exportSchemas = exportSchemas;
|
|
21070
|
-
exports.hashAdvisoryLockKey = hashAdvisoryLockKey;
|
|
21071
21086
|
//# sourceMappingURL=index.cjs.map
|
|
21072
21087
|
//# sourceMappingURL=index.cjs.map
|