@mastra/pg 1.26.0-alpha.3 → 1.26.0-alpha.4
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 +76 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +76 -3
- 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/workflows/index.d.ts +32 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2336,6 +2336,8 @@ var RoutingDbClient = class {
|
|
|
2336
2336
|
return this.active.tx(callback);
|
|
2337
2337
|
}
|
|
2338
2338
|
};
|
|
2339
|
+
/** Bytes reserved for the `_xxxxxxxx` collision suffix when hashWhenTruncated applies. */
|
|
2340
|
+
const TRUNCATION_HASH_SUFFIX_LENGTH = 9;
|
|
2339
2341
|
function truncateIdentifier(value, maxLength = 63) {
|
|
2340
2342
|
if (maxLength <= 0) return "";
|
|
2341
2343
|
if (Buffer.byteLength(value, "utf-8") <= maxLength) return value;
|
|
@@ -2356,9 +2358,25 @@ function truncateIdentifier(value, maxLength = 63) {
|
|
|
2356
2358
|
* in system catalogs (pg_constraint.conname, pg_indexes.indexname, etc.).
|
|
2357
2359
|
* Without this normalisation, runtime lookups that compare a mixed-case name
|
|
2358
2360
|
* against the catalog would silently fail.
|
|
2361
|
+
*
|
|
2362
|
+
* With `hashWhenTruncated`, a name that exceeds the limit is truncated further
|
|
2363
|
+
* to make room for `_` + 8 hex chars of the full name's sha256. Plain
|
|
2364
|
+
* truncation cuts the tail, so two names sharing a long `<schema>_<prefix>`
|
|
2365
|
+
* collapse to the same identifier and `CREATE INDEX IF NOT EXISTS` (which
|
|
2366
|
+
* matches by name only) silently skips the second one. The suffix is
|
|
2367
|
+
* deterministic, so creation, warm-init snapshot checks, and DDL export all
|
|
2368
|
+
* agree on the same name. Opt-in because renaming already-released constraint
|
|
2369
|
+
* names would orphan the existing objects in deployed catalogs.
|
|
2359
2370
|
*/
|
|
2360
|
-
function buildConstraintName({ baseName, schemaName, maxLength = 63 }) {
|
|
2361
|
-
|
|
2371
|
+
function buildConstraintName({ baseName, schemaName, maxLength = 63, hashWhenTruncated = false }) {
|
|
2372
|
+
const fullName = `${schemaName ? `${schemaName}_` : ""}${baseName}`.toLowerCase();
|
|
2373
|
+
if (hashWhenTruncated && Buffer.byteLength(fullName, "utf-8") > maxLength) {
|
|
2374
|
+
const suffixLength = Math.min(TRUNCATION_HASH_SUFFIX_LENGTH, maxLength);
|
|
2375
|
+
if (suffixLength < 2) return truncateIdentifier(fullName, maxLength);
|
|
2376
|
+
const hash = createHash("sha256").update(fullName).digest("hex").slice(0, suffixLength - 1);
|
|
2377
|
+
return `${truncateIdentifier(fullName, maxLength - suffixLength)}_${hash}`;
|
|
2378
|
+
}
|
|
2379
|
+
return truncateIdentifier(fullName, maxLength);
|
|
2362
2380
|
}
|
|
2363
2381
|
//#endregion
|
|
2364
2382
|
//#region src/storage/db/pg-errors.ts
|
|
@@ -22293,6 +22311,7 @@ const WORKFLOW_SNAPSHOT_STATUS_INDEX = "mastra_workflow_snapshot_name_status_cre
|
|
|
22293
22311
|
* Schema-prefixed name of the status index, lowercased and truncated the same way Postgres
|
|
22294
22312
|
* stores it, so the init snapshot's index set answers "does it exist?" without a probe or a
|
|
22295
22313
|
* no-op `CREATE INDEX` (schema-prefixed names routinely exceed the 63-byte limit).
|
|
22314
|
+
* Exported for tests.
|
|
22296
22315
|
*/
|
|
22297
22316
|
function workflowSnapshotStatusIndexName(schemaName) {
|
|
22298
22317
|
return buildConstraintName({
|
|
@@ -22310,6 +22329,48 @@ function workflowSnapshotStatusIndexSQL(indexName, schemaName) {
|
|
|
22310
22329
|
schemaName: getSchemaName(schemaName)
|
|
22311
22330
|
})} (workflow_name, (snapshot ->> 'status'), "createdAt" DESC)`;
|
|
22312
22331
|
}
|
|
22332
|
+
/** Base name (before any schema prefix) of the expression index backing the threadId filter. */
|
|
22333
|
+
const WORKFLOW_SNAPSHOT_THREAD_ID_INDEX = "mastra_workflow_snapshot_threadid_idx";
|
|
22334
|
+
/**
|
|
22335
|
+
* Schema-prefixed name of the threadId index (see workflowSnapshotStatusIndexName).
|
|
22336
|
+
*
|
|
22337
|
+
* Unlike the status index, truncation appends a collision hash: both index names share the
|
|
22338
|
+
* long `<schema>_mastra_workflow_snapshot_` prefix, so with a schema name of 37+ bytes plain
|
|
22339
|
+
* truncation collapses them to the same 63-byte identifier and `CREATE INDEX IF NOT EXISTS`
|
|
22340
|
+
* silently skips this index. The status index keeps plain truncation because its truncated
|
|
22341
|
+
* name already exists in deployed catalogs; this index is new and free to adopt the rule.
|
|
22342
|
+
* Exported for tests.
|
|
22343
|
+
*/
|
|
22344
|
+
function workflowSnapshotThreadIdIndexName(schemaName) {
|
|
22345
|
+
return buildConstraintName({
|
|
22346
|
+
baseName: WORKFLOW_SNAPSHOT_THREAD_ID_INDEX,
|
|
22347
|
+
schemaName: schemaName && schemaName !== "public" ? schemaName : void 0,
|
|
22348
|
+
hashWhenTruncated: true
|
|
22349
|
+
});
|
|
22350
|
+
}
|
|
22351
|
+
/**
|
|
22352
|
+
* Expression extracting the thread id embedded in a snapshot (jsonb columns only). Mirrors
|
|
22353
|
+
* the canonical extraction in `@mastra/core` (`getSnapshotMemoryInfo`), which reads one of
|
|
22354
|
+
* two layouts:
|
|
22355
|
+
* 1. agentic-loop: `context.<suspended step>.suspendPayload.__streamState.messageList.memoryInfo.threadId`
|
|
22356
|
+
* 2. durable loop: `context.input.messageListState.memoryInfo.threadId`
|
|
22357
|
+
*
|
|
22358
|
+
* `jsonb_path_query_first(jsonb, jsonpath)` is IMMUTABLE, so the expression is valid in an
|
|
22359
|
+
* expression index. The WHERE clause in listWorkflowRuns() must use this exact expression
|
|
22360
|
+
* text so the planner can match it against the index. If the snapshot layout changes in
|
|
22361
|
+
* core, this expression must be updated in lockstep or it will wrongly exclude rows.
|
|
22362
|
+
*/
|
|
22363
|
+
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}')`;
|
|
22364
|
+
/**
|
|
22365
|
+
* Expression index on the snapshot-embedded thread id so listWorkflowRuns() threadId filters
|
|
22366
|
+
* (Agent.listSuspendedRuns) can use an index instead of detoasting every snapshot.
|
|
22367
|
+
*/
|
|
22368
|
+
function workflowSnapshotThreadIdIndexSQL(indexName, schemaName) {
|
|
22369
|
+
return `CREATE INDEX IF NOT EXISTS "${indexName}" ON ${getTableName({
|
|
22370
|
+
indexName: TABLE_WORKFLOW_SNAPSHOT,
|
|
22371
|
+
schemaName: getSchemaName(schemaName)
|
|
22372
|
+
})} ((${WORKFLOW_SNAPSHOT_THREAD_ID_EXPR}))`;
|
|
22373
|
+
}
|
|
22313
22374
|
var WorkflowsPG = class WorkflowsPG extends WorkflowsStorage {
|
|
22314
22375
|
#db;
|
|
22315
22376
|
#schema;
|
|
@@ -22382,6 +22443,7 @@ var WorkflowsPG = class WorkflowsPG extends WorkflowsStorage {
|
|
|
22382
22443
|
}));
|
|
22383
22444
|
for (const idx of WorkflowsPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
|
|
22384
22445
|
statements.push(`${workflowSnapshotStatusIndexSQL(workflowSnapshotStatusIndexName(parsedSchema), schemaName)};`);
|
|
22446
|
+
statements.push(`${workflowSnapshotThreadIdIndexSQL(workflowSnapshotThreadIdIndexName(parsedSchema), schemaName)};`);
|
|
22385
22447
|
return statements;
|
|
22386
22448
|
}
|
|
22387
22449
|
/**
|
|
@@ -22408,6 +22470,12 @@ var WorkflowsPG = class WorkflowsPG extends WorkflowsStorage {
|
|
|
22408
22470
|
} catch (error) {
|
|
22409
22471
|
this.logger?.warn?.(`Failed to create index ${indexName}:`, error);
|
|
22410
22472
|
}
|
|
22473
|
+
const threadIdIndexName = workflowSnapshotThreadIdIndexName(this.#schema);
|
|
22474
|
+
try {
|
|
22475
|
+
await this.#db.createIndexFromStatement(threadIdIndexName, workflowSnapshotThreadIdIndexSQL(threadIdIndexName, this.#schema));
|
|
22476
|
+
} catch (error) {
|
|
22477
|
+
this.logger?.warn?.(`Failed to create index ${threadIdIndexName}:`, error);
|
|
22478
|
+
}
|
|
22411
22479
|
}
|
|
22412
22480
|
async init() {
|
|
22413
22481
|
await this.#db.createTable({
|
|
@@ -22688,7 +22756,7 @@ var WorkflowsPG = class WorkflowsPG extends WorkflowsStorage {
|
|
|
22688
22756
|
}, error);
|
|
22689
22757
|
}
|
|
22690
22758
|
}
|
|
22691
|
-
async listWorkflowRuns({ workflowName, fromDate, toDate, perPage, page, resourceId, status } = {}) {
|
|
22759
|
+
async listWorkflowRuns({ workflowName, fromDate, toDate, perPage, page, resourceId, threadId, status } = {}) {
|
|
22692
22760
|
try {
|
|
22693
22761
|
const conditions = [];
|
|
22694
22762
|
const values = [];
|
|
@@ -22709,6 +22777,11 @@ var WorkflowsPG = class WorkflowsPG extends WorkflowsStorage {
|
|
|
22709
22777
|
values.push(resourceId);
|
|
22710
22778
|
paramIndex++;
|
|
22711
22779
|
} else this.logger?.warn?.(`[${TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
22780
|
+
if (threadId) if (await this.#db.getColumnType(TABLE_WORKFLOW_SNAPSHOT, "snapshot") === "jsonb") {
|
|
22781
|
+
conditions.push(`${WORKFLOW_SNAPSHOT_THREAD_ID_EXPR} = $${paramIndex}`);
|
|
22782
|
+
values.push(threadId);
|
|
22783
|
+
paramIndex++;
|
|
22784
|
+
} else this.logger?.warn?.(`[${TABLE_WORKFLOW_SNAPSHOT}] snapshot column is not jsonb. Skipping threadId filter.`);
|
|
22712
22785
|
if (fromDate) {
|
|
22713
22786
|
conditions.push(`"createdAt" >= $${paramIndex}`);
|
|
22714
22787
|
values.push(fromDate);
|