@mastra/pg 1.26.0-alpha.3 → 1.26.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-memory-memory-class.md +1 -1
- package/dist/index.cjs +212 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +213 -57
- package/dist/index.js.map +1 -1
- package/dist/storage/db/constraint-utils.d.ts +11 -1
- package/dist/storage/db/constraint-utils.d.ts.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/polling.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/polling.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +32 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/docs/SKILL.md
CHANGED
|
@@ -51,7 +51,7 @@ export const agent = new Agent({
|
|
|
51
51
|
|
|
52
52
|
**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.
|
|
53
53
|
|
|
54
|
-
**options.generateTitle** (`boolean | { model
|
|
54
|
+
**options.generateTitle** (`boolean | { model?: DynamicArgument<MastraModelConfig>; instructions?: DynamicArgument<string>; minMessages?: number; emitEvent?: boolean }`): Controls automatic thread title generation from the conversation transcript. Accepts a boolean or an object with a custom model (any MastraModelConfig: a model instance, a "provider/model" ID, or an OpenAI-compatible config; defaults to the agent's own model), custom instructions, a minimum message count, and emitEvent. With emitEvent: true the run's stream waits for the title and emits it as a transient data-thread-title chunk before finish (durable and evented agents persist the title but don't emit the chunk yet).
|
|
55
55
|
|
|
56
56
|
## Returns
|
|
57
57
|
|
package/dist/index.cjs
CHANGED
|
@@ -2360,6 +2360,8 @@ var RoutingDbClient = class {
|
|
|
2360
2360
|
return this.active.tx(callback);
|
|
2361
2361
|
}
|
|
2362
2362
|
};
|
|
2363
|
+
/** Bytes reserved for the `_xxxxxxxx` collision suffix when hashWhenTruncated applies. */
|
|
2364
|
+
const TRUNCATION_HASH_SUFFIX_LENGTH = 9;
|
|
2363
2365
|
function truncateIdentifier(value, maxLength = 63) {
|
|
2364
2366
|
if (maxLength <= 0) return "";
|
|
2365
2367
|
if (Buffer.byteLength(value, "utf-8") <= maxLength) return value;
|
|
@@ -2380,9 +2382,25 @@ function truncateIdentifier(value, maxLength = 63) {
|
|
|
2380
2382
|
* in system catalogs (pg_constraint.conname, pg_indexes.indexname, etc.).
|
|
2381
2383
|
* Without this normalisation, runtime lookups that compare a mixed-case name
|
|
2382
2384
|
* against the catalog would silently fail.
|
|
2385
|
+
*
|
|
2386
|
+
* With `hashWhenTruncated`, a name that exceeds the limit is truncated further
|
|
2387
|
+
* to make room for `_` + 8 hex chars of the full name's sha256. Plain
|
|
2388
|
+
* truncation cuts the tail, so two names sharing a long `<schema>_<prefix>`
|
|
2389
|
+
* collapse to the same identifier and `CREATE INDEX IF NOT EXISTS` (which
|
|
2390
|
+
* matches by name only) silently skips the second one. The suffix is
|
|
2391
|
+
* deterministic, so creation, warm-init snapshot checks, and DDL export all
|
|
2392
|
+
* agree on the same name. Opt-in because renaming already-released constraint
|
|
2393
|
+
* names would orphan the existing objects in deployed catalogs.
|
|
2383
2394
|
*/
|
|
2384
|
-
function buildConstraintName({ baseName, schemaName, maxLength = 63 }) {
|
|
2385
|
-
|
|
2395
|
+
function buildConstraintName({ baseName, schemaName, maxLength = 63, hashWhenTruncated = false }) {
|
|
2396
|
+
const fullName = `${schemaName ? `${schemaName}_` : ""}${baseName}`.toLowerCase();
|
|
2397
|
+
if (hashWhenTruncated && Buffer.byteLength(fullName, "utf-8") > maxLength) {
|
|
2398
|
+
const suffixLength = Math.min(TRUNCATION_HASH_SUFFIX_LENGTH, maxLength);
|
|
2399
|
+
if (suffixLength < 2) return truncateIdentifier(fullName, maxLength);
|
|
2400
|
+
const hash = (0, crypto$1.createHash)("sha256").update(fullName).digest("hex").slice(0, suffixLength - 1);
|
|
2401
|
+
return `${truncateIdentifier(fullName, maxLength - suffixLength)}_${hash}`;
|
|
2402
|
+
}
|
|
2403
|
+
return truncateIdentifier(fullName, maxLength);
|
|
2386
2404
|
}
|
|
2387
2405
|
//#endregion
|
|
2388
2406
|
//#region src/storage/db/pg-errors.ts
|
|
@@ -6118,6 +6136,14 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
|
|
|
6118
6136
|
}
|
|
6119
6137
|
async listDatasets(args) {
|
|
6120
6138
|
try {
|
|
6139
|
+
const orderBy = (0, _mastra_core_storage.resolveListOrderBy)(args.orderBy, [
|
|
6140
|
+
"createdAt",
|
|
6141
|
+
"updatedAt",
|
|
6142
|
+
"name"
|
|
6143
|
+
], {
|
|
6144
|
+
field: "createdAt",
|
|
6145
|
+
direction: "DESC"
|
|
6146
|
+
});
|
|
6121
6147
|
const { page, perPage: perPageInput } = args.pagination;
|
|
6122
6148
|
const tableName = getTableName$5({
|
|
6123
6149
|
indexName: _mastra_core_storage.TABLE_DATASETS,
|
|
@@ -6173,7 +6199,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
|
|
|
6173
6199
|
const { offset, perPage: perPageForResponse } = (0, _mastra_core_storage.calculatePagination)(page, perPageInput, perPage);
|
|
6174
6200
|
const limitValue = perPageInput === false ? total : perPage;
|
|
6175
6201
|
return {
|
|
6176
|
-
datasets: (await this.#db.readClient.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "
|
|
6202
|
+
datasets: (await this.#db.readClient.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "${orderBy.field}" ${orderBy.direction}, "id" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [
|
|
6177
6203
|
...queryParams,
|
|
6178
6204
|
limitValue,
|
|
6179
6205
|
offset
|
|
@@ -6740,6 +6766,10 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
|
|
|
6740
6766
|
*/
|
|
6741
6767
|
async #listItems(client, args) {
|
|
6742
6768
|
try {
|
|
6769
|
+
const orderBy = (0, _mastra_core_storage.resolveListOrderBy)(args.orderBy, ["createdAt", "updatedAt"], {
|
|
6770
|
+
field: "createdAt",
|
|
6771
|
+
direction: "DESC"
|
|
6772
|
+
});
|
|
6743
6773
|
const { page, perPage: perPageInput } = args.pagination;
|
|
6744
6774
|
const tableName = getTableName$5({
|
|
6745
6775
|
indexName: _mastra_core_storage.TABLE_DATASET_ITEMS,
|
|
@@ -6790,7 +6820,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
|
|
|
6790
6820
|
const { offset, perPage: perPageForResponse } = (0, _mastra_core_storage.calculatePagination)(page, perPageInput, perPage);
|
|
6791
6821
|
const limitValue = perPageInput === false ? total : perPage;
|
|
6792
6822
|
return {
|
|
6793
|
-
items: (await client.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "
|
|
6823
|
+
items: (await client.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "${orderBy.field}" ${orderBy.direction}, "id" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [
|
|
6794
6824
|
...queryParams,
|
|
6795
6825
|
limitValue,
|
|
6796
6826
|
offset
|
|
@@ -7350,6 +7380,10 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7350
7380
|
}
|
|
7351
7381
|
async listExperiments(args) {
|
|
7352
7382
|
try {
|
|
7383
|
+
const orderBy = (0, _mastra_core_storage.resolveListOrderBy)(args.orderBy, ["createdAt", "status"], {
|
|
7384
|
+
field: "createdAt",
|
|
7385
|
+
direction: "DESC"
|
|
7386
|
+
});
|
|
7353
7387
|
const { page, perPage: perPageInput } = args.pagination;
|
|
7354
7388
|
const tableName = getTableName$5({
|
|
7355
7389
|
indexName: _mastra_core_storage.TABLE_EXPERIMENTS,
|
|
@@ -7421,7 +7455,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7421
7455
|
const { offset, perPage: perPageForResponse } = (0, _mastra_core_storage.calculatePagination)(page, perPageInput, perPage);
|
|
7422
7456
|
const limitValue = perPageInput === false ? total : perPage;
|
|
7423
7457
|
return {
|
|
7424
|
-
experiments: (await this.#db.readClient.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "
|
|
7458
|
+
experiments: (await this.#db.readClient.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "${orderBy.field}" ${orderBy.direction}, "id" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [
|
|
7425
7459
|
...queryParams,
|
|
7426
7460
|
limitValue,
|
|
7427
7461
|
offset
|
|
@@ -7693,6 +7727,10 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7693
7727
|
}
|
|
7694
7728
|
async listExperimentResults(args) {
|
|
7695
7729
|
try {
|
|
7730
|
+
const orderBy = (0, _mastra_core_storage.resolveListOrderBy)(args.orderBy, ["startedAt", "createdAt"], {
|
|
7731
|
+
field: "startedAt",
|
|
7732
|
+
direction: "ASC"
|
|
7733
|
+
});
|
|
7696
7734
|
const { page, perPage: perPageInput } = args.pagination;
|
|
7697
7735
|
const tableName = getTableName$5({
|
|
7698
7736
|
indexName: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
|
|
@@ -7740,7 +7778,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7740
7778
|
const { offset, perPage: perPageForResponse } = (0, _mastra_core_storage.calculatePagination)(page, perPageInput, perPage);
|
|
7741
7779
|
const limitValue = perPageInput === false ? total : perPage;
|
|
7742
7780
|
return {
|
|
7743
|
-
results: (await this.#db.readClient.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "
|
|
7781
|
+
results: (await this.#db.readClient.manyOrNone(`SELECT * FROM ${tableName} ${whereClause} ORDER BY "${orderBy.field}" ${orderBy.direction}, "id" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [
|
|
7744
7782
|
...queryParams,
|
|
7745
7783
|
limitValue,
|
|
7746
7784
|
offset
|
|
@@ -17279,7 +17317,7 @@ const TRACE_SELECT = `
|
|
|
17279
17317
|
r."name" AS "name",
|
|
17280
17318
|
r."entityId" AS "entityId",
|
|
17281
17319
|
r."parentSpanId" AS "parentSpanId",
|
|
17282
|
-
r."
|
|
17320
|
+
r."metadataRaw" AS "metadata",
|
|
17283
17321
|
r."input" AS "input",
|
|
17284
17322
|
r."threadId" AS "threadId",
|
|
17285
17323
|
r."resourceId" AS "resourceId",
|
|
@@ -17497,22 +17535,27 @@ function compileThreadPredicate(predicate, parameterOffset) {
|
|
|
17497
17535
|
values: compiled.values
|
|
17498
17536
|
};
|
|
17499
17537
|
}
|
|
17500
|
-
function compilePostgresTraceScope(schema, selection, relationCollections) {
|
|
17538
|
+
function compilePostgresTraceScope(schema, selection, relationCollections, deltaWindow) {
|
|
17501
17539
|
const spanTable = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
17502
17540
|
const scoreTable = qualifiedTable(schema, TABLE_SCORE_EVENTS);
|
|
17503
17541
|
const feedbackTable = qualifiedTable(schema, TABLE_FEEDBACK_EVENTS);
|
|
17504
17542
|
const values = [selection.timeRange.from, selection.timeRange.to];
|
|
17505
|
-
const
|
|
17506
|
-
SELECT *
|
|
17507
|
-
FROM ${spanTable} r
|
|
17508
|
-
WHERE ${[
|
|
17543
|
+
const rootConditions = [
|
|
17509
17544
|
`r."parentSpanId" IS NULL`,
|
|
17510
17545
|
latestRootPredicate$1(spanTable),
|
|
17511
17546
|
`NOT r."isPending"`,
|
|
17512
17547
|
`r."endedAt" IS NOT NULL`,
|
|
17513
17548
|
`r."startedAt" >= $1`,
|
|
17514
17549
|
`r."startedAt" < $2`
|
|
17515
|
-
]
|
|
17550
|
+
];
|
|
17551
|
+
if (deltaWindow) {
|
|
17552
|
+
values.push(deltaWindow.xactId, deltaWindow.cursorId, deltaWindow.safeHorizon);
|
|
17553
|
+
rootConditions.push(`(r."xactId", r."cursorId") > ($3::xid8, $4::bigint)`, `r."xactId" < $5::xid8`);
|
|
17554
|
+
}
|
|
17555
|
+
const ctes = [`root_scope AS MATERIALIZED (
|
|
17556
|
+
SELECT *
|
|
17557
|
+
FROM ${spanTable} r
|
|
17558
|
+
WHERE ${rootConditions.join("\n AND ")}
|
|
17516
17559
|
)`];
|
|
17517
17560
|
if (relationCollections.has("spans")) ctes.push(`current_spans AS MATERIALIZED (
|
|
17518
17561
|
SELECT
|
|
@@ -17581,8 +17624,18 @@ function compilePostgresTraceScope(schema, selection, relationCollections) {
|
|
|
17581
17624
|
values
|
|
17582
17625
|
};
|
|
17583
17626
|
}
|
|
17584
|
-
function compilePostgresTraceQuery(schema, plan, mode = "data") {
|
|
17585
|
-
const
|
|
17627
|
+
function compilePostgresTraceQuery(schema, plan, mode = "data", safeHorizon) {
|
|
17628
|
+
const relationCollections = collectRelationCollections(plan.where);
|
|
17629
|
+
let deltaWindow;
|
|
17630
|
+
if (plan.paginationMode === "delta") {
|
|
17631
|
+
const watermark = _mastra_core_storage.getTraceQueryDeltaWatermark(plan, "pg");
|
|
17632
|
+
if (watermark === void 0 || safeHorizon === void 0) throw new Error("Delta query requires a cursor and safe horizon");
|
|
17633
|
+
deltaWindow = {
|
|
17634
|
+
...decodeTraceDeltaWatermark(watermark),
|
|
17635
|
+
safeHorizon
|
|
17636
|
+
};
|
|
17637
|
+
}
|
|
17638
|
+
const { ctes, values } = compilePostgresTraceScope(schema, plan, relationCollections, deltaWindow);
|
|
17586
17639
|
let predicateSql = "TRUE";
|
|
17587
17640
|
if (plan.where) {
|
|
17588
17641
|
const predicate = compilePredicate(plan.where, values.length + 1);
|
|
@@ -17590,7 +17643,7 @@ function compilePostgresTraceQuery(schema, plan, mode = "data") {
|
|
|
17590
17643
|
values.push(...predicate.values);
|
|
17591
17644
|
}
|
|
17592
17645
|
ctes.push(`candidates AS (
|
|
17593
|
-
SELECT ${TRACE_SELECT}
|
|
17646
|
+
SELECT ${TRACE_SELECT}${plan.paginationMode === "delta" ? ", r.\"xactId\", r.\"cursorId\"" : ""}
|
|
17594
17647
|
FROM root_scope r
|
|
17595
17648
|
WHERE ${predicateSql}
|
|
17596
17649
|
)`);
|
|
@@ -17601,6 +17654,16 @@ SELECT COUNT(*)::text AS count
|
|
|
17601
17654
|
FROM candidates`,
|
|
17602
17655
|
values
|
|
17603
17656
|
};
|
|
17657
|
+
if (plan.paginationMode === "delta") {
|
|
17658
|
+
values.push(plan.limit + 1);
|
|
17659
|
+
return {
|
|
17660
|
+
text: `${candidates}
|
|
17661
|
+
SELECT * FROM candidates
|
|
17662
|
+
ORDER BY "xactId" ASC, "cursorId" ASC
|
|
17663
|
+
LIMIT $${values.length}`,
|
|
17664
|
+
values
|
|
17665
|
+
};
|
|
17666
|
+
}
|
|
17604
17667
|
if (plan.result === "groups") {
|
|
17605
17668
|
const pageCondition = plan.cursor ? `AND "threadId" > $${values.length + 1}` : "";
|
|
17606
17669
|
if (plan.cursor) values.push(plan.cursor.threadId);
|
|
@@ -17812,13 +17875,83 @@ async function getTraceQueryValues(client, schema, plan, timeoutMs) {
|
|
|
17812
17875
|
valuesTruncated: rows.length > plan.limit
|
|
17813
17876
|
});
|
|
17814
17877
|
}
|
|
17878
|
+
function decodeTraceDeltaWatermark(watermark) {
|
|
17879
|
+
try {
|
|
17880
|
+
return decodeDeltaCursor(watermark);
|
|
17881
|
+
} catch {
|
|
17882
|
+
throw new _mastra_core_storage.TraceQueryCursorError("TRACE_QUERY_CURSOR_MALFORMED");
|
|
17883
|
+
}
|
|
17884
|
+
}
|
|
17885
|
+
function emptyDeltaWatermark(horizon, watermark) {
|
|
17886
|
+
if (watermark !== void 0 && BigInt(decodeTraceDeltaWatermark(watermark).xactId) >= BigInt(horizon)) return watermark;
|
|
17887
|
+
return encodeDeltaCursor(horizon, 0);
|
|
17888
|
+
}
|
|
17889
|
+
async function setRemainingTimeout(transaction, deadline) {
|
|
17890
|
+
const remainingTimeoutMs = Math.floor(deadline - performance.now());
|
|
17891
|
+
if (remainingTimeoutMs <= 0) throw new _mastra_core_storage.TraceQueryExecutionError();
|
|
17892
|
+
await transaction.query(`SELECT set_config('statement_timeout', $1, true)`, [`${remainingTimeoutMs}ms`]);
|
|
17893
|
+
}
|
|
17894
|
+
function traceRowToResult(row) {
|
|
17895
|
+
return {
|
|
17896
|
+
traceId: String(row.traceId),
|
|
17897
|
+
rootSpanId: String(row.rootSpanId),
|
|
17898
|
+
name: row.name,
|
|
17899
|
+
entityId: row.entityId ?? null,
|
|
17900
|
+
parentSpanId: row.parentSpanId ?? null,
|
|
17901
|
+
createdAt: asIsoTimestamp$1(row.startedAt),
|
|
17902
|
+
metadata: row.metadata ?? null,
|
|
17903
|
+
inputPreview: _mastra_core_storage.buildInputPreview(row.input) ?? null,
|
|
17904
|
+
threadId: row.threadId == null ? null : String(row.threadId),
|
|
17905
|
+
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
17906
|
+
startedAt: asIsoTimestamp$1(row.startedAt),
|
|
17907
|
+
endedAt: asIsoTimestamp$1(row.endedAt),
|
|
17908
|
+
entityName: row.entityName == null ? null : String(row.entityName),
|
|
17909
|
+
entityType: row.entityType == null ? null : String(row.entityType),
|
|
17910
|
+
environment: row.environment == null ? null : String(row.environment),
|
|
17911
|
+
status: row.status
|
|
17912
|
+
};
|
|
17913
|
+
}
|
|
17815
17914
|
async function queryTraces(client, schema, plan, timeoutMs) {
|
|
17915
|
+
if (plan.paginationMode === "delta") {
|
|
17916
|
+
assertDeltaPollingEnabled();
|
|
17917
|
+
const watermark = _mastra_core_storage.getTraceQueryDeltaWatermark(plan, "pg");
|
|
17918
|
+
if (watermark !== void 0) decodeTraceDeltaWatermark(watermark);
|
|
17919
|
+
const resolvedTimeoutMs = _mastra_core_storage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
17920
|
+
const deadline = performance.now() + resolvedTimeoutMs;
|
|
17921
|
+
return runWithPostgresTraceQueryTimeout(client, resolvedTimeoutMs, async (transaction) => {
|
|
17922
|
+
await setRemainingTimeout(transaction, deadline);
|
|
17923
|
+
const horizon = await readSafeXactHorizon(transaction);
|
|
17924
|
+
let rows = [];
|
|
17925
|
+
if (watermark !== void 0) {
|
|
17926
|
+
await setRemainingTimeout(transaction, deadline);
|
|
17927
|
+
const query = compilePostgresTraceQuery(schema, plan, "data", horizon);
|
|
17928
|
+
rows = await transaction.any(query.text, query.values);
|
|
17929
|
+
}
|
|
17930
|
+
const visible = rows.slice(0, plan.limit);
|
|
17931
|
+
const last = visible.at(-1);
|
|
17932
|
+
return _mastra_core_storage.traceQueryResponseSchema.parse({
|
|
17933
|
+
traces: visible.map(traceRowToResult),
|
|
17934
|
+
delta: {
|
|
17935
|
+
limit: plan.limit,
|
|
17936
|
+
hasMore: rows.length > plan.limit
|
|
17937
|
+
},
|
|
17938
|
+
deltaCursor: _mastra_core_storage.encodeTraceQueryDeltaCursor(plan, "pg", last ? encodeDeltaCursor(last.xactId, last.cursorId) : emptyDeltaWatermark(horizon, watermark))
|
|
17939
|
+
});
|
|
17940
|
+
}, { repeatableRead: true });
|
|
17941
|
+
}
|
|
17816
17942
|
if (plan.paginationMode === "page") {
|
|
17817
17943
|
const resolvedTimeoutMs = _mastra_core_storage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
17818
17944
|
const deadline = performance.now() + resolvedTimeoutMs;
|
|
17819
17945
|
const countQuery = compilePostgresTraceQuery(schema, plan, "count");
|
|
17820
17946
|
const dataQuery = compilePostgresTraceQuery(schema, plan);
|
|
17821
|
-
const { total, rows } = await runWithPostgresTraceQueryTimeout(client, resolvedTimeoutMs, async (transaction) => {
|
|
17947
|
+
const { total, rows, deltaCursor } = await runWithPostgresTraceQueryTimeout(client, resolvedTimeoutMs, async (transaction) => {
|
|
17948
|
+
let deltaCursor;
|
|
17949
|
+
if (deltaPollingFeatureEnabled() && typeof _mastra_core_storage.encodeTraceQueryDeltaCursor === "function") {
|
|
17950
|
+
await setRemainingTimeout(transaction, deadline);
|
|
17951
|
+
const horizon = await readSafeXactHorizon(transaction);
|
|
17952
|
+
deltaCursor = _mastra_core_storage.encodeTraceQueryDeltaCursor(plan, "pg", encodeDeltaCursor(horizon, 0));
|
|
17953
|
+
}
|
|
17954
|
+
if (deltaCursor !== void 0) await setRemainingTimeout(transaction, deadline);
|
|
17822
17955
|
const countRows = await transaction.any(countQuery.text, countQuery.values);
|
|
17823
17956
|
const remainingTimeoutMs = Math.floor(deadline - performance.now());
|
|
17824
17957
|
if (remainingTimeoutMs <= 0) throw new _mastra_core_storage.TraceQueryExecutionError();
|
|
@@ -17826,29 +17959,14 @@ async function queryTraces(client, schema, plan, timeoutMs) {
|
|
|
17826
17959
|
const rows = await transaction.any(dataQuery.text, dataQuery.values);
|
|
17827
17960
|
return {
|
|
17828
17961
|
total: Number(countRows[0]?.count ?? 0),
|
|
17829
|
-
rows
|
|
17962
|
+
rows,
|
|
17963
|
+
deltaCursor
|
|
17830
17964
|
};
|
|
17831
17965
|
}, { repeatableRead: true });
|
|
17832
|
-
const traces = rows.map(
|
|
17833
|
-
traceId: String(row.traceId),
|
|
17834
|
-
rootSpanId: String(row.rootSpanId),
|
|
17835
|
-
name: row.name,
|
|
17836
|
-
entityId: row.entityId ?? null,
|
|
17837
|
-
parentSpanId: row.parentSpanId ?? null,
|
|
17838
|
-
createdAt: asIsoTimestamp$1(row.startedAt),
|
|
17839
|
-
metadata: row.metadata ?? null,
|
|
17840
|
-
inputPreview: _mastra_core_storage.buildInputPreview(row.input) ?? null,
|
|
17841
|
-
threadId: row.threadId == null ? null : String(row.threadId),
|
|
17842
|
-
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
17843
|
-
startedAt: asIsoTimestamp$1(row.startedAt),
|
|
17844
|
-
endedAt: asIsoTimestamp$1(row.endedAt),
|
|
17845
|
-
entityName: row.entityName == null ? null : String(row.entityName),
|
|
17846
|
-
entityType: row.entityType == null ? null : String(row.entityType),
|
|
17847
|
-
environment: row.environment == null ? null : String(row.environment),
|
|
17848
|
-
status: row.status
|
|
17849
|
-
}));
|
|
17966
|
+
const traces = rows.map(traceRowToResult);
|
|
17850
17967
|
return _mastra_core_storage.traceQueryResponseSchema.parse({
|
|
17851
17968
|
traces,
|
|
17969
|
+
...deltaCursor === void 0 ? {} : { deltaCursor },
|
|
17852
17970
|
pagination: {
|
|
17853
17971
|
total,
|
|
17854
17972
|
page: plan.page,
|
|
@@ -17871,24 +17989,7 @@ async function queryTraces(client, schema, plan, timeoutMs) {
|
|
|
17871
17989
|
}) : null }
|
|
17872
17990
|
});
|
|
17873
17991
|
}
|
|
17874
|
-
const traces = visibleRows.map(
|
|
17875
|
-
traceId: String(row.traceId),
|
|
17876
|
-
rootSpanId: String(row.rootSpanId),
|
|
17877
|
-
name: row.name,
|
|
17878
|
-
entityId: row.entityId ?? null,
|
|
17879
|
-
parentSpanId: row.parentSpanId ?? null,
|
|
17880
|
-
createdAt: asIsoTimestamp$1(row.startedAt),
|
|
17881
|
-
metadata: row.metadata ?? null,
|
|
17882
|
-
inputPreview: _mastra_core_storage.buildInputPreview(row.input) ?? null,
|
|
17883
|
-
threadId: row.threadId == null ? null : String(row.threadId),
|
|
17884
|
-
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
17885
|
-
startedAt: asIsoTimestamp$1(row.startedAt),
|
|
17886
|
-
endedAt: asIsoTimestamp$1(row.endedAt),
|
|
17887
|
-
entityName: row.entityName == null ? null : String(row.entityName),
|
|
17888
|
-
entityType: row.entityType == null ? null : String(row.entityType),
|
|
17889
|
-
environment: row.environment == null ? null : String(row.environment),
|
|
17890
|
-
status: row.status
|
|
17891
|
-
}));
|
|
17992
|
+
const traces = visibleRows.map(traceRowToResult);
|
|
17892
17993
|
const last = traces.at(-1);
|
|
17893
17994
|
return _mastra_core_storage.traceQueryResponseSchema.parse({
|
|
17894
17995
|
traces,
|
|
@@ -18627,7 +18728,7 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
18627
18728
|
* Use it through `MastraCompositeStore` with a dedicated Postgres connection.
|
|
18628
18729
|
*/
|
|
18629
18730
|
function wrapError(op, error, details) {
|
|
18630
|
-
if (error instanceof _mastra_core_error.MastraError || error instanceof _mastra_core_storage.TraceQueryExecutionError || error instanceof _mastra_core_storage.TraceQueryResourceLimitError) throw error;
|
|
18731
|
+
if (error instanceof _mastra_core_error.MastraError || error instanceof _mastra_core_storage.TraceQueryCursorError || error instanceof _mastra_core_storage.TraceQueryExecutionError || error instanceof _mastra_core_storage.TraceQueryResourceLimitError) throw error;
|
|
18631
18732
|
throw new _mastra_core_error.MastraError({
|
|
18632
18733
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", op, "FAILED"),
|
|
18633
18734
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -22317,6 +22418,7 @@ const WORKFLOW_SNAPSHOT_STATUS_INDEX = "mastra_workflow_snapshot_name_status_cre
|
|
|
22317
22418
|
* Schema-prefixed name of the status index, lowercased and truncated the same way Postgres
|
|
22318
22419
|
* stores it, so the init snapshot's index set answers "does it exist?" without a probe or a
|
|
22319
22420
|
* no-op `CREATE INDEX` (schema-prefixed names routinely exceed the 63-byte limit).
|
|
22421
|
+
* Exported for tests.
|
|
22320
22422
|
*/
|
|
22321
22423
|
function workflowSnapshotStatusIndexName(schemaName) {
|
|
22322
22424
|
return buildConstraintName({
|
|
@@ -22334,6 +22436,48 @@ function workflowSnapshotStatusIndexSQL(indexName, schemaName) {
|
|
|
22334
22436
|
schemaName: getSchemaName(schemaName)
|
|
22335
22437
|
})} (workflow_name, (snapshot ->> 'status'), "createdAt" DESC)`;
|
|
22336
22438
|
}
|
|
22439
|
+
/** Base name (before any schema prefix) of the expression index backing the threadId filter. */
|
|
22440
|
+
const WORKFLOW_SNAPSHOT_THREAD_ID_INDEX = "mastra_workflow_snapshot_threadid_idx";
|
|
22441
|
+
/**
|
|
22442
|
+
* Schema-prefixed name of the threadId index (see workflowSnapshotStatusIndexName).
|
|
22443
|
+
*
|
|
22444
|
+
* Unlike the status index, truncation appends a collision hash: both index names share the
|
|
22445
|
+
* long `<schema>_mastra_workflow_snapshot_` prefix, so with a schema name of 37+ bytes plain
|
|
22446
|
+
* truncation collapses them to the same 63-byte identifier and `CREATE INDEX IF NOT EXISTS`
|
|
22447
|
+
* silently skips this index. The status index keeps plain truncation because its truncated
|
|
22448
|
+
* name already exists in deployed catalogs; this index is new and free to adopt the rule.
|
|
22449
|
+
* Exported for tests.
|
|
22450
|
+
*/
|
|
22451
|
+
function workflowSnapshotThreadIdIndexName(schemaName) {
|
|
22452
|
+
return buildConstraintName({
|
|
22453
|
+
baseName: WORKFLOW_SNAPSHOT_THREAD_ID_INDEX,
|
|
22454
|
+
schemaName: schemaName && schemaName !== "public" ? schemaName : void 0,
|
|
22455
|
+
hashWhenTruncated: true
|
|
22456
|
+
});
|
|
22457
|
+
}
|
|
22458
|
+
/**
|
|
22459
|
+
* Expression extracting the thread id embedded in a snapshot (jsonb columns only). Mirrors
|
|
22460
|
+
* the canonical extraction in `@mastra/core` (`getSnapshotMemoryInfo`), which reads one of
|
|
22461
|
+
* two layouts:
|
|
22462
|
+
* 1. agentic-loop: `context.<suspended step>.suspendPayload.__streamState.messageList.memoryInfo.threadId`
|
|
22463
|
+
* 2. durable loop: `context.input.messageListState.memoryInfo.threadId`
|
|
22464
|
+
*
|
|
22465
|
+
* `jsonb_path_query_first(jsonb, jsonpath)` is IMMUTABLE, so the expression is valid in an
|
|
22466
|
+
* expression index. The WHERE clause in listWorkflowRuns() must use this exact expression
|
|
22467
|
+
* text so the planner can match it against the index. If the snapshot layout changes in
|
|
22468
|
+
* core, this expression must be updated in lockstep or it will wrongly exclude rows.
|
|
22469
|
+
*/
|
|
22470
|
+
const WORKFLOW_SNAPSHOT_THREAD_ID_EXPR = `COALESCE(jsonb_path_query_first(snapshot, '$.context.* ? (@.status == "suspended").suspendPayload.__streamState.messageList.memoryInfo.threadId') #>> '{}', snapshot #>> '{context,input,messageListState,memoryInfo,threadId}')`;
|
|
22471
|
+
/**
|
|
22472
|
+
* Expression index on the snapshot-embedded thread id so listWorkflowRuns() threadId filters
|
|
22473
|
+
* (Agent.listSuspendedRuns) can use an index instead of detoasting every snapshot.
|
|
22474
|
+
*/
|
|
22475
|
+
function workflowSnapshotThreadIdIndexSQL(indexName, schemaName) {
|
|
22476
|
+
return `CREATE INDEX IF NOT EXISTS "${indexName}" ON ${getTableName({
|
|
22477
|
+
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
22478
|
+
schemaName: getSchemaName(schemaName)
|
|
22479
|
+
})} ((${WORKFLOW_SNAPSHOT_THREAD_ID_EXPR}))`;
|
|
22480
|
+
}
|
|
22337
22481
|
var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorage {
|
|
22338
22482
|
#db;
|
|
22339
22483
|
#schema;
|
|
@@ -22406,6 +22550,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
22406
22550
|
}));
|
|
22407
22551
|
for (const idx of WorkflowsPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
|
|
22408
22552
|
statements.push(`${workflowSnapshotStatusIndexSQL(workflowSnapshotStatusIndexName(parsedSchema), schemaName)};`);
|
|
22553
|
+
statements.push(`${workflowSnapshotThreadIdIndexSQL(workflowSnapshotThreadIdIndexName(parsedSchema), schemaName)};`);
|
|
22409
22554
|
return statements;
|
|
22410
22555
|
}
|
|
22411
22556
|
/**
|
|
@@ -22432,6 +22577,12 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
22432
22577
|
} catch (error) {
|
|
22433
22578
|
this.logger?.warn?.(`Failed to create index ${indexName}:`, error);
|
|
22434
22579
|
}
|
|
22580
|
+
const threadIdIndexName = workflowSnapshotThreadIdIndexName(this.#schema);
|
|
22581
|
+
try {
|
|
22582
|
+
await this.#db.createIndexFromStatement(threadIdIndexName, workflowSnapshotThreadIdIndexSQL(threadIdIndexName, this.#schema));
|
|
22583
|
+
} catch (error) {
|
|
22584
|
+
this.logger?.warn?.(`Failed to create index ${threadIdIndexName}:`, error);
|
|
22585
|
+
}
|
|
22435
22586
|
}
|
|
22436
22587
|
async init() {
|
|
22437
22588
|
await this.#db.createTable({
|
|
@@ -22712,7 +22863,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
22712
22863
|
}, error);
|
|
22713
22864
|
}
|
|
22714
22865
|
}
|
|
22715
|
-
async listWorkflowRuns({ workflowName, fromDate, toDate, perPage, page, resourceId, status } = {}) {
|
|
22866
|
+
async listWorkflowRuns({ workflowName, fromDate, toDate, perPage, page, resourceId, threadId, status } = {}) {
|
|
22716
22867
|
try {
|
|
22717
22868
|
const conditions = [];
|
|
22718
22869
|
const values = [];
|
|
@@ -22733,6 +22884,11 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
22733
22884
|
values.push(resourceId);
|
|
22734
22885
|
paramIndex++;
|
|
22735
22886
|
} else this.logger?.warn?.(`[${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
22887
|
+
if (threadId) if (await this.#db.getColumnType(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, "snapshot") === "jsonb") {
|
|
22888
|
+
conditions.push(`${WORKFLOW_SNAPSHOT_THREAD_ID_EXPR} = $${paramIndex}`);
|
|
22889
|
+
values.push(threadId);
|
|
22890
|
+
paramIndex++;
|
|
22891
|
+
} else this.logger?.warn?.(`[${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT}] snapshot column is not jsonb. Skipping threadId filter.`);
|
|
22736
22892
|
if (fromDate) {
|
|
22737
22893
|
conditions.push(`"createdAt" >= $${paramIndex}`);
|
|
22738
22894
|
values.push(fromDate);
|