@mastra/pg 1.20.1-alpha.1 → 1.20.1-alpha.3
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 +36 -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 -0
- package/dist/index.cjs +66 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +66 -11
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/factory-storage.d.ts +22 -0
- package/dist/storage/factory-storage.d.ts.map +1 -1
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 1.20.1-alpha.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Stop a dropped Postgres connection from killing the process while a client is checked out. ([#21765](https://github.com/mastra-ai/mastra/pull/21765))
|
|
8
|
+
|
|
9
|
+
`PgFactoryStorage` attached an `error` listener to the pool, but pg only routes pool-level errors for _idle_ clients — it hands ownership of a client to the borrower for the duration of a checkout. A backend restart or network blip that landed on a client mid-transaction therefore reached an emitter with nothing listening, and Node escalated it to an uncaughtException that took the whole server down (`Connection terminated unexpectedly` at `pg/lib/client.js`), even though the idle siblings were logged and discarded cleanly.
|
|
10
|
+
|
|
11
|
+
Pools created by `PgFactoryStorage` now attach a listener once per physical connection as it is established, so a client stays covered while borrowed. While the client is idle the pool's own listener already reports the failure, so the extra listener stays quiet and a dropped connection is announced once, as the right thing. The pool still discards the failed connection and reconnects on the next checkout; the failure is now logged instead of fatal. Caller-supplied pools are left untouched, as before.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`6db7a5d`](https://github.com/mastra-ai/mastra/commit/6db7a5dd3dd2b6f7ef75dcd804fcffef5fa83963), [`0cdc5dc`](https://github.com/mastra-ai/mastra/commit/0cdc5dc69024957815da4f51acc4119eb4f447d7)]:
|
|
14
|
+
- @mastra/core@1.60.0-alpha.12
|
|
15
|
+
|
|
16
|
+
## 1.20.1-alpha.2
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Added a `durable` option to stored agents so agents created through the Agents API can run with durable execution — no code deployment required. ([#21715](https://github.com/mastra-ai/mastra/pull/21715))
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
await mastraClient.createStoredAgent({
|
|
24
|
+
id: 'helper',
|
|
25
|
+
name: 'Helper',
|
|
26
|
+
instructions: 'You are a helpful assistant.',
|
|
27
|
+
model: { provider: 'openai', name: 'gpt-5' },
|
|
28
|
+
durable: true,
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Pass `true` for defaults, or `{ maxSteps, cleanupTimeoutMs }` to tune the durable loop. Cache and pubsub are inherited from the server's Mastra instance, so configure distributed backends there for durability across replicas. Automatic recovery is still configured in code via `recovery.durableAgents`.
|
|
33
|
+
|
|
34
|
+
- Improved PgVector upsert performance when writing many vectors at once. Batches are now written with a small number of multi-row inserts instead of one insert per vector, which reduces database round trips and connection pool usage during RAG and memory ingestion. ([#21719](https://github.com/mastra-ai/mastra/pull/21719))
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [[`6223446`](https://github.com/mastra-ai/mastra/commit/6223446ddce6166e96e0ba5e00d628b615dee8ca), [`583e235`](https://github.com/mastra-ai/mastra/commit/583e23519c13af16c1746f9c49722d011216611b), [`a77f8d4`](https://github.com/mastra-ai/mastra/commit/a77f8d4740d2178a74c41e4bf678b4fcd8fa0bb2), [`40d358e`](https://github.com/mastra-ai/mastra/commit/40d358e29d55543803e64b49241122f598ffabc7), [`e80cd7e`](https://github.com/mastra-ai/mastra/commit/e80cd7e7683e7d732e1cc6784bcac1d2640d2ce3), [`20504b2`](https://github.com/mastra-ai/mastra/commit/20504b2ecebd0e077acda3d457ab57480a98ed3e)]:
|
|
37
|
+
- @mastra/core@1.60.0-alpha.11
|
|
38
|
+
|
|
3
39
|
## 1.20.1-alpha.1
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -145,4 +145,5 @@ export const agent = new Agent({
|
|
|
145
145
|
- [listThreads](https://mastra.ai/reference/memory/listThreads)
|
|
146
146
|
- [deleteMessages](https://mastra.ai/reference/memory/deleteMessages)
|
|
147
147
|
- [cloneThread](https://mastra.ai/reference/memory/cloneThread)
|
|
148
|
+
- [settled](https://mastra.ai/reference/memory/settled)
|
|
148
149
|
- [Clone Utility Methods](https://mastra.ai/reference/memory/clone-utilities)
|
package/dist/index.cjs
CHANGED
|
@@ -565,6 +565,7 @@ function buildFilterQuery(filter, minScore, topK) {
|
|
|
565
565
|
}
|
|
566
566
|
//#endregion
|
|
567
567
|
//#region src/vector/index.ts
|
|
568
|
+
const MAX_UPSERT_ROWS_PER_STATEMENT = Math.floor(65535 / 3);
|
|
568
569
|
var PgVector = class extends _mastra_core_vector.MastraVector {
|
|
569
570
|
pool;
|
|
570
571
|
describeIndexCache = /* @__PURE__ */ new Map();
|
|
@@ -957,23 +958,41 @@ var PgVector = class extends _mastra_core_vector.MastraVector {
|
|
|
957
958
|
const indexInfo = await this.getIndexInfo({ indexName });
|
|
958
959
|
const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType, indexInfo.dimension);
|
|
959
960
|
const ops = this.getVectorOps(indexInfo.vectorType, indexInfo.metric ?? "cosine");
|
|
960
|
-
for (let i = 0; i < vectors.length; i++) {
|
|
961
|
+
if (new Set(vectorIds).size !== vectorIds.length) for (let i = 0; i < vectors.length; i++) {
|
|
961
962
|
const vectorStr = ops.formatVector(vectors[i], indexInfo.dimension);
|
|
962
963
|
const query = `
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
`;
|
|
964
|
+
INSERT INTO ${tableName} (vector_id, embedding, metadata)
|
|
965
|
+
VALUES ($1, $2::${qualifiedVectorType}, $3::jsonb)
|
|
966
|
+
ON CONFLICT (vector_id)
|
|
967
|
+
DO UPDATE SET
|
|
968
|
+
embedding = $2::${qualifiedVectorType},
|
|
969
|
+
metadata = $3::jsonb
|
|
970
|
+
`;
|
|
971
971
|
await client.query(query, [
|
|
972
972
|
vectorIds[i],
|
|
973
973
|
vectorStr,
|
|
974
974
|
JSON.stringify(metadata?.[i] || {})
|
|
975
975
|
]);
|
|
976
976
|
}
|
|
977
|
+
else for (let start = 0; start < vectors.length; start += MAX_UPSERT_ROWS_PER_STATEMENT) {
|
|
978
|
+
const end = Math.min(start + MAX_UPSERT_ROWS_PER_STATEMENT, vectors.length);
|
|
979
|
+
const rows = [];
|
|
980
|
+
const values = [];
|
|
981
|
+
for (let i = start; i < end; i++) {
|
|
982
|
+
const base = values.length;
|
|
983
|
+
rows.push(`($${base + 1}, $${base + 2}::${qualifiedVectorType}, $${base + 3}::jsonb)`);
|
|
984
|
+
values.push(vectorIds[i], ops.formatVector(vectors[i], indexInfo.dimension), JSON.stringify(metadata?.[i] || {}));
|
|
985
|
+
}
|
|
986
|
+
const query = `
|
|
987
|
+
INSERT INTO ${tableName} (vector_id, embedding, metadata)
|
|
988
|
+
VALUES ${rows.join(", ")}
|
|
989
|
+
ON CONFLICT (vector_id)
|
|
990
|
+
DO UPDATE SET
|
|
991
|
+
embedding = EXCLUDED.embedding,
|
|
992
|
+
metadata = EXCLUDED.metadata
|
|
993
|
+
`;
|
|
994
|
+
await client.query(query, values);
|
|
995
|
+
}
|
|
977
996
|
await client.query("COMMIT");
|
|
978
997
|
this.logger?.debug(`Upserted ${vectors.length} vectors to ${indexName}`, {
|
|
979
998
|
indexName,
|
|
@@ -3803,6 +3822,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
3803
3822
|
"workspace",
|
|
3804
3823
|
"skills",
|
|
3805
3824
|
"skillsFormat",
|
|
3825
|
+
"durable",
|
|
3806
3826
|
"browser",
|
|
3807
3827
|
"toolProviders"
|
|
3808
3828
|
]
|
|
@@ -4282,10 +4302,10 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4282
4302
|
"defaultOptions", workflows, agents, "integrationTools", "toolProviders",
|
|
4283
4303
|
"inputProcessors", "outputProcessors", memory, scorers,
|
|
4284
4304
|
"mcpClients", "requestContextSchema", workspace, skills, "skillsFormat",
|
|
4285
|
-
browser,
|
|
4305
|
+
durable, browser,
|
|
4286
4306
|
"changedFields", "changeMessage",
|
|
4287
4307
|
"createdAt", "createdAtZ"
|
|
4288
|
-
) 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)`, [
|
|
4308
|
+
) 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)`, [
|
|
4289
4309
|
input.id,
|
|
4290
4310
|
input.agentId,
|
|
4291
4311
|
input.versionNumber,
|
|
@@ -4308,6 +4328,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4308
4328
|
input.workspace ? JSON.stringify(input.workspace) : null,
|
|
4309
4329
|
input.skills ? JSON.stringify(input.skills) : null,
|
|
4310
4330
|
input.skillsFormat ?? null,
|
|
4331
|
+
input.durable !== void 0 ? JSON.stringify(input.durable) : null,
|
|
4311
4332
|
input.browser ? JSON.stringify(input.browser) : null,
|
|
4312
4333
|
input.changedFields ? JSON.stringify(input.changedFields) : null,
|
|
4313
4334
|
input.changeMessage ?? null,
|
|
@@ -4536,6 +4557,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4536
4557
|
workspace: parseJsonResilient(row.workspace, "workspace"),
|
|
4537
4558
|
skills: parseJsonResilient(row.skills, "skills"),
|
|
4538
4559
|
skillsFormat: row.skillsFormat,
|
|
4560
|
+
durable: parseJsonResilient(row.durable, "durable"),
|
|
4539
4561
|
browser: parseJsonResilient(row.browser, "browser"),
|
|
4540
4562
|
changedFields: parseJsonResilient(row.changedFields, "changedFields"),
|
|
4541
4563
|
changeMessage: row.changeMessage,
|
|
@@ -20752,6 +20774,38 @@ var PgFactoryStorageOps = class {
|
|
|
20752
20774
|
* Supports serializable app-table transactions for cross-replica invariant
|
|
20753
20775
|
* enforcement and `authDatabase()` exposing the shared pool.
|
|
20754
20776
|
*/
|
|
20777
|
+
/**
|
|
20778
|
+
* A pool-level `error` listener only covers *idle* clients: pg hands ownership
|
|
20779
|
+
* of a client to the borrower for the duration of a checkout and takes its own
|
|
20780
|
+
* listener off. So a backend restart or network blip that lands on a client
|
|
20781
|
+
* mid-transaction reaches an emitter with no listener, and Node escalates that
|
|
20782
|
+
* to an uncaughtException that kills the process — the pool handler logs the
|
|
20783
|
+
* idle siblings and the borrowed one still brings everything down.
|
|
20784
|
+
*
|
|
20785
|
+
* Attach a listener once per physical connection instead. `connect` fires when
|
|
20786
|
+
* the pool establishes a client, so the client stays covered for its whole life
|
|
20787
|
+
* and there is nothing to remove on release.
|
|
20788
|
+
*
|
|
20789
|
+
* That listener outlives the checkout, so it also sees the failures the pool is
|
|
20790
|
+
* already reporting through its own idle listener. Follow `acquire`/`release`
|
|
20791
|
+
* to tell the two apart and stay quiet while the client is idle — otherwise one
|
|
20792
|
+
* dropped connection is announced twice, the second time as the wrong thing.
|
|
20793
|
+
*
|
|
20794
|
+
* The pool still discards the failed connection; this only keeps the failure
|
|
20795
|
+
* reportable instead of fatal.
|
|
20796
|
+
*/
|
|
20797
|
+
function guardCheckedOutClientErrors(pool, warn = console.warn) {
|
|
20798
|
+
const borrowed = /* @__PURE__ */ new WeakSet();
|
|
20799
|
+
pool.on("connect", (client) => {
|
|
20800
|
+
borrowed.add(client);
|
|
20801
|
+
client.on("error", (err) => {
|
|
20802
|
+
if (!borrowed.has(client)) return;
|
|
20803
|
+
warn(`PgFactoryStorage: client error while checked out (the pool discards this connection): ${err instanceof Error ? err.message : String(err)}`);
|
|
20804
|
+
});
|
|
20805
|
+
});
|
|
20806
|
+
pool.on("acquire", (client) => borrowed.add(client));
|
|
20807
|
+
pool.on("release", (_err, client) => borrowed.delete(client));
|
|
20808
|
+
}
|
|
20755
20809
|
var PgFactoryStorage = class extends _mastra_core_storage.FactoryStorage {
|
|
20756
20810
|
ops;
|
|
20757
20811
|
#pool;
|
|
@@ -20772,6 +20826,7 @@ var PgFactoryStorage = class extends _mastra_core_storage.FactoryStorage {
|
|
|
20772
20826
|
this.#pool.on("error", (err) => {
|
|
20773
20827
|
console.warn(`PgFactoryStorage: idle pool client error (pool discards the client and reconnects on next checkout): ${err instanceof Error ? err.message : String(err)}`);
|
|
20774
20828
|
});
|
|
20829
|
+
guardCheckedOutClientErrors(this.#pool);
|
|
20775
20830
|
}
|
|
20776
20831
|
this.ops = new PgFactoryStorageOps(this.#pool, this.#schemas);
|
|
20777
20832
|
}
|