@mastra/pg 1.20.1-alpha.0 → 1.20.1-alpha.2
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 +32 -0
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-deployment-workers.md +4 -4
- package/dist/docs/references/docs-memory-working-memory.md +1 -1
- package/dist/docs/references/{docs-storage-overview.md → docs-storage.md} +1 -1
- package/dist/docs/references/integrations-databases-postgresql.md +1 -0
- package/dist/docs/references/reference-memory-memory-class.md +1 -0
- package/dist/index.cjs +129 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +129 -13
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +12 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/db/schema-snapshot.d.ts +2 -0
- package/dist/storage/db/schema-snapshot.d.ts.map +1 -1
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 1.20.1-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 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))
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
await mastraClient.createStoredAgent({
|
|
11
|
+
id: 'helper',
|
|
12
|
+
name: 'Helper',
|
|
13
|
+
instructions: 'You are a helpful assistant.',
|
|
14
|
+
model: { provider: 'openai', name: 'gpt-5' },
|
|
15
|
+
durable: true,
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
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`.
|
|
20
|
+
|
|
21
|
+
- 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))
|
|
22
|
+
|
|
23
|
+
- 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)]:
|
|
24
|
+
- @mastra/core@1.60.0-alpha.11
|
|
25
|
+
|
|
26
|
+
## 1.20.1-alpha.1
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Make `listWorkflowRuns` status filtering indexable on Postgres. The status predicate previously wrapped every snapshot in a `regexp_replace(snapshot::text, ...)::jsonb` sanitization step, which forced a sequential scan over the whole `mastra_workflow_snapshot` table. On `jsonb` snapshot columns Postgres already rejects the problematic Unicode escape sequences at insert time, so the sanitization was a no-op there and the query now uses a plain `snapshot->>'status'` comparison backed by a new default expression index on `(workflow_name, snapshot->>'status', "createdAt" DESC)`. Legacy tables whose snapshot column is still `json` or `text` keep the sanitizing path. ([#21684](https://github.com/mastra-ai/mastra/pull/21684))
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [[`4e7a421`](https://github.com/mastra-ai/mastra/commit/4e7a421dce8a48742f785d1e93ad2f43a572b282), [`242e324`](https://github.com/mastra-ai/mastra/commit/242e3241e73cbd5c9bb86a31ebb49ca0256488d4), [`217e967`](https://github.com/mastra-ai/mastra/commit/217e9672d8b3160eb729d8e9f0044949e88da239), [`d774e89`](https://github.com/mastra-ai/mastra/commit/d774e8930c781df8c9effe3763e6b501c099b6cc), [`9c27a53`](https://github.com/mastra-ai/mastra/commit/9c27a53cd9d3de4f3f025bc387d94ce371c33f95), [`dff25a1`](https://github.com/mastra-ai/mastra/commit/dff25a1103fa72ee082a9b6f805ebeb5ce400753), [`217e967`](https://github.com/mastra-ai/mastra/commit/217e9672d8b3160eb729d8e9f0044949e88da239), [`7f78585`](https://github.com/mastra-ai/mastra/commit/7f785857e401570e2ffb316911f126ed363aa537), [`f2a4afd`](https://github.com/mastra-ai/mastra/commit/f2a4afd7e37e809669001ed17724b341a5c1f45e), [`d438148`](https://github.com/mastra-ai/mastra/commit/d438148e222c1e2fb3c652725ce75680962ebec4), [`ba05fe0`](https://github.com/mastra-ai/mastra/commit/ba05fe0738f70cb686777546e968237d09269142), [`d26a8d4`](https://github.com/mastra-ai/mastra/commit/d26a8d4281f28414715b333c85bedaf70d0b2890), [`677cdc6`](https://github.com/mastra-ai/mastra/commit/677cdc6af564dec29a13464d12b7ab2a4efc22e9), [`a318490`](https://github.com/mastra-ai/mastra/commit/a318490e17da32f338d50929c770d901a9b3dd72), [`763e0c6`](https://github.com/mastra-ai/mastra/commit/763e0c61e04d76ad9a9efd301aa57525ca0cbea9), [`23e0be2`](https://github.com/mastra-ai/mastra/commit/23e0be261381e49534b4ff3101c60ee64a946cbf), [`7fc8806`](https://github.com/mastra-ai/mastra/commit/7fc880627d3cbf995d31ea0e8b807bf15417e651), [`0e02eac`](https://github.com/mastra-ai/mastra/commit/0e02eacdb2e30e1697a41910b41163742a181dc1), [`4df174c`](https://github.com/mastra-ai/mastra/commit/4df174c32bddf093a82f273070b8380aef7c9e90), [`f7c25b5`](https://github.com/mastra-ai/mastra/commit/f7c25b5106ddfb48e591f98df7a51e0f2dd01dba), [`dc09cc1`](https://github.com/mastra-ai/mastra/commit/dc09cc1083d861cde192c1cd235324dc75b8c731), [`36b4649`](https://github.com/mastra-ai/mastra/commit/36b4649045a3a380cbab8ceca866db4086223aff), [`377eb81`](https://github.com/mastra-ai/mastra/commit/377eb81ce43b964e3a6b541df172da74a8ff3716)]:
|
|
33
|
+
- @mastra/core@1.60.0-alpha.8
|
|
34
|
+
|
|
3
35
|
## 1.20.1-alpha.0
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-pg
|
|
|
3
3
|
description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/pg"
|
|
6
|
-
version: "1.20.1-alpha.
|
|
6
|
+
version: "1.20.1-alpha.2"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -19,7 +19,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
19
19
|
- [Workers](references/docs-deployment-workers.md) - Separate background processing from the API layer by running workflow execution, cron schedules, and background tasks in dedicated worker processes.
|
|
20
20
|
- [Semantic recall](references/docs-memory-semantic-recall.md) - Learn how to use semantic recall in Mastra to retrieve relevant messages from past conversations using vector search and embeddings.
|
|
21
21
|
- [Working memory](references/docs-memory-working-memory.md) - Learn how to configure working memory in Mastra to store persistent user data, preferences.
|
|
22
|
-
- [Storage](references/docs-storage
|
|
22
|
+
- [Storage](references/docs-storage.md) - Configure storage for Mastra to persist runtime state across agents, workflows, observability, evals, schedules, and memory.
|
|
23
23
|
|
|
24
24
|
### Integrations
|
|
25
25
|
|
|
@@ -339,7 +339,7 @@ MASTRA_STEP_EXECUTION_URL=http://api:4111/api
|
|
|
339
339
|
|
|
340
340
|
Without this variable, the orchestration worker attempts to execute steps in its own process, which doesn't have access to the full Mastra runtime in a split deployment.
|
|
341
341
|
|
|
342
|
-
The endpoint uses the server's normal auth pipeline. If the API has an auth provider, set `MASTRA_WORKER_AUTH_TOKEN` to a bearer token that provider accepts. Mastra forwards the value as an `Authorization: Bearer` credential. The configured auth provider validates the token. See [Worker authentication](https://mastra.ai/docs/
|
|
342
|
+
The endpoint uses the server's normal auth pipeline. If the API has an auth provider, set `MASTRA_WORKER_AUTH_TOKEN` to a bearer token that provider accepts. Mastra forwards the value as an `Authorization: Bearer` credential. The configured auth provider validates the token. See [Worker authentication](https://mastra.ai/docs/auth/workers) for server configuration and other credential formats.
|
|
343
343
|
|
|
344
344
|
### Scale workers
|
|
345
345
|
|
|
@@ -365,18 +365,18 @@ A distributed PubSub backend persists unacknowledged events, which lets orchestr
|
|
|
365
365
|
|
|
366
366
|
The scheduler calculates the next fire time from the current time after it restarts. It doesn't replay schedules that elapsed while it was unavailable.
|
|
367
367
|
|
|
368
|
-
If the API crashes while a step is executing, that work can be lost and the workflow run can remain in a `running` state. See [known limitations](#known-limitations) and [durable agent crash recovery](https://mastra.ai/docs/
|
|
368
|
+
If the API crashes while a step is executing, that work can be lost and the workflow run can remain in a `running` state. See [known limitations](#known-limitations) and [durable agent crash recovery](https://mastra.ai/docs/harness/durable-agents).
|
|
369
369
|
|
|
370
370
|
## Known limitations
|
|
371
371
|
|
|
372
372
|
- **No dead-letter queue**: Failed events are nacked and retried, but there's no DLQ for events that fail after all retries.
|
|
373
373
|
- **No built-in health endpoint**: Workers don't expose an HTTP health check. Use container-level liveness probes or process monitoring.
|
|
374
374
|
- **Scheduler is single-instance**: Running multiple scheduler processes causes duplicate schedule fires.
|
|
375
|
-
- **Runs stuck in "running" after API crash**: If the API process crashes while executing a workflow step, the run remains in `running` status with no automatic retry. For [durable agents](https://mastra.ai/docs/
|
|
375
|
+
- **Runs stuck in "running" after API crash**: If the API process crashes while executing a workflow step, the run remains in `running` status with no automatic retry. For [durable agents](https://mastra.ai/docs/harness/durable-agents), set `recovery.durableAgents` to `'auto'` in the Mastra config to automatically re-drive orphaned runs on server restart. See [Crash recovery](https://mastra.ai/docs/harness/durable-agents) for details.
|
|
376
376
|
|
|
377
377
|
## Related
|
|
378
378
|
|
|
379
|
-
- [Worker authentication](https://mastra.ai/docs/
|
|
379
|
+
- [Worker authentication](https://mastra.ai/docs/auth/workers): Secure worker-to-API communication
|
|
380
380
|
- [Workers reference](https://mastra.ai/reference/workers/overview): Details about worker environment variables and types, with a list of supported storage backends
|
|
381
381
|
- [CLI reference](https://mastra.ai/reference/cli/mastra): `mastra worker build` and `mastra worker start`
|
|
382
382
|
- [PubSub](https://mastra.ai/docs/server/pubsub): Event delivery backends
|
|
@@ -400,7 +400,7 @@ const response = await agent.generate('What do you know about me?', {
|
|
|
400
400
|
|
|
401
401
|
## Opt in to state signals (experimental)
|
|
402
402
|
|
|
403
|
-
By default, working memory reaches the model as part of the system message. You can opt into delivering it as a [state signal](https://mastra.ai/docs/
|
|
403
|
+
By default, working memory reaches the model as part of the system message. You can opt into delivering it as a [state signal](https://mastra.ai/docs/harness/signals) instead by setting `useStateSignals: true`:
|
|
404
404
|
|
|
405
405
|
```typescript
|
|
406
406
|
const memory = new Memory({
|
|
@@ -10,7 +10,7 @@ Storage powers:
|
|
|
10
10
|
- [Workflows](https://mastra.ai/docs/workflows/overview): Durable snapshots for suspended and resumed workflow runs.
|
|
11
11
|
- [Observability](https://mastra.ai/docs/observability/overview): Traces, spans, metrics, logs, and feedback.
|
|
12
12
|
- [Evals](https://mastra.ai/docs/evals/overview): Scores, datasets, experiments, and evaluation results.
|
|
13
|
-
- [Long-running agents](https://mastra.ai/docs/
|
|
13
|
+
- [Long-running agents](https://mastra.ai/docs/harness/durable-agents): Background tasks, schedules, goals, and thread state.
|
|
14
14
|
|
|
15
15
|
## When to configure storage
|
|
16
16
|
|
|
@@ -408,6 +408,7 @@ PostgreSQL storage creates composite indexes during initialization for common qu
|
|
|
408
408
|
- `mastra_ai_spans_scope_startedat_idx`: (scope, startedAt DESC)
|
|
409
409
|
- `mastra_scores_trace_id_span_id_created_at_idx`: (traceId, spanId, createdAt DESC)
|
|
410
410
|
- `mastra_workflow_snapshot_name_createdat_idx`: (workflow\_name, createdAt DESC)
|
|
411
|
+
- `mastra_workflow_snapshot_name_status_createdat_idx`: (workflow\_name, snapshot->>'status', createdAt DESC), created only when the `snapshot` column is `jsonb`
|
|
411
412
|
|
|
412
413
|
These indexes improve performance for filtered queries with sorting, including `dateRange` filters on message queries and Studio's workflow runs-list.
|
|
413
414
|
|
|
@@ -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,
|
|
@@ -2176,7 +2195,7 @@ async function loadSchemaSnapshot(client, schemaName) {
|
|
|
2176
2195
|
const schema = schemaName || "public";
|
|
2177
2196
|
const [tableRows, columnRows, indexRows] = await Promise.all([
|
|
2178
2197
|
client.manyOrNone(`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = $1`, [schema]),
|
|
2179
|
-
client.manyOrNone(`SELECT c.relname AS table_name, a.attname AS column_name
|
|
2198
|
+
client.manyOrNone(`SELECT c.relname AS table_name, a.attname AS column_name, format_type(a.atttypid, a.atttypmod) AS data_type
|
|
2180
2199
|
FROM pg_catalog.pg_class c
|
|
2181
2200
|
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
2182
2201
|
JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
|
|
@@ -2191,6 +2210,7 @@ async function loadSchemaSnapshot(client, schemaName) {
|
|
|
2191
2210
|
WHERE n.nspname = $1`, [schema])
|
|
2192
2211
|
]);
|
|
2193
2212
|
const columns = /* @__PURE__ */ new Map();
|
|
2213
|
+
const columnTypes = /* @__PURE__ */ new Map();
|
|
2194
2214
|
for (const row of columnRows) {
|
|
2195
2215
|
let set = columns.get(row.table_name);
|
|
2196
2216
|
if (!set) {
|
|
@@ -2198,6 +2218,12 @@ async function loadSchemaSnapshot(client, schemaName) {
|
|
|
2198
2218
|
columns.set(row.table_name, set);
|
|
2199
2219
|
}
|
|
2200
2220
|
set.add(row.column_name);
|
|
2221
|
+
let types = columnTypes.get(row.table_name);
|
|
2222
|
+
if (!types) {
|
|
2223
|
+
types = /* @__PURE__ */ new Map();
|
|
2224
|
+
columnTypes.set(row.table_name, types);
|
|
2225
|
+
}
|
|
2226
|
+
types.set(row.column_name, row.data_type);
|
|
2201
2227
|
}
|
|
2202
2228
|
const indexes = /* @__PURE__ */ new Set();
|
|
2203
2229
|
const replicaIdentityIndexes = /* @__PURE__ */ new Set();
|
|
@@ -2211,6 +2237,7 @@ async function loadSchemaSnapshot(client, schemaName) {
|
|
|
2211
2237
|
schemaName: schema,
|
|
2212
2238
|
tables: new Set(tableRows.map((r) => r.tablename)),
|
|
2213
2239
|
columns,
|
|
2240
|
+
columnTypes,
|
|
2214
2241
|
indexes,
|
|
2215
2242
|
replicaIdentityIndexes,
|
|
2216
2243
|
primaryKeyIndexes
|
|
@@ -2464,6 +2491,8 @@ var PgDB = class extends _mastra_core_base.MastraBase {
|
|
|
2464
2491
|
skipDefaultIndexes;
|
|
2465
2492
|
/** Cache of actual table columns: tableName -> Set<columnName> */
|
|
2466
2493
|
tableColumnsCache = /* @__PURE__ */ new Map();
|
|
2494
|
+
/** Cache of column Postgres data types: tableName -> columnName -> data_type */
|
|
2495
|
+
columnTypeCache = /* @__PURE__ */ new Map();
|
|
2467
2496
|
constructor(config) {
|
|
2468
2497
|
super({
|
|
2469
2498
|
component: "STORAGE",
|
|
@@ -2538,7 +2567,9 @@ var PgDB = class extends _mastra_core_base.MastraBase {
|
|
|
2538
2567
|
}
|
|
2539
2568
|
}
|
|
2540
2569
|
this.tableColumnsCache.delete(oldName);
|
|
2570
|
+
this.columnTypeCache.delete(oldName);
|
|
2541
2571
|
this.tableColumnsCache.delete(newName);
|
|
2572
|
+
this.columnTypeCache.delete(newName);
|
|
2542
2573
|
}
|
|
2543
2574
|
/**
|
|
2544
2575
|
* Records an out-of-band `DROP TABLE` in the init snapshot. See
|
|
@@ -2554,8 +2585,10 @@ var PgDB = class extends _mastra_core_base.MastraBase {
|
|
|
2554
2585
|
if (snapshot) {
|
|
2555
2586
|
snapshot.tables.delete(tableName);
|
|
2556
2587
|
snapshot.columns.delete(tableName);
|
|
2588
|
+
snapshot.columnTypes.delete(tableName);
|
|
2557
2589
|
}
|
|
2558
2590
|
this.tableColumnsCache.delete(tableName);
|
|
2591
|
+
this.columnTypeCache.delete(tableName);
|
|
2559
2592
|
}
|
|
2560
2593
|
/**
|
|
2561
2594
|
* Records an out-of-band `ALTER TABLE … ADD COLUMN` in the init snapshot.
|
|
@@ -2565,6 +2598,7 @@ var PgDB = class extends _mastra_core_base.MastraBase {
|
|
|
2565
2598
|
const snapshot = this.schemaSnapshot;
|
|
2566
2599
|
if (snapshot) this.snapshotColumns(snapshot, tableName).add(column);
|
|
2567
2600
|
this.tableColumnsCache.delete(tableName);
|
|
2601
|
+
this.columnTypeCache.delete(tableName);
|
|
2568
2602
|
}
|
|
2569
2603
|
/**
|
|
2570
2604
|
* Gets the set of column names that actually exist in the database table.
|
|
@@ -2607,6 +2641,50 @@ var PgDB = class extends _mastra_core_base.MastraBase {
|
|
|
2607
2641
|
]);
|
|
2608
2642
|
}
|
|
2609
2643
|
/**
|
|
2644
|
+
* Returns the Postgres data type of a column (e.g. `jsonb`, `json`, `text`),
|
|
2645
|
+
* or null when the table or column does not exist.
|
|
2646
|
+
*
|
|
2647
|
+
* Answered from the init snapshot when one is installed, so a warm `init()`
|
|
2648
|
+
* issues no catalog probe. Outside init, results are cached per instance and
|
|
2649
|
+
* the cache is invalidated alongside {@link tableColumnsCache} whenever DDL
|
|
2650
|
+
* changes a table.
|
|
2651
|
+
*/
|
|
2652
|
+
async getColumnType(table, column) {
|
|
2653
|
+
const snapshot = this.schemaSnapshot;
|
|
2654
|
+
if (snapshot) {
|
|
2655
|
+
const types = snapshot.columnTypes.get(table);
|
|
2656
|
+
const known = types?.get(column) ?? types?.get(column.toLowerCase());
|
|
2657
|
+
if (known) return known;
|
|
2658
|
+
if (types) return null;
|
|
2659
|
+
}
|
|
2660
|
+
const cached = this.columnTypeCache.get(table)?.get(column);
|
|
2661
|
+
if (cached !== void 0) return cached;
|
|
2662
|
+
const schema = this.schemaName || "public";
|
|
2663
|
+
const dataType = (await this.client.oneOrNone(`SELECT data_type FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND (column_name = $3 OR column_name = $4)`, [
|
|
2664
|
+
schema,
|
|
2665
|
+
table,
|
|
2666
|
+
column,
|
|
2667
|
+
column.toLowerCase()
|
|
2668
|
+
]))?.data_type ?? null;
|
|
2669
|
+
if (dataType) {
|
|
2670
|
+
if (snapshot) {
|
|
2671
|
+
let snapshotTypes = snapshot.columnTypes.get(table);
|
|
2672
|
+
if (!snapshotTypes) {
|
|
2673
|
+
snapshotTypes = /* @__PURE__ */ new Map();
|
|
2674
|
+
snapshot.columnTypes.set(table, snapshotTypes);
|
|
2675
|
+
}
|
|
2676
|
+
snapshotTypes.set(column, dataType);
|
|
2677
|
+
}
|
|
2678
|
+
let types = this.columnTypeCache.get(table);
|
|
2679
|
+
if (!types) {
|
|
2680
|
+
types = /* @__PURE__ */ new Map();
|
|
2681
|
+
this.columnTypeCache.set(table, types);
|
|
2682
|
+
}
|
|
2683
|
+
types.set(column, dataType);
|
|
2684
|
+
}
|
|
2685
|
+
return dataType;
|
|
2686
|
+
}
|
|
2687
|
+
/**
|
|
2610
2688
|
* Prepares values for insertion, handling JSONB columns by stringifying them
|
|
2611
2689
|
*/
|
|
2612
2690
|
prepareValuesForInsert(record, tableName) {
|
|
@@ -2805,6 +2883,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
2805
2883
|
}, error);
|
|
2806
2884
|
} finally {
|
|
2807
2885
|
this.tableColumnsCache.delete(tableName);
|
|
2886
|
+
this.columnTypeCache.delete(tableName);
|
|
2808
2887
|
}
|
|
2809
2888
|
}
|
|
2810
2889
|
async setupTimestampTriggers(tableName) {
|
|
@@ -3127,6 +3206,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
3127
3206
|
}, error);
|
|
3128
3207
|
} finally {
|
|
3129
3208
|
this.tableColumnsCache.delete(tableName);
|
|
3209
|
+
this.columnTypeCache.delete(tableName);
|
|
3130
3210
|
}
|
|
3131
3211
|
}
|
|
3132
3212
|
async load({ tableName, keys }) {
|
|
@@ -3190,6 +3270,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
3190
3270
|
}, error);
|
|
3191
3271
|
} finally {
|
|
3192
3272
|
this.tableColumnsCache.delete(tableName);
|
|
3273
|
+
this.columnTypeCache.delete(tableName);
|
|
3193
3274
|
}
|
|
3194
3275
|
}
|
|
3195
3276
|
async createIndex(options) {
|
|
@@ -3741,6 +3822,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
3741
3822
|
"workspace",
|
|
3742
3823
|
"skills",
|
|
3743
3824
|
"skillsFormat",
|
|
3825
|
+
"durable",
|
|
3744
3826
|
"browser",
|
|
3745
3827
|
"toolProviders"
|
|
3746
3828
|
]
|
|
@@ -4220,10 +4302,10 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4220
4302
|
"defaultOptions", workflows, agents, "integrationTools", "toolProviders",
|
|
4221
4303
|
"inputProcessors", "outputProcessors", memory, scorers,
|
|
4222
4304
|
"mcpClients", "requestContextSchema", workspace, skills, "skillsFormat",
|
|
4223
|
-
browser,
|
|
4305
|
+
durable, browser,
|
|
4224
4306
|
"changedFields", "changeMessage",
|
|
4225
4307
|
"createdAt", "createdAtZ"
|
|
4226
|
-
) 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)`, [
|
|
4227
4309
|
input.id,
|
|
4228
4310
|
input.agentId,
|
|
4229
4311
|
input.versionNumber,
|
|
@@ -4246,6 +4328,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4246
4328
|
input.workspace ? JSON.stringify(input.workspace) : null,
|
|
4247
4329
|
input.skills ? JSON.stringify(input.skills) : null,
|
|
4248
4330
|
input.skillsFormat ?? null,
|
|
4331
|
+
input.durable !== void 0 ? JSON.stringify(input.durable) : null,
|
|
4249
4332
|
input.browser ? JSON.stringify(input.browser) : null,
|
|
4250
4333
|
input.changedFields ? JSON.stringify(input.changedFields) : null,
|
|
4251
4334
|
input.changeMessage ?? null,
|
|
@@ -4474,6 +4557,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4474
4557
|
workspace: parseJsonResilient(row.workspace, "workspace"),
|
|
4475
4558
|
skills: parseJsonResilient(row.skills, "skills"),
|
|
4476
4559
|
skillsFormat: row.skillsFormat,
|
|
4560
|
+
durable: parseJsonResilient(row.durable, "durable"),
|
|
4477
4561
|
browser: parseJsonResilient(row.browser, "browser"),
|
|
4478
4562
|
changedFields: parseJsonResilient(row.changedFields, "changedFields"),
|
|
4479
4563
|
changeMessage: row.changeMessage,
|
|
@@ -19322,6 +19406,29 @@ function getTableName({ indexName, schemaName }) {
|
|
|
19322
19406
|
const quotedIndexName = `"${indexName}"`;
|
|
19323
19407
|
return schemaName ? `${schemaName}.${quotedIndexName}` : quotedIndexName;
|
|
19324
19408
|
}
|
|
19409
|
+
/** Base name (before any schema prefix) of the expression index backing the status filter. */
|
|
19410
|
+
const WORKFLOW_SNAPSHOT_STATUS_INDEX = "mastra_workflow_snapshot_name_status_createdat_idx";
|
|
19411
|
+
/**
|
|
19412
|
+
* Schema-prefixed name of the status index, lowercased and truncated the same way Postgres
|
|
19413
|
+
* stores it, so the init snapshot's index set answers "does it exist?" without a probe or a
|
|
19414
|
+
* no-op `CREATE INDEX` (schema-prefixed names routinely exceed the 63-byte limit).
|
|
19415
|
+
*/
|
|
19416
|
+
function workflowSnapshotStatusIndexName(schemaName) {
|
|
19417
|
+
return buildConstraintName({
|
|
19418
|
+
baseName: WORKFLOW_SNAPSHOT_STATUS_INDEX,
|
|
19419
|
+
schemaName: schemaName && schemaName !== "public" ? schemaName : void 0
|
|
19420
|
+
});
|
|
19421
|
+
}
|
|
19422
|
+
/**
|
|
19423
|
+
* Expression index on `(workflow_name, snapshot->>'status', "createdAt" DESC)` so
|
|
19424
|
+
* listWorkflowRuns() status filters can use an index instead of scanning every snapshot.
|
|
19425
|
+
*/
|
|
19426
|
+
function workflowSnapshotStatusIndexSQL(indexName, schemaName) {
|
|
19427
|
+
return `CREATE INDEX IF NOT EXISTS "${indexName}" ON ${getTableName({
|
|
19428
|
+
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
19429
|
+
schemaName: getSchemaName(schemaName)
|
|
19430
|
+
})} (workflow_name, (snapshot ->> 'status'), "createdAt" DESC)`;
|
|
19431
|
+
}
|
|
19325
19432
|
/**
|
|
19326
19433
|
* Sanitizes JSON string for PostgreSQL jsonb:
|
|
19327
19434
|
* - Removes problematic Unicode sequences:
|
|
@@ -19404,6 +19511,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
19404
19511
|
includeAllConstraints: true
|
|
19405
19512
|
}));
|
|
19406
19513
|
for (const idx of WorkflowsPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
|
|
19514
|
+
statements.push(`${workflowSnapshotStatusIndexSQL(workflowSnapshotStatusIndexName(parsedSchema), schemaName)};`);
|
|
19407
19515
|
return statements;
|
|
19408
19516
|
}
|
|
19409
19517
|
/**
|
|
@@ -19423,6 +19531,13 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
19423
19531
|
} catch (error) {
|
|
19424
19532
|
this.logger?.warn?.(`Failed to create index ${indexDef.name}:`, error);
|
|
19425
19533
|
}
|
|
19534
|
+
if (await this.#db.getColumnType(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, "snapshot") !== "jsonb") return;
|
|
19535
|
+
const indexName = workflowSnapshotStatusIndexName(this.#schema);
|
|
19536
|
+
try {
|
|
19537
|
+
await this.#db.createIndexFromStatement(indexName, workflowSnapshotStatusIndexSQL(indexName, this.#schema));
|
|
19538
|
+
} catch (error) {
|
|
19539
|
+
this.logger?.warn?.(`Failed to create index ${indexName}:`, error);
|
|
19540
|
+
}
|
|
19426
19541
|
}
|
|
19427
19542
|
async init() {
|
|
19428
19543
|
await this.#db.createTable({
|
|
@@ -19712,7 +19827,8 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
19712
19827
|
paramIndex++;
|
|
19713
19828
|
}
|
|
19714
19829
|
if (status) {
|
|
19715
|
-
|
|
19830
|
+
const statusExpr = await this.#db.getColumnType(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, "snapshot") === "jsonb" ? `snapshot ->> 'status'` : `regexp_replace(snapshot::text, '\\\\u(0000|[Dd][89A-Fa-f][0-9A-Fa-f]{2})', '', 'g')::jsonb ->> 'status'`;
|
|
19831
|
+
conditions.push(`${statusExpr} = $${paramIndex}`);
|
|
19716
19832
|
values.push(status);
|
|
19717
19833
|
paramIndex++;
|
|
19718
19834
|
}
|