@mastra/pg 1.33.0-alpha.2 → 1.33.0-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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +128 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +128 -57
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +14 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +2 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/thread-query.d.ts +0 -2
- package/dist/storage/domains/observability/v-next/thread-query.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +9 -3
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/docs/SKILL.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -4019,6 +4019,42 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
4019
4019
|
}, error);
|
|
4020
4020
|
}
|
|
4021
4021
|
}
|
|
4022
|
+
/**
|
|
4023
|
+
* Runs one UPDATE per record in a transaction, changing a row only while every
|
|
4024
|
+
* column in `nullColumns` is still NULL. Never inserts. Returns, in input order,
|
|
4025
|
+
* whether each update changed a row.
|
|
4026
|
+
*/
|
|
4027
|
+
async batchUpdateWhereNull({ tableName, updates, nullColumns }) {
|
|
4028
|
+
const nullConditions = nullColumns.map((column) => ` AND "${(0, _mastra_core_utils.parseSqlIdentifier)(column, "column name")}" IS NULL`).join("");
|
|
4029
|
+
try {
|
|
4030
|
+
return await this.client.tx(async (tx) => {
|
|
4031
|
+
const applied = [];
|
|
4032
|
+
for (const update of updates) {
|
|
4033
|
+
const query = await this.buildUpdateQuery({
|
|
4034
|
+
tableName,
|
|
4035
|
+
...update
|
|
4036
|
+
});
|
|
4037
|
+
if (!query) {
|
|
4038
|
+
applied.push(false);
|
|
4039
|
+
continue;
|
|
4040
|
+
}
|
|
4041
|
+
const rows = await tx.any(`${query.sql}${nullConditions} RETURNING 1`, query.values);
|
|
4042
|
+
applied.push(rows.length > 0);
|
|
4043
|
+
}
|
|
4044
|
+
return applied;
|
|
4045
|
+
});
|
|
4046
|
+
} catch (error) {
|
|
4047
|
+
throw new _mastra_core_error.MastraError({
|
|
4048
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "BATCH_UPDATE_WHERE_NULL", "FAILED"),
|
|
4049
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
4050
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
4051
|
+
details: {
|
|
4052
|
+
tableName,
|
|
4053
|
+
numberOfRecords: updates.length
|
|
4054
|
+
}
|
|
4055
|
+
}, error);
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4022
4058
|
async batchDelete({ tableName, keys }) {
|
|
4023
4059
|
try {
|
|
4024
4060
|
if (keys.length === 0) return;
|
|
@@ -4139,9 +4175,14 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
4139
4175
|
columns: [column]
|
|
4140
4176
|
});
|
|
4141
4177
|
}
|
|
4142
|
-
async executeUpdate(client,
|
|
4178
|
+
async executeUpdate(client, args) {
|
|
4179
|
+
const query = await this.buildUpdateQuery(args);
|
|
4180
|
+
if (!query) return;
|
|
4181
|
+
await client.none(query.sql, query.values);
|
|
4182
|
+
}
|
|
4183
|
+
async buildUpdateQuery({ tableName, keys, data }) {
|
|
4143
4184
|
const filteredData = await this.filterRecordToKnownColumns(tableName, data);
|
|
4144
|
-
if (Object.keys(filteredData).length === 0) return;
|
|
4185
|
+
if (Object.keys(filteredData).length === 0) return null;
|
|
4145
4186
|
const setColumns = [];
|
|
4146
4187
|
const setValues = [];
|
|
4147
4188
|
let paramIndex = 1;
|
|
@@ -4157,12 +4198,13 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
4157
4198
|
whereConditions.push(`"${parsedKey}" = $${paramIndex++}`);
|
|
4158
4199
|
whereValues.push(this.prepareValue(value, key, tableName));
|
|
4159
4200
|
});
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4201
|
+
return {
|
|
4202
|
+
sql: `UPDATE ${getTableName$6({
|
|
4203
|
+
indexName: tableName,
|
|
4204
|
+
schemaName: getSchemaName$6(this.schemaName)
|
|
4205
|
+
})} SET ${setColumns.join(", ")} WHERE ${whereConditions.join(" AND ")}`,
|
|
4206
|
+
values: [...setValues, ...whereValues]
|
|
4207
|
+
};
|
|
4166
4208
|
}
|
|
4167
4209
|
};
|
|
4168
4210
|
// src/storage/domains/utils.ts
|
|
@@ -12038,7 +12080,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12038
12080
|
indexName: OM_TABLE,
|
|
12039
12081
|
schemaName: quotedSchemaName
|
|
12040
12082
|
});
|
|
12041
|
-
const idxPrefix = schemaPrefix ?
|
|
12083
|
+
const idxPrefix = schemaPrefix ? schemaPrefix : "";
|
|
12042
12084
|
statements.push(`CREATE INDEX IF NOT EXISTS "${idxPrefix}idx_om_lookup_key" ON ${fullOmTableName} ("lookupKey");`);
|
|
12043
12085
|
}
|
|
12044
12086
|
for (const idx of MemoryPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
|
|
@@ -15712,30 +15754,33 @@ var ObservabilityPG = class ObservabilityPG extends _mastra_core_storage.Observa
|
|
|
15712
15754
|
}, error);
|
|
15713
15755
|
}
|
|
15714
15756
|
}
|
|
15757
|
+
#toSpanUpdates(records) {
|
|
15758
|
+
return records.map((record) => {
|
|
15759
|
+
const data = { ...record.updates };
|
|
15760
|
+
if (data.endedAt instanceof Date) {
|
|
15761
|
+
const endedAt = data.endedAt.toISOString();
|
|
15762
|
+
data.endedAt = endedAt;
|
|
15763
|
+
data.endedAtZ = endedAt;
|
|
15764
|
+
}
|
|
15765
|
+
if (data.startedAt instanceof Date) {
|
|
15766
|
+
const startedAt = data.startedAt.toISOString();
|
|
15767
|
+
data.startedAt = startedAt;
|
|
15768
|
+
data.startedAtZ = startedAt;
|
|
15769
|
+
}
|
|
15770
|
+
return {
|
|
15771
|
+
keys: {
|
|
15772
|
+
spanId: record.spanId,
|
|
15773
|
+
traceId: record.traceId
|
|
15774
|
+
},
|
|
15775
|
+
data
|
|
15776
|
+
};
|
|
15777
|
+
});
|
|
15778
|
+
}
|
|
15715
15779
|
async batchUpdateSpans(args) {
|
|
15716
15780
|
try {
|
|
15717
15781
|
return this.#db.batchUpdate({
|
|
15718
15782
|
tableName: _mastra_core_storage.TABLE_SPANS,
|
|
15719
|
-
updates: args.records
|
|
15720
|
-
const data = { ...record.updates };
|
|
15721
|
-
if (data.endedAt instanceof Date) {
|
|
15722
|
-
const endedAt = data.endedAt.toISOString();
|
|
15723
|
-
data.endedAt = endedAt;
|
|
15724
|
-
data.endedAtZ = endedAt;
|
|
15725
|
-
}
|
|
15726
|
-
if (data.startedAt instanceof Date) {
|
|
15727
|
-
const startedAt = data.startedAt.toISOString();
|
|
15728
|
-
data.startedAt = startedAt;
|
|
15729
|
-
data.startedAtZ = startedAt;
|
|
15730
|
-
}
|
|
15731
|
-
return {
|
|
15732
|
-
keys: {
|
|
15733
|
-
spanId: record.spanId,
|
|
15734
|
-
traceId: record.traceId
|
|
15735
|
-
},
|
|
15736
|
-
data
|
|
15737
|
-
};
|
|
15738
|
-
})
|
|
15783
|
+
updates: this.#toSpanUpdates(args.records)
|
|
15739
15784
|
});
|
|
15740
15785
|
} catch (error) {
|
|
15741
15786
|
throw new _mastra_core_error.MastraError({
|
|
@@ -15745,6 +15790,25 @@ var ObservabilityPG = class ObservabilityPG extends _mastra_core_storage.Observa
|
|
|
15745
15790
|
}, error);
|
|
15746
15791
|
}
|
|
15747
15792
|
}
|
|
15793
|
+
async batchUpdateUnendedSpans(args) {
|
|
15794
|
+
try {
|
|
15795
|
+
const applied = await this.#db.batchUpdateWhereNull({
|
|
15796
|
+
tableName: _mastra_core_storage.TABLE_SPANS,
|
|
15797
|
+
updates: this.#toSpanUpdates(args.records),
|
|
15798
|
+
nullColumns: ["endedAt"]
|
|
15799
|
+
});
|
|
15800
|
+
return { updated: args.records.filter((_, index) => applied[index]).map(({ traceId, spanId }) => ({
|
|
15801
|
+
traceId,
|
|
15802
|
+
spanId
|
|
15803
|
+
})) };
|
|
15804
|
+
} catch (error) {
|
|
15805
|
+
throw new _mastra_core_error.MastraError({
|
|
15806
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "BATCH_UPDATE_UNENDED_SPANS", "FAILED"),
|
|
15807
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
15808
|
+
category: _mastra_core_error.ErrorCategory.USER
|
|
15809
|
+
}, error);
|
|
15810
|
+
}
|
|
15811
|
+
}
|
|
15748
15812
|
async batchDeleteTraces(args) {
|
|
15749
15813
|
this.assertUnscopedBatchDeleteTraces(args);
|
|
15750
15814
|
try {
|
|
@@ -20583,7 +20647,7 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
|
|
|
20583
20647
|
return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${values.length}`;
|
|
20584
20648
|
}).join(" AND ")})`;
|
|
20585
20649
|
}));
|
|
20586
|
-
const payloads = await run(`SELECT "organizationId", "traceId", "cursorId",
|
|
20650
|
+
const payloads = await run(`SELECT "organizationId", "traceId", "cursorId", ${contextFields.map((field) => `"${field}"`).join(", ")},
|
|
20587
20651
|
CASE WHEN "spanType" = 'agent_run' THEN "timeToFirstChunkMs" END AS "timeToFirstChunkMs",
|
|
20588
20652
|
CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
20589
20653
|
${[
|
|
@@ -20598,30 +20662,10 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
|
|
|
20598
20662
|
String(version)
|
|
20599
20663
|
]);
|
|
20600
20664
|
const byRoot = new Map(payloads.map((row) => [key(row.organizationId, row.traceId, row.cursorId), row]));
|
|
20601
|
-
const agents = page.filter((row) => byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId))?.spanType === "agent_run");
|
|
20602
|
-
const models = /* @__PURE__ */ new Map();
|
|
20603
|
-
if (agents.length) {
|
|
20604
|
-
const modelValues = [];
|
|
20605
|
-
const rows = await run(`SELECT DISTINCT ON ("organizationId", "traceId") "organizationId", "traceId",
|
|
20606
|
-
CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
20607
|
-
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider
|
|
20608
|
-
FROM ${table} WHERE "spanType" = 'model_generation' AND NOT "isPending" AND (${agents.map((row) => `(${Object.entries({
|
|
20609
|
-
organizationId: row.organizationId,
|
|
20610
|
-
resourceId: row.resourceId,
|
|
20611
|
-
traceId: row.firstTraceId,
|
|
20612
|
-
parentSpanId: row.firstSpanId
|
|
20613
|
-
}).map(([field, value]) => {
|
|
20614
|
-
modelValues.push(value);
|
|
20615
|
-
return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${modelValues.length}`;
|
|
20616
|
-
}).join(" AND ")})`).join(" OR ")})
|
|
20617
|
-
ORDER BY "organizationId", "traceId", "startedAt", "spanId" COLLATE "C", "cursorId" DESC`, modelValues);
|
|
20618
|
-
for (const row of rows) models.set(JSON.stringify([row.organizationId, row.traceId]), row);
|
|
20619
|
-
}
|
|
20620
20665
|
const threads = page.flatMap((row) => {
|
|
20621
20666
|
const first = byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId));
|
|
20622
20667
|
const last = byRoot.get(key(row.organizationId, row.lastTraceId, row.lastCursorId));
|
|
20623
20668
|
if (!first || !last) return [];
|
|
20624
|
-
const model = models.get(JSON.stringify([row.organizationId, row.firstTraceId]));
|
|
20625
20669
|
return [_mastra_core_storage.threadQueryRowSchema.parse({
|
|
20626
20670
|
organizationId: row.organizationId,
|
|
20627
20671
|
threadId: row.threadId,
|
|
@@ -20633,8 +20677,6 @@ async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto
|
|
|
20633
20677
|
endedAt: row.endedAt.toISOString(),
|
|
20634
20678
|
traceCount: Number(row.traceCount),
|
|
20635
20679
|
timeToFirstChunkMs: first.timeToFirstChunkMs,
|
|
20636
|
-
model: model?.model ?? null,
|
|
20637
|
-
provider: model?.provider ?? null,
|
|
20638
20680
|
inputPreview: readPreview(first.inputPreview, first.input),
|
|
20639
20681
|
outputPreview: readPreview(last.outputPreview, last.output),
|
|
20640
20682
|
errorPreview: readPreview(last.errorPreview, last.error)
|
|
@@ -25618,6 +25660,13 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
25618
25660
|
supportsConcurrentUpdates() {
|
|
25619
25661
|
return true;
|
|
25620
25662
|
}
|
|
25663
|
+
supportsGuardedSnapshotWrites() {
|
|
25664
|
+
return true;
|
|
25665
|
+
}
|
|
25666
|
+
/** SQL for a snapshot's status. Legacy json/text columns can hold escapes that fail a jsonb cast (#11563). */
|
|
25667
|
+
async #statusExpression(column) {
|
|
25668
|
+
return await this.#db.getColumnType(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, "snapshot") === "jsonb" ? `${column} ->> 'status'` : `regexp_replace(${column}::text, '\\\\u(0000|[Dd][89A-Fa-f][0-9A-Fa-f]{2})', '', 'g')::jsonb ->> 'status'`;
|
|
25669
|
+
}
|
|
25621
25670
|
parseWorkflowRun(row) {
|
|
25622
25671
|
let parsedSnapshot = row.snapshot;
|
|
25623
25672
|
if (typeof parsedSnapshot === "string") try {
|
|
@@ -26013,20 +26062,22 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
26013
26062
|
}, error);
|
|
26014
26063
|
}
|
|
26015
26064
|
}
|
|
26016
|
-
async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence }) {
|
|
26065
|
+
async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence, expectedStatus }) {
|
|
26017
26066
|
try {
|
|
26018
26067
|
const now = /* @__PURE__ */ new Date();
|
|
26019
26068
|
const createdAtValue = createdAt ? createdAt : now;
|
|
26020
26069
|
const updatedAtValue = updatedAt ? updatedAt : now;
|
|
26021
26070
|
const sanitizedSnapshot = toPgJson(snapshot);
|
|
26022
|
-
|
|
26071
|
+
const guard = expectedStatus === void 0 ? "" : ` WHERE ${await this.#statusExpression("t.snapshot")} = ANY($9::text[])`;
|
|
26072
|
+
return await withRunFence(this.#db.client, this.#runOwnersTable(), (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "persistWorkflowSnapshot", (q) => q.oneOrNone(`INSERT INTO ${getTableName({
|
|
26023
26073
|
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
26024
26074
|
schemaName: getSchemaName(this.#schema)
|
|
26025
26075
|
})} AS t
|
|
26026
26076
|
(workflow_name, run_id, "resourceId", snapshot, "createdAt", "updatedAt", "createdAtZ", "updatedAtZ")
|
|
26027
26077
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
26028
26078
|
ON CONFLICT (workflow_name, run_id) DO UPDATE
|
|
26029
|
-
SET "resourceId" = COALESCE($3, t."resourceId"), snapshot = $4, "updatedAt" = $6, "updatedAtZ" = $8
|
|
26079
|
+
SET "resourceId" = COALESCE($3, t."resourceId"), snapshot = $4, "updatedAt" = $6, "updatedAtZ" = $8${guard}
|
|
26080
|
+
RETURNING 1 AS written`, [
|
|
26030
26081
|
workflowName,
|
|
26031
26082
|
runId,
|
|
26032
26083
|
resourceId,
|
|
@@ -26034,8 +26085,9 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
26034
26085
|
createdAtValue,
|
|
26035
26086
|
updatedAtValue,
|
|
26036
26087
|
createdAtValue,
|
|
26037
|
-
updatedAtValue
|
|
26038
|
-
|
|
26088
|
+
updatedAtValue,
|
|
26089
|
+
...expectedStatus === void 0 ? [] : [Array.isArray(expectedStatus) ? expectedStatus : [expectedStatus]]
|
|
26090
|
+
])) !== null;
|
|
26039
26091
|
} catch (error) {
|
|
26040
26092
|
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
26041
26093
|
throw new _mastra_core_error.MastraError({
|
|
@@ -26045,6 +26097,25 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
26045
26097
|
}, error);
|
|
26046
26098
|
}
|
|
26047
26099
|
}
|
|
26100
|
+
async loadWorkflowRunStatus({ workflowName, runId }) {
|
|
26101
|
+
try {
|
|
26102
|
+
const statusExpr = await this.#statusExpression("snapshot");
|
|
26103
|
+
return (await this.#db.client.oneOrNone(`SELECT ${statusExpr} AS status FROM ${getTableName({
|
|
26104
|
+
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
26105
|
+
schemaName: getSchemaName(this.#schema)
|
|
26106
|
+
})} WHERE "workflow_name" = $1 AND "run_id" = $2 ORDER BY "createdAt" DESC LIMIT 1`, [workflowName, runId]))?.status ?? null;
|
|
26107
|
+
} catch (error) {
|
|
26108
|
+
throw new _mastra_core_error.MastraError({
|
|
26109
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "LOAD_WORKFLOW_RUN_STATUS", "FAILED"),
|
|
26110
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
26111
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
26112
|
+
details: {
|
|
26113
|
+
workflowName,
|
|
26114
|
+
runId
|
|
26115
|
+
}
|
|
26116
|
+
}, error);
|
|
26117
|
+
}
|
|
26118
|
+
}
|
|
26048
26119
|
async loadWorkflowSnapshot({ workflowName, runId }) {
|
|
26049
26120
|
try {
|
|
26050
26121
|
const result = await this.#db.load({
|