@mastra/mssql 0.0.0-feat-support-ai-sdk-5-again-20250813225910 → 0.0.0-feat-add-query-option-to-playground-20251209160219
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 +1004 -3
- package/README.md +324 -37
- package/dist/index.cjs +1847 -756
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1848 -757
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +15 -36
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +44 -0
- package/dist/storage/domains/observability/index.d.ts.map +1 -0
- package/dist/storage/domains/operations/index.d.ts +67 -4
- package/dist/storage/domains/operations/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +15 -6
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/utils.d.ts +19 -0
- package/dist/storage/domains/utils.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +28 -10
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +116 -74
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +30 -12
- package/dist/storage/domains/legacy-evals/index.d.ts +0 -20
- package/dist/storage/domains/legacy-evals/index.d.ts.map +0 -1
- package/dist/storage/domains/traces/index.d.ts +0 -37
- package/dist/storage/domains/traces/index.d.ts.map +0 -1
- package/docker-compose.yaml +0 -14
- package/eslint.config.js +0 -6
- package/src/index.ts +0 -2
- package/src/storage/domains/legacy-evals/index.ts +0 -175
- package/src/storage/domains/memory/index.ts +0 -1024
- package/src/storage/domains/operations/index.ts +0 -401
- package/src/storage/domains/scores/index.ts +0 -316
- package/src/storage/domains/traces/index.ts +0 -212
- package/src/storage/domains/utils.ts +0 -12
- package/src/storage/domains/workflows/index.ts +0 -259
- package/src/storage/index.test.ts +0 -2228
- package/src/storage/index.ts +0 -448
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -17
- package/vitest.config.ts +0 -12
package/dist/index.cjs
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
var error = require('@mastra/core/error');
|
|
4
4
|
var storage = require('@mastra/core/storage');
|
|
5
|
-
var
|
|
6
|
-
var utils = require('@mastra/core/utils');
|
|
5
|
+
var sql3 = require('mssql');
|
|
7
6
|
var agent = require('@mastra/core/agent');
|
|
7
|
+
var utils = require('@mastra/core/utils');
|
|
8
|
+
var crypto = require('crypto');
|
|
9
|
+
var evals = require('@mastra/core/evals');
|
|
8
10
|
|
|
9
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
12
|
|
|
11
|
-
var
|
|
13
|
+
var sql3__default = /*#__PURE__*/_interopDefault(sql3);
|
|
12
14
|
|
|
13
15
|
// src/storage/index.ts
|
|
14
16
|
function getSchemaName(schema) {
|
|
@@ -20,154 +22,109 @@ function getTableName({ indexName, schemaName }) {
|
|
|
20
22
|
const quotedSchemaName = schemaName;
|
|
21
23
|
return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (row.test_info) {
|
|
28
|
-
try {
|
|
29
|
-
testInfoValue = typeof row.test_info === "string" ? JSON.parse(row.test_info) : row.test_info;
|
|
30
|
-
} catch {
|
|
31
|
-
}
|
|
25
|
+
function buildDateRangeFilter(dateRange, fieldName) {
|
|
26
|
+
const filters = {};
|
|
27
|
+
if (dateRange?.start) {
|
|
28
|
+
filters[`${fieldName}_gte`] = dateRange.start;
|
|
32
29
|
}
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
resultValue = typeof row.result === "string" ? JSON.parse(row.result) : row.result;
|
|
36
|
-
} catch {
|
|
37
|
-
}
|
|
30
|
+
if (dateRange?.end) {
|
|
31
|
+
filters[`${fieldName}_lte`] = dateRange.end;
|
|
38
32
|
}
|
|
39
|
-
return
|
|
40
|
-
agentName: row.agent_name,
|
|
41
|
-
input: row.input,
|
|
42
|
-
output: row.output,
|
|
43
|
-
result: resultValue,
|
|
44
|
-
metricName: row.metric_name,
|
|
45
|
-
instructions: row.instructions,
|
|
46
|
-
testInfo: testInfoValue,
|
|
47
|
-
globalRunId: row.global_run_id,
|
|
48
|
-
runId: row.run_id,
|
|
49
|
-
createdAt: row.created_at
|
|
50
|
-
};
|
|
33
|
+
return filters;
|
|
51
34
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const where = [];
|
|
88
|
-
const params = {};
|
|
89
|
-
if (agentName) {
|
|
90
|
-
where.push("agent_name = @agentName");
|
|
91
|
-
params["agentName"] = agentName;
|
|
92
|
-
}
|
|
93
|
-
if (type === "test") {
|
|
94
|
-
where.push("test_info IS NOT NULL AND JSON_VALUE(test_info, '$.testPath') IS NOT NULL");
|
|
95
|
-
} else if (type === "live") {
|
|
96
|
-
where.push("(test_info IS NULL OR JSON_VALUE(test_info, '$.testPath') IS NULL)");
|
|
97
|
-
}
|
|
98
|
-
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
99
|
-
where.push(`[created_at] >= @fromDate`);
|
|
100
|
-
params[`fromDate`] = fromDate.toISOString();
|
|
101
|
-
}
|
|
102
|
-
if (toDate instanceof Date && !isNaN(toDate.getTime())) {
|
|
103
|
-
where.push(`[created_at] <= @toDate`);
|
|
104
|
-
params[`toDate`] = toDate.toISOString();
|
|
105
|
-
}
|
|
106
|
-
const whereClause = where.length > 0 ? `WHERE ${where.join(" AND ")}` : "";
|
|
107
|
-
const tableName = getTableName({ indexName: storage.TABLE_EVALS, schemaName: getSchemaName(this.schema) });
|
|
108
|
-
const offset = page * perPage;
|
|
109
|
-
const countQuery = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause}`;
|
|
110
|
-
const dataQuery = `SELECT * FROM ${tableName} ${whereClause} ORDER BY seq_id DESC OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
111
|
-
try {
|
|
112
|
-
const countReq = this.pool.request();
|
|
113
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
114
|
-
if (value instanceof Date) {
|
|
115
|
-
countReq.input(key, sql2__default.default.DateTime, value);
|
|
116
|
-
} else {
|
|
117
|
-
countReq.input(key, value);
|
|
35
|
+
function isInOperator(value) {
|
|
36
|
+
return typeof value === "object" && value !== null && "$in" in value && Array.isArray(value.$in);
|
|
37
|
+
}
|
|
38
|
+
function prepareWhereClause(filters, _schema) {
|
|
39
|
+
const conditions = [];
|
|
40
|
+
const params = {};
|
|
41
|
+
let paramIndex = 1;
|
|
42
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
43
|
+
if (value === void 0) return;
|
|
44
|
+
if (key.endsWith("_gte")) {
|
|
45
|
+
const paramName = `p${paramIndex++}`;
|
|
46
|
+
const fieldName = key.slice(0, -4);
|
|
47
|
+
conditions.push(`[${utils.parseSqlIdentifier(fieldName, "field name")}] >= @${paramName}`);
|
|
48
|
+
params[paramName] = value instanceof Date ? value.toISOString() : value;
|
|
49
|
+
} else if (key.endsWith("_lte")) {
|
|
50
|
+
const paramName = `p${paramIndex++}`;
|
|
51
|
+
const fieldName = key.slice(0, -4);
|
|
52
|
+
conditions.push(`[${utils.parseSqlIdentifier(fieldName, "field name")}] <= @${paramName}`);
|
|
53
|
+
params[paramName] = value instanceof Date ? value.toISOString() : value;
|
|
54
|
+
} else if (value === null) {
|
|
55
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IS NULL`);
|
|
56
|
+
} else if (isInOperator(value)) {
|
|
57
|
+
const inValues = value.$in;
|
|
58
|
+
if (inValues.length === 0) {
|
|
59
|
+
conditions.push("1 = 0");
|
|
60
|
+
} else if (inValues.length === 1) {
|
|
61
|
+
const paramName = `p${paramIndex++}`;
|
|
62
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
|
|
63
|
+
params[paramName] = inValues[0] instanceof Date ? inValues[0].toISOString() : inValues[0];
|
|
64
|
+
} else {
|
|
65
|
+
const inParamNames = [];
|
|
66
|
+
for (const item of inValues) {
|
|
67
|
+
const paramName = `p${paramIndex++}`;
|
|
68
|
+
inParamNames.push(`@${paramName}`);
|
|
69
|
+
params[paramName] = item instanceof Date ? item.toISOString() : item;
|
|
118
70
|
}
|
|
119
|
-
|
|
120
|
-
const countResult = await countReq.query(countQuery);
|
|
121
|
-
const total = countResult.recordset[0]?.total || 0;
|
|
122
|
-
if (total === 0) {
|
|
123
|
-
return {
|
|
124
|
-
evals: [],
|
|
125
|
-
total: 0,
|
|
126
|
-
page,
|
|
127
|
-
perPage,
|
|
128
|
-
hasMore: false
|
|
129
|
-
};
|
|
71
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IN (${inParamNames.join(", ")})`);
|
|
130
72
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
73
|
+
} else if (Array.isArray(value)) {
|
|
74
|
+
if (value.length === 0) {
|
|
75
|
+
conditions.push("1 = 0");
|
|
76
|
+
} else if (value.length === 1) {
|
|
77
|
+
const paramName = `p${paramIndex++}`;
|
|
78
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
|
|
79
|
+
params[paramName] = value[0] instanceof Date ? value[0].toISOString() : value[0];
|
|
80
|
+
} else {
|
|
81
|
+
const inParamNames = [];
|
|
82
|
+
for (const item of value) {
|
|
83
|
+
const paramName = `p${paramIndex++}`;
|
|
84
|
+
inParamNames.push(`@${paramName}`);
|
|
85
|
+
params[paramName] = item instanceof Date ? item.toISOString() : item;
|
|
137
86
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
evals: rows?.map((row) => transformEvalRow(row)) ?? [],
|
|
145
|
-
total,
|
|
146
|
-
page,
|
|
147
|
-
perPage,
|
|
148
|
-
hasMore: offset + (rows?.length ?? 0) < total
|
|
149
|
-
};
|
|
150
|
-
} catch (error$1) {
|
|
151
|
-
const mastraError = new error.MastraError(
|
|
152
|
-
{
|
|
153
|
-
id: "MASTRA_STORAGE_MSSQL_STORE_GET_EVALS_FAILED",
|
|
154
|
-
domain: error.ErrorDomain.STORAGE,
|
|
155
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
156
|
-
details: {
|
|
157
|
-
agentName: agentName || "all",
|
|
158
|
-
type: type || "all",
|
|
159
|
-
page,
|
|
160
|
-
perPage
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
error$1
|
|
164
|
-
);
|
|
165
|
-
this.logger?.error?.(mastraError.toString());
|
|
166
|
-
this.logger?.trackException(mastraError);
|
|
167
|
-
throw mastraError;
|
|
87
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IN (${inParamNames.join(", ")})`);
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
const paramName = `p${paramIndex++}`;
|
|
91
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
|
|
92
|
+
params[paramName] = value instanceof Date ? value.toISOString() : value;
|
|
168
93
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
sql: conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "",
|
|
97
|
+
params
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function transformFromSqlRow({
|
|
101
|
+
tableName,
|
|
102
|
+
sqlRow
|
|
103
|
+
}) {
|
|
104
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
105
|
+
const result = {};
|
|
106
|
+
Object.entries(sqlRow).forEach(([key, value]) => {
|
|
107
|
+
const columnSchema = schema?.[key];
|
|
108
|
+
if (columnSchema?.type === "jsonb" && typeof value === "string") {
|
|
109
|
+
try {
|
|
110
|
+
result[key] = JSON.parse(value);
|
|
111
|
+
} catch {
|
|
112
|
+
result[key] = value;
|
|
113
|
+
}
|
|
114
|
+
} else if (columnSchema?.type === "timestamp" && value && typeof value === "string") {
|
|
115
|
+
result[key] = new Date(value);
|
|
116
|
+
} else if (columnSchema?.type === "timestamp" && value instanceof Date) {
|
|
117
|
+
result[key] = value;
|
|
118
|
+
} else if (columnSchema?.type === "boolean") {
|
|
119
|
+
result[key] = Boolean(value);
|
|
120
|
+
} else {
|
|
121
|
+
result[key] = value;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/storage/domains/memory/index.ts
|
|
171
128
|
var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
172
129
|
pool;
|
|
173
130
|
schema;
|
|
@@ -185,7 +142,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
185
142
|
});
|
|
186
143
|
const cleanMessages = messagesWithParsedContent.map(({ seq_id, ...rest }) => rest);
|
|
187
144
|
const list = new agent.MessageList().add(cleanMessages, "memory");
|
|
188
|
-
return format === "v2" ? list.get.all.
|
|
145
|
+
return format === "v2" ? list.get.all.db() : list.get.all.v1();
|
|
189
146
|
}
|
|
190
147
|
constructor({
|
|
191
148
|
pool,
|
|
@@ -199,7 +156,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
199
156
|
}
|
|
200
157
|
async getThreadById({ threadId }) {
|
|
201
158
|
try {
|
|
202
|
-
const
|
|
159
|
+
const sql5 = `SELECT
|
|
203
160
|
id,
|
|
204
161
|
[resourceId],
|
|
205
162
|
title,
|
|
@@ -210,7 +167,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
210
167
|
WHERE id = @threadId`;
|
|
211
168
|
const request = this.pool.request();
|
|
212
169
|
request.input("threadId", threadId);
|
|
213
|
-
const resultSet = await request.query(
|
|
170
|
+
const resultSet = await request.query(sql5);
|
|
214
171
|
const thread = resultSet.recordset[0] || null;
|
|
215
172
|
if (!thread) {
|
|
216
173
|
return null;
|
|
@@ -224,7 +181,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
224
181
|
} catch (error$1) {
|
|
225
182
|
throw new error.MastraError(
|
|
226
183
|
{
|
|
227
|
-
id: "
|
|
184
|
+
id: storage.createStorageErrorId("MSSQL", "GET_THREAD_BY_ID", "FAILED"),
|
|
228
185
|
domain: error.ErrorDomain.STORAGE,
|
|
229
186
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
230
187
|
details: {
|
|
@@ -235,11 +192,24 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
235
192
|
);
|
|
236
193
|
}
|
|
237
194
|
}
|
|
238
|
-
async
|
|
239
|
-
const { resourceId, page = 0, perPage: perPageInput, orderBy
|
|
195
|
+
async listThreadsByResourceId(args) {
|
|
196
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
197
|
+
if (page < 0) {
|
|
198
|
+
throw new error.MastraError({
|
|
199
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
200
|
+
domain: error.ErrorDomain.STORAGE,
|
|
201
|
+
category: error.ErrorCategory.USER,
|
|
202
|
+
text: "Page number must be non-negative",
|
|
203
|
+
details: {
|
|
204
|
+
resourceId,
|
|
205
|
+
page
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
210
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
211
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
240
212
|
try {
|
|
241
|
-
const perPage = perPageInput !== void 0 ? perPageInput : 100;
|
|
242
|
-
const currentOffset = page * perPage;
|
|
243
213
|
const baseQuery = `FROM ${getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) })} WHERE [resourceId] = @resourceId`;
|
|
244
214
|
const countQuery = `SELECT COUNT(*) as count ${baseQuery}`;
|
|
245
215
|
const countRequest = this.pool.request();
|
|
@@ -251,16 +221,22 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
251
221
|
threads: [],
|
|
252
222
|
total: 0,
|
|
253
223
|
page,
|
|
254
|
-
perPage,
|
|
224
|
+
perPage: perPageForResponse,
|
|
255
225
|
hasMore: false
|
|
256
226
|
};
|
|
257
227
|
}
|
|
258
|
-
const orderByField =
|
|
259
|
-
const
|
|
228
|
+
const orderByField = field === "createdAt" ? "[createdAt]" : "[updatedAt]";
|
|
229
|
+
const dir = (direction || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
|
|
230
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
231
|
+
const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir} OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
260
232
|
const dataRequest = this.pool.request();
|
|
261
233
|
dataRequest.input("resourceId", resourceId);
|
|
262
|
-
dataRequest.input("
|
|
263
|
-
|
|
234
|
+
dataRequest.input("offset", offset);
|
|
235
|
+
if (limitValue > 2147483647) {
|
|
236
|
+
dataRequest.input("perPage", sql3__default.default.BigInt, limitValue);
|
|
237
|
+
} else {
|
|
238
|
+
dataRequest.input("perPage", limitValue);
|
|
239
|
+
}
|
|
264
240
|
const rowsResult = await dataRequest.query(dataQuery);
|
|
265
241
|
const rows = rowsResult.recordset || [];
|
|
266
242
|
const threads = rows.map((thread) => ({
|
|
@@ -273,13 +249,13 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
273
249
|
threads,
|
|
274
250
|
total,
|
|
275
251
|
page,
|
|
276
|
-
perPage,
|
|
277
|
-
hasMore:
|
|
252
|
+
perPage: perPageForResponse,
|
|
253
|
+
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
278
254
|
};
|
|
279
255
|
} catch (error$1) {
|
|
280
256
|
const mastraError = new error.MastraError(
|
|
281
257
|
{
|
|
282
|
-
id: "
|
|
258
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
|
|
283
259
|
domain: error.ErrorDomain.STORAGE,
|
|
284
260
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
285
261
|
details: {
|
|
@@ -291,7 +267,13 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
291
267
|
);
|
|
292
268
|
this.logger?.error?.(mastraError.toString());
|
|
293
269
|
this.logger?.trackException?.(mastraError);
|
|
294
|
-
return {
|
|
270
|
+
return {
|
|
271
|
+
threads: [],
|
|
272
|
+
total: 0,
|
|
273
|
+
page,
|
|
274
|
+
perPage: perPageForResponse,
|
|
275
|
+
hasMore: false
|
|
276
|
+
};
|
|
295
277
|
}
|
|
296
278
|
}
|
|
297
279
|
async saveThread({ thread }) {
|
|
@@ -313,15 +295,20 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
313
295
|
req.input("id", thread.id);
|
|
314
296
|
req.input("resourceId", thread.resourceId);
|
|
315
297
|
req.input("title", thread.title);
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
298
|
+
const metadata = thread.metadata ? JSON.stringify(thread.metadata) : null;
|
|
299
|
+
if (metadata === null) {
|
|
300
|
+
req.input("metadata", sql3__default.default.NVarChar, null);
|
|
301
|
+
} else {
|
|
302
|
+
req.input("metadata", metadata);
|
|
303
|
+
}
|
|
304
|
+
req.input("createdAt", sql3__default.default.DateTime2, thread.createdAt);
|
|
305
|
+
req.input("updatedAt", sql3__default.default.DateTime2, thread.updatedAt);
|
|
319
306
|
await req.query(mergeSql);
|
|
320
307
|
return thread;
|
|
321
308
|
} catch (error$1) {
|
|
322
309
|
throw new error.MastraError(
|
|
323
310
|
{
|
|
324
|
-
id: "
|
|
311
|
+
id: storage.createStorageErrorId("MSSQL", "SAVE_THREAD", "FAILED"),
|
|
325
312
|
domain: error.ErrorDomain.STORAGE,
|
|
326
313
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
327
314
|
details: {
|
|
@@ -332,30 +319,6 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
332
319
|
);
|
|
333
320
|
}
|
|
334
321
|
}
|
|
335
|
-
/**
|
|
336
|
-
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
337
|
-
*/
|
|
338
|
-
async getThreadsByResourceId(args) {
|
|
339
|
-
const { resourceId, orderBy = "createdAt", sortDirection = "DESC" } = args;
|
|
340
|
-
try {
|
|
341
|
-
const baseQuery = `FROM ${getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) })} WHERE [resourceId] = @resourceId`;
|
|
342
|
-
const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
|
|
343
|
-
const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${sortDirection}`;
|
|
344
|
-
const request = this.pool.request();
|
|
345
|
-
request.input("resourceId", resourceId);
|
|
346
|
-
const resultSet = await request.query(dataQuery);
|
|
347
|
-
const rows = resultSet.recordset || [];
|
|
348
|
-
return rows.map((thread) => ({
|
|
349
|
-
...thread,
|
|
350
|
-
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
351
|
-
createdAt: thread.createdAt,
|
|
352
|
-
updatedAt: thread.updatedAt
|
|
353
|
-
}));
|
|
354
|
-
} catch (error) {
|
|
355
|
-
this.logger?.error?.(`Error getting threads for resource ${resourceId}:`, error);
|
|
356
|
-
return [];
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
322
|
/**
|
|
360
323
|
* Updates a thread's title and metadata, merging with existing metadata. Returns the updated thread.
|
|
361
324
|
*/
|
|
@@ -367,7 +330,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
367
330
|
const existingThread = await this.getThreadById({ threadId: id });
|
|
368
331
|
if (!existingThread) {
|
|
369
332
|
throw new error.MastraError({
|
|
370
|
-
id: "
|
|
333
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_THREAD", "NOT_FOUND"),
|
|
371
334
|
domain: error.ErrorDomain.STORAGE,
|
|
372
335
|
category: error.ErrorCategory.USER,
|
|
373
336
|
text: `Thread ${id} not found`,
|
|
@@ -383,7 +346,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
383
346
|
};
|
|
384
347
|
try {
|
|
385
348
|
const table = getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) });
|
|
386
|
-
const
|
|
349
|
+
const sql5 = `UPDATE ${table}
|
|
387
350
|
SET title = @title,
|
|
388
351
|
metadata = @metadata,
|
|
389
352
|
[updatedAt] = @updatedAt
|
|
@@ -394,7 +357,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
394
357
|
req.input("title", title);
|
|
395
358
|
req.input("metadata", JSON.stringify(mergedMetadata));
|
|
396
359
|
req.input("updatedAt", /* @__PURE__ */ new Date());
|
|
397
|
-
const result = await req.query(
|
|
360
|
+
const result = await req.query(sql5);
|
|
398
361
|
let thread = result.recordset && result.recordset[0];
|
|
399
362
|
if (thread && "seq_id" in thread) {
|
|
400
363
|
const { seq_id, ...rest } = thread;
|
|
@@ -402,7 +365,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
402
365
|
}
|
|
403
366
|
if (!thread) {
|
|
404
367
|
throw new error.MastraError({
|
|
405
|
-
id: "
|
|
368
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_THREAD", "NOT_FOUND"),
|
|
406
369
|
domain: error.ErrorDomain.STORAGE,
|
|
407
370
|
category: error.ErrorCategory.USER,
|
|
408
371
|
text: `Thread ${id} not found after update`,
|
|
@@ -421,7 +384,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
421
384
|
} catch (error$1) {
|
|
422
385
|
throw new error.MastraError(
|
|
423
386
|
{
|
|
424
|
-
id: "
|
|
387
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_THREAD", "FAILED"),
|
|
425
388
|
domain: error.ErrorDomain.STORAGE,
|
|
426
389
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
427
390
|
details: {
|
|
@@ -451,7 +414,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
451
414
|
});
|
|
452
415
|
throw new error.MastraError(
|
|
453
416
|
{
|
|
454
|
-
id: "
|
|
417
|
+
id: storage.createStorageErrorId("MSSQL", "DELETE_THREAD", "FAILED"),
|
|
455
418
|
domain: error.ErrorDomain.STORAGE,
|
|
456
419
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
457
420
|
details: {
|
|
@@ -462,24 +425,18 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
462
425
|
);
|
|
463
426
|
}
|
|
464
427
|
}
|
|
465
|
-
async _getIncludedMessages({
|
|
466
|
-
|
|
467
|
-
selectBy,
|
|
468
|
-
orderByStatement
|
|
469
|
-
}) {
|
|
470
|
-
const include = selectBy?.include;
|
|
471
|
-
if (!include) return null;
|
|
428
|
+
async _getIncludedMessages({ include }) {
|
|
429
|
+
if (!include || include.length === 0) return null;
|
|
472
430
|
const unionQueries = [];
|
|
473
431
|
const paramValues = [];
|
|
474
432
|
let paramIdx = 1;
|
|
475
433
|
const paramNames = [];
|
|
434
|
+
const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
|
|
476
435
|
for (const inc of include) {
|
|
477
436
|
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
478
|
-
const
|
|
479
|
-
const
|
|
480
|
-
const
|
|
481
|
-
const pPrev = `@p${paramIdx + 2}`;
|
|
482
|
-
const pNext = `@p${paramIdx + 3}`;
|
|
437
|
+
const pId = `@p${paramIdx}`;
|
|
438
|
+
const pPrev = `@p${paramIdx + 1}`;
|
|
439
|
+
const pNext = `@p${paramIdx + 2}`;
|
|
483
440
|
unionQueries.push(
|
|
484
441
|
`
|
|
485
442
|
SELECT
|
|
@@ -492,30 +449,32 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
492
449
|
m.[resourceId],
|
|
493
450
|
m.seq_id
|
|
494
451
|
FROM (
|
|
495
|
-
SELECT *, ROW_NUMBER() OVER (
|
|
496
|
-
FROM ${
|
|
497
|
-
WHERE [thread_id] = ${
|
|
452
|
+
SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
|
|
453
|
+
FROM ${tableName}
|
|
454
|
+
WHERE [thread_id] = (SELECT thread_id FROM ${tableName} WHERE id = ${pId})
|
|
498
455
|
) AS m
|
|
499
456
|
WHERE m.id = ${pId}
|
|
500
457
|
OR EXISTS (
|
|
501
458
|
SELECT 1
|
|
502
459
|
FROM (
|
|
503
|
-
SELECT *, ROW_NUMBER() OVER (
|
|
504
|
-
FROM ${
|
|
505
|
-
WHERE [thread_id] = ${
|
|
460
|
+
SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
|
|
461
|
+
FROM ${tableName}
|
|
462
|
+
WHERE [thread_id] = (SELECT thread_id FROM ${tableName} WHERE id = ${pId})
|
|
506
463
|
) AS target
|
|
507
464
|
WHERE target.id = ${pId}
|
|
508
465
|
AND (
|
|
509
|
-
|
|
466
|
+
-- Get previous messages (messages that come BEFORE the target)
|
|
467
|
+
(m.row_num < target.row_num AND m.row_num >= target.row_num - ${pPrev})
|
|
510
468
|
OR
|
|
511
|
-
|
|
469
|
+
-- Get next messages (messages that come AFTER the target)
|
|
470
|
+
(m.row_num > target.row_num AND m.row_num <= target.row_num + ${pNext})
|
|
512
471
|
)
|
|
513
472
|
)
|
|
514
473
|
`
|
|
515
474
|
);
|
|
516
|
-
paramValues.push(
|
|
517
|
-
paramNames.push(`p${paramIdx}`, `p${paramIdx + 1}`, `p${paramIdx + 2}
|
|
518
|
-
paramIdx +=
|
|
475
|
+
paramValues.push(id, withPreviousMessages, withNextMessages);
|
|
476
|
+
paramNames.push(`p${paramIdx}`, `p${paramIdx + 1}`, `p${paramIdx + 2}`);
|
|
477
|
+
paramIdx += 3;
|
|
519
478
|
}
|
|
520
479
|
const finalQuery = `
|
|
521
480
|
SELECT * FROM (
|
|
@@ -537,33 +496,16 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
537
496
|
});
|
|
538
497
|
return dedupedRows;
|
|
539
498
|
}
|
|
540
|
-
async
|
|
541
|
-
|
|
499
|
+
async listMessagesById({ messageIds }) {
|
|
500
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
542
501
|
const selectStatement = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId`;
|
|
543
502
|
const orderByStatement = `ORDER BY [seq_id] DESC`;
|
|
544
|
-
const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
545
503
|
try {
|
|
546
504
|
let rows = [];
|
|
547
|
-
|
|
548
|
-
if (include?.length) {
|
|
549
|
-
const includeMessages = await this._getIncludedMessages({ threadId, selectBy, orderByStatement });
|
|
550
|
-
if (includeMessages) {
|
|
551
|
-
rows.push(...includeMessages);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
const excludeIds = rows.map((m) => m.id).filter(Boolean);
|
|
555
|
-
let query = `${selectStatement} FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })} WHERE [thread_id] = @threadId`;
|
|
505
|
+
let query = `${selectStatement} FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })} WHERE [id] IN (${messageIds.map((_, i) => `@id${i}`).join(", ")})`;
|
|
556
506
|
const request = this.pool.request();
|
|
557
|
-
request.input(
|
|
558
|
-
|
|
559
|
-
const excludeParams = excludeIds.map((_, idx) => `@id${idx}`);
|
|
560
|
-
query += ` AND id NOT IN (${excludeParams.join(", ")})`;
|
|
561
|
-
excludeIds.forEach((id, idx) => {
|
|
562
|
-
request.input(`id${idx}`, id);
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
query += ` ${orderByStatement} OFFSET 0 ROWS FETCH NEXT @limit ROWS ONLY`;
|
|
566
|
-
request.input("limit", limit);
|
|
507
|
+
messageIds.forEach((id, i) => request.input(`id${i}`, id));
|
|
508
|
+
query += ` ${orderByStatement}`;
|
|
567
509
|
const result = await request.query(query);
|
|
568
510
|
const remainingRows = result.recordset || [];
|
|
569
511
|
rows.push(...remainingRows);
|
|
@@ -571,120 +513,177 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
571
513
|
const timeDiff = a.seq_id - b.seq_id;
|
|
572
514
|
return timeDiff;
|
|
573
515
|
});
|
|
574
|
-
|
|
575
|
-
|
|
516
|
+
const messagesWithParsedContent = rows.map((row) => {
|
|
517
|
+
if (typeof row.content === "string") {
|
|
518
|
+
try {
|
|
519
|
+
return { ...row, content: JSON.parse(row.content) };
|
|
520
|
+
} catch {
|
|
521
|
+
return row;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return row;
|
|
525
|
+
});
|
|
526
|
+
const cleanMessages = messagesWithParsedContent.map(({ seq_id, ...rest }) => rest);
|
|
527
|
+
const list = new agent.MessageList().add(cleanMessages, "memory");
|
|
528
|
+
return { messages: list.get.all.db() };
|
|
576
529
|
} catch (error$1) {
|
|
577
530
|
const mastraError = new error.MastraError(
|
|
578
531
|
{
|
|
579
|
-
id: "
|
|
532
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
580
533
|
domain: error.ErrorDomain.STORAGE,
|
|
581
534
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
582
535
|
details: {
|
|
583
|
-
|
|
536
|
+
messageIds: JSON.stringify(messageIds)
|
|
584
537
|
}
|
|
585
538
|
},
|
|
586
539
|
error$1
|
|
587
540
|
);
|
|
588
541
|
this.logger?.error?.(mastraError.toString());
|
|
589
|
-
this.logger?.trackException(mastraError);
|
|
590
|
-
return [];
|
|
542
|
+
this.logger?.trackException?.(mastraError);
|
|
543
|
+
return { messages: [] };
|
|
591
544
|
}
|
|
592
545
|
}
|
|
593
|
-
async
|
|
594
|
-
const { threadId,
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
546
|
+
async listMessages(args) {
|
|
547
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
548
|
+
const threadIds = Array.isArray(threadId) ? threadId : [threadId];
|
|
549
|
+
if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
|
|
550
|
+
throw new error.MastraError(
|
|
551
|
+
{
|
|
552
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
553
|
+
domain: error.ErrorDomain.STORAGE,
|
|
554
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
555
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
556
|
+
},
|
|
557
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
if (page < 0) {
|
|
561
|
+
throw new error.MastraError({
|
|
562
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_MESSAGES", "INVALID_PAGE"),
|
|
563
|
+
domain: error.ErrorDomain.STORAGE,
|
|
564
|
+
category: error.ErrorCategory.USER,
|
|
565
|
+
text: "Page number must be non-negative",
|
|
566
|
+
details: {
|
|
567
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
568
|
+
page
|
|
569
|
+
}
|
|
570
|
+
});
|
|
599
571
|
}
|
|
572
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
573
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
600
574
|
try {
|
|
601
|
-
const {
|
|
602
|
-
const
|
|
603
|
-
const
|
|
604
|
-
const
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
conditions.push("[createdAt] >= @fromDate");
|
|
619
|
-
request.input("fromDate", fromDate.toISOString());
|
|
620
|
-
}
|
|
621
|
-
if (toDate instanceof Date && !isNaN(toDate.getTime())) {
|
|
622
|
-
conditions.push("[createdAt] <= @toDate");
|
|
623
|
-
request.input("toDate", toDate.toISOString());
|
|
624
|
-
}
|
|
625
|
-
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
626
|
-
const countQuery = `SELECT COUNT(*) as total FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })} ${whereClause}`;
|
|
627
|
-
const countResult = await request.query(countQuery);
|
|
575
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
576
|
+
const orderByStatement = `ORDER BY [${field}] ${direction}, [seq_id] ${direction}`;
|
|
577
|
+
const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
|
|
578
|
+
const baseQuery = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId FROM ${tableName}`;
|
|
579
|
+
const filters = {
|
|
580
|
+
thread_id: threadIds.length === 1 ? threadIds[0] : { $in: threadIds },
|
|
581
|
+
...resourceId ? { resourceId } : {},
|
|
582
|
+
...buildDateRangeFilter(filter?.dateRange, "createdAt")
|
|
583
|
+
};
|
|
584
|
+
const { sql: actualWhereClause = "", params: whereParams } = prepareWhereClause(
|
|
585
|
+
filters);
|
|
586
|
+
const bindWhereParams = (req) => {
|
|
587
|
+
Object.entries(whereParams).forEach(([paramName, paramValue]) => req.input(paramName, paramValue));
|
|
588
|
+
};
|
|
589
|
+
const countRequest = this.pool.request();
|
|
590
|
+
bindWhereParams(countRequest);
|
|
591
|
+
const countResult = await countRequest.query(`SELECT COUNT(*) as total FROM ${tableName}${actualWhereClause}`);
|
|
628
592
|
const total = parseInt(countResult.recordset[0]?.total, 10) || 0;
|
|
629
|
-
|
|
630
|
-
const
|
|
593
|
+
const fetchBaseMessages = async () => {
|
|
594
|
+
const request = this.pool.request();
|
|
595
|
+
bindWhereParams(request);
|
|
596
|
+
if (perPageInput === false) {
|
|
597
|
+
const result2 = await request.query(`${baseQuery}${actualWhereClause} ${orderByStatement}`);
|
|
598
|
+
return result2.recordset || [];
|
|
599
|
+
}
|
|
600
|
+
request.input("offset", offset);
|
|
601
|
+
request.input("limit", perPage > 2147483647 ? sql3__default.default.BigInt : sql3__default.default.Int, perPage);
|
|
602
|
+
const result = await request.query(
|
|
603
|
+
`${baseQuery}${actualWhereClause} ${orderByStatement} OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
|
|
604
|
+
);
|
|
605
|
+
return result.recordset || [];
|
|
606
|
+
};
|
|
607
|
+
const baseRows = perPage === 0 ? [] : await fetchBaseMessages();
|
|
608
|
+
const messages = [...baseRows];
|
|
609
|
+
const seqById = /* @__PURE__ */ new Map();
|
|
610
|
+
messages.forEach((msg) => {
|
|
611
|
+
if (typeof msg.seq_id === "number") seqById.set(msg.id, msg.seq_id);
|
|
612
|
+
});
|
|
613
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
631
614
|
return {
|
|
632
|
-
messages:
|
|
633
|
-
total:
|
|
634
|
-
page
|
|
635
|
-
perPage,
|
|
615
|
+
messages: [],
|
|
616
|
+
total: 0,
|
|
617
|
+
page,
|
|
618
|
+
perPage: perPageForResponse,
|
|
636
619
|
hasMore: false
|
|
637
620
|
};
|
|
638
621
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
622
|
+
if (include?.length) {
|
|
623
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
624
|
+
const includeMessages = await this._getIncludedMessages({ include });
|
|
625
|
+
includeMessages?.forEach((msg) => {
|
|
626
|
+
if (!messageIds.has(msg.id)) {
|
|
627
|
+
messages.push(msg);
|
|
628
|
+
messageIds.add(msg.id);
|
|
629
|
+
if (typeof msg.seq_id === "number") seqById.set(msg.id, msg.seq_id);
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
const parsed = this._parseAndFormatMessages(messages, "v2");
|
|
634
|
+
const mult = direction === "ASC" ? 1 : -1;
|
|
635
|
+
const finalMessages = parsed.sort((a, b) => {
|
|
636
|
+
const aVal = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
637
|
+
const bVal = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
638
|
+
if (aVal == null || bVal == null) {
|
|
639
|
+
return aVal == null && bVal == null ? a.id.localeCompare(b.id) : aVal == null ? 1 : -1;
|
|
640
|
+
}
|
|
641
|
+
const diff = (typeof aVal === "number" && typeof bVal === "number" ? aVal - bVal : String(aVal).localeCompare(String(bVal))) * mult;
|
|
642
|
+
if (diff !== 0) return diff;
|
|
643
|
+
const seqA = seqById.get(a.id);
|
|
644
|
+
const seqB = seqById.get(b.id);
|
|
645
|
+
return seqA != null && seqB != null ? (seqA - seqB) * mult : a.id.localeCompare(b.id);
|
|
646
|
+
});
|
|
647
|
+
const threadIdSet = new Set(threadIds);
|
|
648
|
+
const returnedThreadMessageCount = finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).length;
|
|
649
|
+
const hasMore = perPageInput !== false && returnedThreadMessageCount < total && offset + perPage < total;
|
|
654
650
|
return {
|
|
655
|
-
messages:
|
|
656
|
-
total
|
|
657
|
-
page
|
|
658
|
-
perPage,
|
|
659
|
-
hasMore
|
|
651
|
+
messages: finalMessages,
|
|
652
|
+
total,
|
|
653
|
+
page,
|
|
654
|
+
perPage: perPageForResponse,
|
|
655
|
+
hasMore
|
|
660
656
|
};
|
|
661
657
|
} catch (error$1) {
|
|
662
658
|
const mastraError = new error.MastraError(
|
|
663
659
|
{
|
|
664
|
-
id: "
|
|
660
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_MESSAGES", "FAILED"),
|
|
665
661
|
domain: error.ErrorDomain.STORAGE,
|
|
666
662
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
667
663
|
details: {
|
|
668
|
-
threadId,
|
|
669
|
-
|
|
664
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
665
|
+
resourceId: resourceId ?? ""
|
|
670
666
|
}
|
|
671
667
|
},
|
|
672
668
|
error$1
|
|
673
669
|
);
|
|
674
670
|
this.logger?.error?.(mastraError.toString());
|
|
675
|
-
this.logger?.trackException(mastraError);
|
|
676
|
-
return {
|
|
671
|
+
this.logger?.trackException?.(mastraError);
|
|
672
|
+
return {
|
|
673
|
+
messages: [],
|
|
674
|
+
total: 0,
|
|
675
|
+
page,
|
|
676
|
+
perPage: perPageForResponse,
|
|
677
|
+
hasMore: false
|
|
678
|
+
};
|
|
677
679
|
}
|
|
678
680
|
}
|
|
679
|
-
async saveMessages({
|
|
680
|
-
messages
|
|
681
|
-
format
|
|
682
|
-
}) {
|
|
683
|
-
if (messages.length === 0) return messages;
|
|
681
|
+
async saveMessages({ messages }) {
|
|
682
|
+
if (messages.length === 0) return { messages: [] };
|
|
684
683
|
const threadId = messages[0]?.threadId;
|
|
685
684
|
if (!threadId) {
|
|
686
685
|
throw new error.MastraError({
|
|
687
|
-
id: "
|
|
686
|
+
id: storage.createStorageErrorId("MSSQL", "SAVE_MESSAGES", "INVALID_THREAD_ID"),
|
|
688
687
|
domain: error.ErrorDomain.STORAGE,
|
|
689
688
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
690
689
|
text: `Thread ID is required`
|
|
@@ -693,7 +692,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
693
692
|
const thread = await this.getThreadById({ threadId });
|
|
694
693
|
if (!thread) {
|
|
695
694
|
throw new error.MastraError({
|
|
696
|
-
id: "
|
|
695
|
+
id: storage.createStorageErrorId("MSSQL", "SAVE_MESSAGES", "THREAD_NOT_FOUND"),
|
|
697
696
|
domain: error.ErrorDomain.STORAGE,
|
|
698
697
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
699
698
|
text: `Thread ${threadId} not found`,
|
|
@@ -724,7 +723,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
724
723
|
"content",
|
|
725
724
|
typeof message.content === "string" ? message.content : JSON.stringify(message.content)
|
|
726
725
|
);
|
|
727
|
-
request.input("createdAt",
|
|
726
|
+
request.input("createdAt", sql3__default.default.DateTime2, message.createdAt);
|
|
728
727
|
request.input("role", message.role);
|
|
729
728
|
request.input("type", message.type || "v2");
|
|
730
729
|
request.input("resourceId", message.resourceId);
|
|
@@ -743,7 +742,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
743
742
|
await request.query(mergeSql);
|
|
744
743
|
}
|
|
745
744
|
const threadReq = transaction.request();
|
|
746
|
-
threadReq.input("updatedAt",
|
|
745
|
+
threadReq.input("updatedAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
747
746
|
threadReq.input("id", threadId);
|
|
748
747
|
await threadReq.query(`UPDATE ${tableThreads} SET [updatedAt] = @updatedAt WHERE id = @id`);
|
|
749
748
|
await transaction.commit();
|
|
@@ -762,12 +761,11 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
762
761
|
return message;
|
|
763
762
|
});
|
|
764
763
|
const list = new agent.MessageList().add(messagesWithParsedContent, "memory");
|
|
765
|
-
|
|
766
|
-
return list.get.all.v1();
|
|
764
|
+
return { messages: list.get.all.db() };
|
|
767
765
|
} catch (error$1) {
|
|
768
766
|
throw new error.MastraError(
|
|
769
767
|
{
|
|
770
|
-
id: "
|
|
768
|
+
id: storage.createStorageErrorId("MSSQL", "SAVE_MESSAGES", "FAILED"),
|
|
771
769
|
domain: error.ErrorDomain.STORAGE,
|
|
772
770
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
773
771
|
details: { threadId }
|
|
@@ -858,7 +856,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
858
856
|
await transaction.rollback();
|
|
859
857
|
throw new error.MastraError(
|
|
860
858
|
{
|
|
861
|
-
id: "
|
|
859
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_MESSAGES", "FAILED"),
|
|
862
860
|
domain: error.ErrorDomain.STORAGE,
|
|
863
861
|
category: error.ErrorCategory.THIRD_PARTY
|
|
864
862
|
},
|
|
@@ -920,7 +918,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
920
918
|
} catch (error$1) {
|
|
921
919
|
throw new error.MastraError(
|
|
922
920
|
{
|
|
923
|
-
id: "
|
|
921
|
+
id: storage.createStorageErrorId("MSSQL", "DELETE_MESSAGES", "FAILED"),
|
|
924
922
|
domain: error.ErrorDomain.STORAGE,
|
|
925
923
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
926
924
|
details: { messageIds: messageIds.join(", ") }
|
|
@@ -939,14 +937,16 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
939
937
|
return null;
|
|
940
938
|
}
|
|
941
939
|
return {
|
|
942
|
-
|
|
943
|
-
|
|
940
|
+
id: result.id,
|
|
941
|
+
createdAt: result.createdAt,
|
|
942
|
+
updatedAt: result.updatedAt,
|
|
943
|
+
workingMemory: result.workingMemory,
|
|
944
944
|
metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
|
|
945
945
|
};
|
|
946
946
|
} catch (error$1) {
|
|
947
947
|
const mastraError = new error.MastraError(
|
|
948
948
|
{
|
|
949
|
-
id: "
|
|
949
|
+
id: storage.createStorageErrorId("MSSQL", "GET_RESOURCE_BY_ID", "FAILED"),
|
|
950
950
|
domain: error.ErrorDomain.STORAGE,
|
|
951
951
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
952
952
|
details: { resourceId }
|
|
@@ -954,7 +954,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
954
954
|
error$1
|
|
955
955
|
);
|
|
956
956
|
this.logger?.error?.(mastraError.toString());
|
|
957
|
-
this.logger?.trackException(mastraError);
|
|
957
|
+
this.logger?.trackException?.(mastraError);
|
|
958
958
|
throw mastraError;
|
|
959
959
|
}
|
|
960
960
|
}
|
|
@@ -963,7 +963,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
963
963
|
tableName: storage.TABLE_RESOURCES,
|
|
964
964
|
record: {
|
|
965
965
|
...resource,
|
|
966
|
-
metadata:
|
|
966
|
+
metadata: resource.metadata
|
|
967
967
|
}
|
|
968
968
|
});
|
|
969
969
|
return resource;
|
|
@@ -1013,7 +1013,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1013
1013
|
} catch (error$1) {
|
|
1014
1014
|
const mastraError = new error.MastraError(
|
|
1015
1015
|
{
|
|
1016
|
-
id: "
|
|
1016
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_RESOURCE", "FAILED"),
|
|
1017
1017
|
domain: error.ErrorDomain.STORAGE,
|
|
1018
1018
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1019
1019
|
details: { resourceId }
|
|
@@ -1021,115 +1021,440 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1021
1021
|
error$1
|
|
1022
1022
|
);
|
|
1023
1023
|
this.logger?.error?.(mastraError.toString());
|
|
1024
|
-
this.logger?.trackException(mastraError);
|
|
1024
|
+
this.logger?.trackException?.(mastraError);
|
|
1025
1025
|
throw mastraError;
|
|
1026
1026
|
}
|
|
1027
1027
|
}
|
|
1028
1028
|
};
|
|
1029
|
-
var
|
|
1029
|
+
var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
1030
1030
|
pool;
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
case "timestamp":
|
|
1039
|
-
return "DATETIME2(7)";
|
|
1040
|
-
case "uuid":
|
|
1041
|
-
return "UNIQUEIDENTIFIER";
|
|
1042
|
-
case "jsonb":
|
|
1043
|
-
return "NVARCHAR(MAX)";
|
|
1044
|
-
case "integer":
|
|
1045
|
-
return "INT";
|
|
1046
|
-
case "bigint":
|
|
1047
|
-
return "BIGINT";
|
|
1048
|
-
case "float":
|
|
1049
|
-
return "FLOAT";
|
|
1050
|
-
default:
|
|
1051
|
-
throw new error.MastraError({
|
|
1052
|
-
id: "MASTRA_STORAGE_MSSQL_STORE_TYPE_NOT_SUPPORTED",
|
|
1053
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1054
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
constructor({ pool, schemaName }) {
|
|
1031
|
+
operations;
|
|
1032
|
+
schema;
|
|
1033
|
+
constructor({
|
|
1034
|
+
pool,
|
|
1035
|
+
operations,
|
|
1036
|
+
schema
|
|
1037
|
+
}) {
|
|
1059
1038
|
super();
|
|
1060
1039
|
this.pool = pool;
|
|
1061
|
-
this.
|
|
1062
|
-
|
|
1063
|
-
async hasColumn(table, column) {
|
|
1064
|
-
const schema = this.schemaName || "dbo";
|
|
1065
|
-
const request = this.pool.request();
|
|
1066
|
-
request.input("schema", schema);
|
|
1067
|
-
request.input("table", table);
|
|
1068
|
-
request.input("column", column);
|
|
1069
|
-
request.input("columnLower", column.toLowerCase());
|
|
1070
|
-
const result = await request.query(
|
|
1071
|
-
`SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND (COLUMN_NAME = @column OR COLUMN_NAME = @columnLower)`
|
|
1072
|
-
);
|
|
1073
|
-
return result.recordset.length > 0;
|
|
1040
|
+
this.operations = operations;
|
|
1041
|
+
this.schema = schema;
|
|
1074
1042
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
this.setupSchemaPromise = (async () => {
|
|
1081
|
-
try {
|
|
1082
|
-
const checkRequest = this.pool.request();
|
|
1083
|
-
checkRequest.input("schemaName", this.schemaName);
|
|
1084
|
-
const checkResult = await checkRequest.query(`
|
|
1085
|
-
SELECT 1 AS found FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = @schemaName
|
|
1086
|
-
`);
|
|
1087
|
-
const schemaExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1088
|
-
if (!schemaExists) {
|
|
1089
|
-
try {
|
|
1090
|
-
await this.pool.request().query(`CREATE SCHEMA [${this.schemaName}]`);
|
|
1091
|
-
this.logger?.info?.(`Schema "${this.schemaName}" created successfully`);
|
|
1092
|
-
} catch (error) {
|
|
1093
|
-
this.logger?.error?.(`Failed to create schema "${this.schemaName}"`, { error });
|
|
1094
|
-
throw new Error(
|
|
1095
|
-
`Unable to create schema "${this.schemaName}". This requires CREATE privilege on the database. Either create the schema manually or grant CREATE privilege to the user.`
|
|
1096
|
-
);
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
this.schemaSetupComplete = true;
|
|
1100
|
-
this.logger?.debug?.(`Schema "${this.schemaName}" is ready for use`);
|
|
1101
|
-
} catch (error) {
|
|
1102
|
-
this.schemaSetupComplete = void 0;
|
|
1103
|
-
this.setupSchemaPromise = null;
|
|
1104
|
-
throw error;
|
|
1105
|
-
} finally {
|
|
1106
|
-
this.setupSchemaPromise = null;
|
|
1107
|
-
}
|
|
1108
|
-
})();
|
|
1109
|
-
}
|
|
1110
|
-
await this.setupSchemaPromise;
|
|
1043
|
+
get tracingStrategy() {
|
|
1044
|
+
return {
|
|
1045
|
+
preferred: "batch-with-updates",
|
|
1046
|
+
supported: ["batch-with-updates", "insert-only"]
|
|
1047
|
+
};
|
|
1111
1048
|
}
|
|
1112
|
-
async
|
|
1049
|
+
async createSpan(span) {
|
|
1113
1050
|
try {
|
|
1114
|
-
const
|
|
1115
|
-
const
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1051
|
+
const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
|
|
1052
|
+
const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
|
|
1053
|
+
const record = {
|
|
1054
|
+
...span,
|
|
1055
|
+
startedAt,
|
|
1056
|
+
endedAt
|
|
1057
|
+
// Note: createdAt/updatedAt will be set by default values
|
|
1058
|
+
};
|
|
1059
|
+
return this.operations.insert({ tableName: storage.TABLE_SPANS, record });
|
|
1060
|
+
} catch (error$1) {
|
|
1061
|
+
throw new error.MastraError(
|
|
1062
|
+
{
|
|
1063
|
+
id: storage.createStorageErrorId("MSSQL", "CREATE_SPAN", "FAILED"),
|
|
1064
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1065
|
+
category: error.ErrorCategory.USER,
|
|
1066
|
+
details: {
|
|
1067
|
+
spanId: span.spanId,
|
|
1068
|
+
traceId: span.traceId,
|
|
1069
|
+
spanType: span.spanType,
|
|
1070
|
+
spanName: span.name
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
error$1
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
async getTrace(traceId) {
|
|
1078
|
+
try {
|
|
1079
|
+
const tableName = getTableName({
|
|
1080
|
+
indexName: storage.TABLE_SPANS,
|
|
1081
|
+
schemaName: getSchemaName(this.schema)
|
|
1082
|
+
});
|
|
1083
|
+
const request = this.pool.request();
|
|
1084
|
+
request.input("traceId", traceId);
|
|
1085
|
+
const result = await request.query(
|
|
1086
|
+
`SELECT
|
|
1087
|
+
[traceId], [spanId], [parentSpanId], [name], [scope], [spanType],
|
|
1088
|
+
[attributes], [metadata], [links], [input], [output], [error], [isEvent],
|
|
1089
|
+
[startedAt], [endedAt], [createdAt], [updatedAt]
|
|
1090
|
+
FROM ${tableName}
|
|
1091
|
+
WHERE [traceId] = @traceId
|
|
1092
|
+
ORDER BY [startedAt] DESC`
|
|
1093
|
+
);
|
|
1094
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
1095
|
+
return null;
|
|
1096
|
+
}
|
|
1097
|
+
return {
|
|
1098
|
+
traceId,
|
|
1099
|
+
spans: result.recordset.map(
|
|
1100
|
+
(span) => transformFromSqlRow({
|
|
1101
|
+
tableName: storage.TABLE_SPANS,
|
|
1102
|
+
sqlRow: span
|
|
1103
|
+
})
|
|
1104
|
+
)
|
|
1105
|
+
};
|
|
1106
|
+
} catch (error$1) {
|
|
1107
|
+
throw new error.MastraError(
|
|
1108
|
+
{
|
|
1109
|
+
id: storage.createStorageErrorId("MSSQL", "GET_TRACE", "FAILED"),
|
|
1110
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1111
|
+
category: error.ErrorCategory.USER,
|
|
1112
|
+
details: {
|
|
1113
|
+
traceId
|
|
1114
|
+
}
|
|
1115
|
+
},
|
|
1116
|
+
error$1
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
async updateSpan({
|
|
1121
|
+
spanId,
|
|
1122
|
+
traceId,
|
|
1123
|
+
updates
|
|
1124
|
+
}) {
|
|
1125
|
+
try {
|
|
1126
|
+
const data = { ...updates };
|
|
1127
|
+
if (data.endedAt instanceof Date) {
|
|
1128
|
+
data.endedAt = data.endedAt.toISOString();
|
|
1129
|
+
}
|
|
1130
|
+
if (data.startedAt instanceof Date) {
|
|
1131
|
+
data.startedAt = data.startedAt.toISOString();
|
|
1132
|
+
}
|
|
1133
|
+
await this.operations.update({
|
|
1134
|
+
tableName: storage.TABLE_SPANS,
|
|
1135
|
+
keys: { spanId, traceId },
|
|
1136
|
+
data
|
|
1137
|
+
});
|
|
1138
|
+
} catch (error$1) {
|
|
1139
|
+
throw new error.MastraError(
|
|
1140
|
+
{
|
|
1141
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_SPAN", "FAILED"),
|
|
1142
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1143
|
+
category: error.ErrorCategory.USER,
|
|
1144
|
+
details: {
|
|
1145
|
+
spanId,
|
|
1146
|
+
traceId
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
error$1
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
async getTracesPaginated({
|
|
1154
|
+
filters,
|
|
1155
|
+
pagination
|
|
1156
|
+
}) {
|
|
1157
|
+
const page = pagination?.page ?? 0;
|
|
1158
|
+
const perPage = pagination?.perPage ?? 10;
|
|
1159
|
+
const { entityId, entityType, ...actualFilters } = filters || {};
|
|
1160
|
+
const filtersWithDateRange = {
|
|
1161
|
+
...actualFilters,
|
|
1162
|
+
...buildDateRangeFilter(pagination?.dateRange, "startedAt"),
|
|
1163
|
+
parentSpanId: null
|
|
1164
|
+
// Only get root spans for traces
|
|
1165
|
+
};
|
|
1166
|
+
const whereClause = prepareWhereClause(filtersWithDateRange);
|
|
1167
|
+
let actualWhereClause = whereClause.sql;
|
|
1168
|
+
const params = { ...whereClause.params };
|
|
1169
|
+
let currentParamIndex = Object.keys(params).length + 1;
|
|
1170
|
+
if (entityId && entityType) {
|
|
1171
|
+
let name = "";
|
|
1172
|
+
if (entityType === "workflow") {
|
|
1173
|
+
name = `workflow run: '${entityId}'`;
|
|
1174
|
+
} else if (entityType === "agent") {
|
|
1175
|
+
name = `agent run: '${entityId}'`;
|
|
1176
|
+
} else {
|
|
1177
|
+
const error$1 = new error.MastraError({
|
|
1178
|
+
id: storage.createStorageErrorId("MSSQL", "GET_TRACES_PAGINATED", "INVALID_ENTITY_TYPE"),
|
|
1179
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1180
|
+
category: error.ErrorCategory.USER,
|
|
1181
|
+
details: {
|
|
1182
|
+
entityType
|
|
1183
|
+
},
|
|
1184
|
+
text: `Cannot filter by entity type: ${entityType}`
|
|
1185
|
+
});
|
|
1186
|
+
throw error$1;
|
|
1187
|
+
}
|
|
1188
|
+
const entityParam = `p${currentParamIndex++}`;
|
|
1189
|
+
if (actualWhereClause) {
|
|
1190
|
+
actualWhereClause += ` AND [name] = @${entityParam}`;
|
|
1191
|
+
} else {
|
|
1192
|
+
actualWhereClause = ` WHERE [name] = @${entityParam}`;
|
|
1193
|
+
}
|
|
1194
|
+
params[entityParam] = name;
|
|
1195
|
+
}
|
|
1196
|
+
const tableName = getTableName({
|
|
1197
|
+
indexName: storage.TABLE_SPANS,
|
|
1198
|
+
schemaName: getSchemaName(this.schema)
|
|
1199
|
+
});
|
|
1200
|
+
try {
|
|
1201
|
+
const countRequest = this.pool.request();
|
|
1202
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1203
|
+
countRequest.input(key, value);
|
|
1204
|
+
});
|
|
1205
|
+
const countResult = await countRequest.query(
|
|
1206
|
+
`SELECT COUNT(*) as count FROM ${tableName}${actualWhereClause}`
|
|
1207
|
+
);
|
|
1208
|
+
const total = countResult.recordset[0]?.count ?? 0;
|
|
1209
|
+
if (total === 0) {
|
|
1210
|
+
return {
|
|
1211
|
+
pagination: {
|
|
1212
|
+
total: 0,
|
|
1213
|
+
page,
|
|
1214
|
+
perPage,
|
|
1215
|
+
hasMore: false
|
|
1216
|
+
},
|
|
1217
|
+
spans: []
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
const dataRequest = this.pool.request();
|
|
1221
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1222
|
+
dataRequest.input(key, value);
|
|
1223
|
+
});
|
|
1224
|
+
dataRequest.input("offset", page * perPage);
|
|
1225
|
+
dataRequest.input("limit", perPage);
|
|
1226
|
+
const dataResult = await dataRequest.query(
|
|
1227
|
+
`SELECT * FROM ${tableName}${actualWhereClause} ORDER BY [startedAt] DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
|
|
1228
|
+
);
|
|
1229
|
+
const spans = dataResult.recordset.map(
|
|
1230
|
+
(row) => transformFromSqlRow({
|
|
1231
|
+
tableName: storage.TABLE_SPANS,
|
|
1232
|
+
sqlRow: row
|
|
1233
|
+
})
|
|
1234
|
+
);
|
|
1235
|
+
return {
|
|
1236
|
+
pagination: {
|
|
1237
|
+
total,
|
|
1238
|
+
page,
|
|
1239
|
+
perPage,
|
|
1240
|
+
hasMore: (page + 1) * perPage < total
|
|
1241
|
+
},
|
|
1242
|
+
spans
|
|
1243
|
+
};
|
|
1244
|
+
} catch (error$1) {
|
|
1245
|
+
throw new error.MastraError(
|
|
1246
|
+
{
|
|
1247
|
+
id: storage.createStorageErrorId("MSSQL", "GET_TRACES_PAGINATED", "FAILED"),
|
|
1248
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1249
|
+
category: error.ErrorCategory.USER
|
|
1250
|
+
},
|
|
1251
|
+
error$1
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
async batchCreateSpans(args) {
|
|
1256
|
+
if (!args.records || args.records.length === 0) {
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
try {
|
|
1260
|
+
await this.operations.batchInsert({
|
|
1261
|
+
tableName: storage.TABLE_SPANS,
|
|
1262
|
+
records: args.records.map((span) => ({
|
|
1263
|
+
...span,
|
|
1264
|
+
startedAt: span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt,
|
|
1265
|
+
endedAt: span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt
|
|
1266
|
+
}))
|
|
1267
|
+
});
|
|
1268
|
+
} catch (error$1) {
|
|
1269
|
+
throw new error.MastraError(
|
|
1270
|
+
{
|
|
1271
|
+
id: storage.createStorageErrorId("MSSQL", "BATCH_CREATE_SPANS", "FAILED"),
|
|
1272
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1273
|
+
category: error.ErrorCategory.USER,
|
|
1274
|
+
details: {
|
|
1275
|
+
count: args.records.length
|
|
1276
|
+
}
|
|
1277
|
+
},
|
|
1278
|
+
error$1
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
async batchUpdateSpans(args) {
|
|
1283
|
+
if (!args.records || args.records.length === 0) {
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
try {
|
|
1287
|
+
const updates = args.records.map(({ traceId, spanId, updates: data }) => {
|
|
1288
|
+
const processedData = { ...data };
|
|
1289
|
+
if (processedData.endedAt instanceof Date) {
|
|
1290
|
+
processedData.endedAt = processedData.endedAt.toISOString();
|
|
1291
|
+
}
|
|
1292
|
+
if (processedData.startedAt instanceof Date) {
|
|
1293
|
+
processedData.startedAt = processedData.startedAt.toISOString();
|
|
1294
|
+
}
|
|
1295
|
+
return {
|
|
1296
|
+
keys: { spanId, traceId },
|
|
1297
|
+
data: processedData
|
|
1298
|
+
};
|
|
1299
|
+
});
|
|
1300
|
+
await this.operations.batchUpdate({
|
|
1301
|
+
tableName: storage.TABLE_SPANS,
|
|
1302
|
+
updates
|
|
1303
|
+
});
|
|
1304
|
+
} catch (error$1) {
|
|
1305
|
+
throw new error.MastraError(
|
|
1306
|
+
{
|
|
1307
|
+
id: storage.createStorageErrorId("MSSQL", "BATCH_UPDATE_SPANS", "FAILED"),
|
|
1308
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1309
|
+
category: error.ErrorCategory.USER,
|
|
1310
|
+
details: {
|
|
1311
|
+
count: args.records.length
|
|
1312
|
+
}
|
|
1313
|
+
},
|
|
1314
|
+
error$1
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
async batchDeleteTraces(args) {
|
|
1319
|
+
if (!args.traceIds || args.traceIds.length === 0) {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
try {
|
|
1323
|
+
const keys = args.traceIds.map((traceId) => ({ traceId }));
|
|
1324
|
+
await this.operations.batchDelete({
|
|
1325
|
+
tableName: storage.TABLE_SPANS,
|
|
1326
|
+
keys
|
|
1327
|
+
});
|
|
1328
|
+
} catch (error$1) {
|
|
1329
|
+
throw new error.MastraError(
|
|
1330
|
+
{
|
|
1331
|
+
id: storage.createStorageErrorId("MSSQL", "BATCH_DELETE_TRACES", "FAILED"),
|
|
1332
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1333
|
+
category: error.ErrorCategory.USER,
|
|
1334
|
+
details: {
|
|
1335
|
+
count: args.traceIds.length
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1338
|
+
error$1
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
1344
|
+
pool;
|
|
1345
|
+
schemaName;
|
|
1346
|
+
setupSchemaPromise = null;
|
|
1347
|
+
schemaSetupComplete = void 0;
|
|
1348
|
+
getSqlType(type, isPrimaryKey = false, useLargeStorage = false) {
|
|
1349
|
+
switch (type) {
|
|
1350
|
+
case "text":
|
|
1351
|
+
if (useLargeStorage) {
|
|
1352
|
+
return "NVARCHAR(MAX)";
|
|
1353
|
+
}
|
|
1354
|
+
return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(400)";
|
|
1355
|
+
case "timestamp":
|
|
1356
|
+
return "DATETIME2(7)";
|
|
1357
|
+
case "uuid":
|
|
1358
|
+
return "UNIQUEIDENTIFIER";
|
|
1359
|
+
case "jsonb":
|
|
1360
|
+
return "NVARCHAR(MAX)";
|
|
1361
|
+
case "integer":
|
|
1362
|
+
return "INT";
|
|
1363
|
+
case "bigint":
|
|
1364
|
+
return "BIGINT";
|
|
1365
|
+
case "float":
|
|
1366
|
+
return "FLOAT";
|
|
1367
|
+
case "boolean":
|
|
1368
|
+
return "BIT";
|
|
1369
|
+
default:
|
|
1370
|
+
throw new error.MastraError({
|
|
1371
|
+
id: storage.createStorageErrorId("MSSQL", "TYPE", "NOT_SUPPORTED"),
|
|
1372
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1373
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
constructor({ pool, schemaName }) {
|
|
1378
|
+
super();
|
|
1379
|
+
this.pool = pool;
|
|
1380
|
+
this.schemaName = schemaName;
|
|
1381
|
+
}
|
|
1382
|
+
async hasColumn(table, column) {
|
|
1383
|
+
const schema = this.schemaName || "dbo";
|
|
1384
|
+
const request = this.pool.request();
|
|
1385
|
+
request.input("schema", schema);
|
|
1386
|
+
request.input("table", table);
|
|
1387
|
+
request.input("column", column);
|
|
1388
|
+
request.input("columnLower", column.toLowerCase());
|
|
1389
|
+
const result = await request.query(
|
|
1390
|
+
`SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND (COLUMN_NAME = @column OR COLUMN_NAME = @columnLower)`
|
|
1391
|
+
);
|
|
1392
|
+
return result.recordset.length > 0;
|
|
1393
|
+
}
|
|
1394
|
+
async setupSchema() {
|
|
1395
|
+
if (!this.schemaName || this.schemaSetupComplete) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
if (!this.setupSchemaPromise) {
|
|
1399
|
+
this.setupSchemaPromise = (async () => {
|
|
1400
|
+
try {
|
|
1401
|
+
const checkRequest = this.pool.request();
|
|
1402
|
+
checkRequest.input("schemaName", this.schemaName);
|
|
1403
|
+
const checkResult = await checkRequest.query(`
|
|
1404
|
+
SELECT 1 AS found FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = @schemaName
|
|
1405
|
+
`);
|
|
1406
|
+
const schemaExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1407
|
+
if (!schemaExists) {
|
|
1408
|
+
try {
|
|
1409
|
+
await this.pool.request().query(`CREATE SCHEMA [${this.schemaName}]`);
|
|
1410
|
+
this.logger?.info?.(`Schema "${this.schemaName}" created successfully`);
|
|
1411
|
+
} catch (error) {
|
|
1412
|
+
this.logger?.error?.(`Failed to create schema "${this.schemaName}"`, { error });
|
|
1413
|
+
throw new Error(
|
|
1414
|
+
`Unable to create schema "${this.schemaName}". This requires CREATE privilege on the database. Either create the schema manually or grant CREATE privilege to the user.`
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
this.schemaSetupComplete = true;
|
|
1419
|
+
this.logger?.debug?.(`Schema "${this.schemaName}" is ready for use`);
|
|
1420
|
+
} catch (error) {
|
|
1421
|
+
this.schemaSetupComplete = void 0;
|
|
1422
|
+
this.setupSchemaPromise = null;
|
|
1423
|
+
throw error;
|
|
1424
|
+
} finally {
|
|
1425
|
+
this.setupSchemaPromise = null;
|
|
1426
|
+
}
|
|
1427
|
+
})();
|
|
1428
|
+
}
|
|
1429
|
+
await this.setupSchemaPromise;
|
|
1430
|
+
}
|
|
1431
|
+
async insert({
|
|
1432
|
+
tableName,
|
|
1433
|
+
record,
|
|
1434
|
+
transaction
|
|
1435
|
+
}) {
|
|
1436
|
+
try {
|
|
1437
|
+
const columns = Object.keys(record);
|
|
1438
|
+
const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
1439
|
+
const paramNames = columns.map((_, i) => `@param${i}`);
|
|
1440
|
+
const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${parsedColumns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
|
|
1441
|
+
const request = transaction ? transaction.request() : this.pool.request();
|
|
1442
|
+
columns.forEach((col, i) => {
|
|
1443
|
+
const value = record[col];
|
|
1444
|
+
const preparedValue = this.prepareValue(value, col, tableName);
|
|
1445
|
+
if (preparedValue instanceof Date) {
|
|
1446
|
+
request.input(`param${i}`, sql3__default.default.DateTime2, preparedValue);
|
|
1447
|
+
} else if (preparedValue === null || preparedValue === void 0) {
|
|
1448
|
+
request.input(`param${i}`, this.getMssqlType(tableName, col), null);
|
|
1124
1449
|
} else {
|
|
1125
|
-
request.input(`param${i}`,
|
|
1450
|
+
request.input(`param${i}`, preparedValue);
|
|
1126
1451
|
}
|
|
1127
1452
|
});
|
|
1128
1453
|
await request.query(insertSql);
|
|
1129
1454
|
} catch (error$1) {
|
|
1130
1455
|
throw new error.MastraError(
|
|
1131
1456
|
{
|
|
1132
|
-
id: "
|
|
1457
|
+
id: storage.createStorageErrorId("MSSQL", "INSERT", "FAILED"),
|
|
1133
1458
|
domain: error.ErrorDomain.STORAGE,
|
|
1134
1459
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1135
1460
|
details: {
|
|
@@ -1146,7 +1471,7 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1146
1471
|
try {
|
|
1147
1472
|
await this.pool.request().query(`TRUNCATE TABLE ${fullTableName}`);
|
|
1148
1473
|
} catch (truncateError) {
|
|
1149
|
-
if (truncateError
|
|
1474
|
+
if (truncateError?.number === 4712) {
|
|
1150
1475
|
await this.pool.request().query(`DELETE FROM ${fullTableName}`);
|
|
1151
1476
|
} else {
|
|
1152
1477
|
throw truncateError;
|
|
@@ -1155,7 +1480,7 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1155
1480
|
} catch (error$1) {
|
|
1156
1481
|
throw new error.MastraError(
|
|
1157
1482
|
{
|
|
1158
|
-
id: "
|
|
1483
|
+
id: storage.createStorageErrorId("MSSQL", "CLEAR_TABLE", "FAILED"),
|
|
1159
1484
|
domain: error.ErrorDomain.STORAGE,
|
|
1160
1485
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1161
1486
|
details: {
|
|
@@ -1169,9 +1494,11 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1169
1494
|
getDefaultValue(type) {
|
|
1170
1495
|
switch (type) {
|
|
1171
1496
|
case "timestamp":
|
|
1172
|
-
return "DEFAULT
|
|
1497
|
+
return "DEFAULT SYSUTCDATETIME()";
|
|
1173
1498
|
case "jsonb":
|
|
1174
1499
|
return "DEFAULT N'{}'";
|
|
1500
|
+
case "boolean":
|
|
1501
|
+
return "DEFAULT 0";
|
|
1175
1502
|
default:
|
|
1176
1503
|
return super.getDefaultValue(type);
|
|
1177
1504
|
}
|
|
@@ -1182,13 +1509,29 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1182
1509
|
}) {
|
|
1183
1510
|
try {
|
|
1184
1511
|
const uniqueConstraintColumns = tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? ["workflow_name", "run_id"] : [];
|
|
1512
|
+
const largeDataColumns = [
|
|
1513
|
+
"workingMemory",
|
|
1514
|
+
"snapshot",
|
|
1515
|
+
"metadata",
|
|
1516
|
+
"content",
|
|
1517
|
+
// messages.content - can be very long conversation content
|
|
1518
|
+
"input",
|
|
1519
|
+
// evals.input - test input data
|
|
1520
|
+
"output",
|
|
1521
|
+
// evals.output - test output data
|
|
1522
|
+
"instructions",
|
|
1523
|
+
// evals.instructions - evaluation instructions
|
|
1524
|
+
"other"
|
|
1525
|
+
// traces.other - additional trace data
|
|
1526
|
+
];
|
|
1185
1527
|
const columns = Object.entries(schema).map(([name, def]) => {
|
|
1186
1528
|
const parsedName = utils.parseSqlIdentifier(name, "column name");
|
|
1187
1529
|
const constraints = [];
|
|
1188
1530
|
if (def.primaryKey) constraints.push("PRIMARY KEY");
|
|
1189
1531
|
if (!def.nullable) constraints.push("NOT NULL");
|
|
1190
1532
|
const isIndexed = !!def.primaryKey || uniqueConstraintColumns.includes(name);
|
|
1191
|
-
|
|
1533
|
+
const useLargeStorage = largeDataColumns.includes(name);
|
|
1534
|
+
return `[${parsedName}] ${this.getSqlType(def.type, isIndexed, useLargeStorage)} ${constraints.join(" ")}`.trim();
|
|
1192
1535
|
}).join(",\n");
|
|
1193
1536
|
if (this.schemaName) {
|
|
1194
1537
|
await this.setupSchema();
|
|
@@ -1240,7 +1583,7 @@ ${columns}
|
|
|
1240
1583
|
} catch (error$1) {
|
|
1241
1584
|
throw new error.MastraError(
|
|
1242
1585
|
{
|
|
1243
|
-
id: "
|
|
1586
|
+
id: storage.createStorageErrorId("MSSQL", "CREATE_TABLE", "FAILED"),
|
|
1244
1587
|
domain: error.ErrorDomain.STORAGE,
|
|
1245
1588
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1246
1589
|
details: {
|
|
@@ -1275,7 +1618,19 @@ ${columns}
|
|
|
1275
1618
|
const columnExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1276
1619
|
if (!columnExists) {
|
|
1277
1620
|
const columnDef = schema[columnName];
|
|
1278
|
-
const
|
|
1621
|
+
const largeDataColumns = [
|
|
1622
|
+
"workingMemory",
|
|
1623
|
+
"snapshot",
|
|
1624
|
+
"metadata",
|
|
1625
|
+
"content",
|
|
1626
|
+
"input",
|
|
1627
|
+
"output",
|
|
1628
|
+
"instructions",
|
|
1629
|
+
"other"
|
|
1630
|
+
];
|
|
1631
|
+
const useLargeStorage = largeDataColumns.includes(columnName);
|
|
1632
|
+
const isIndexed = !!columnDef.primaryKey;
|
|
1633
|
+
const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage);
|
|
1279
1634
|
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
1280
1635
|
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
1281
1636
|
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
@@ -1288,7 +1643,7 @@ ${columns}
|
|
|
1288
1643
|
} catch (error$1) {
|
|
1289
1644
|
throw new error.MastraError(
|
|
1290
1645
|
{
|
|
1291
|
-
id: "
|
|
1646
|
+
id: storage.createStorageErrorId("MSSQL", "ALTER_TABLE", "FAILED"),
|
|
1292
1647
|
domain: error.ErrorDomain.STORAGE,
|
|
1293
1648
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1294
1649
|
details: {
|
|
@@ -1303,13 +1658,17 @@ ${columns}
|
|
|
1303
1658
|
try {
|
|
1304
1659
|
const keyEntries = Object.entries(keys).map(([key, value]) => [utils.parseSqlIdentifier(key, "column name"), value]);
|
|
1305
1660
|
const conditions = keyEntries.map(([key], i) => `[${key}] = @param${i}`).join(" AND ");
|
|
1306
|
-
const
|
|
1307
|
-
const sql7 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
|
|
1661
|
+
const sql5 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
|
|
1308
1662
|
const request = this.pool.request();
|
|
1309
|
-
|
|
1310
|
-
|
|
1663
|
+
keyEntries.forEach(([key, value], i) => {
|
|
1664
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1665
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1666
|
+
request.input(`param${i}`, this.getMssqlType(tableName, key), null);
|
|
1667
|
+
} else {
|
|
1668
|
+
request.input(`param${i}`, preparedValue);
|
|
1669
|
+
}
|
|
1311
1670
|
});
|
|
1312
|
-
const resultSet = await request.query(
|
|
1671
|
+
const resultSet = await request.query(sql5);
|
|
1313
1672
|
const result = resultSet.recordset[0] || null;
|
|
1314
1673
|
if (!result) {
|
|
1315
1674
|
return null;
|
|
@@ -1325,7 +1684,7 @@ ${columns}
|
|
|
1325
1684
|
} catch (error$1) {
|
|
1326
1685
|
throw new error.MastraError(
|
|
1327
1686
|
{
|
|
1328
|
-
id: "
|
|
1687
|
+
id: storage.createStorageErrorId("MSSQL", "LOAD", "FAILED"),
|
|
1329
1688
|
domain: error.ErrorDomain.STORAGE,
|
|
1330
1689
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1331
1690
|
details: {
|
|
@@ -1341,14 +1700,14 @@ ${columns}
|
|
|
1341
1700
|
try {
|
|
1342
1701
|
await transaction.begin();
|
|
1343
1702
|
for (const record of records) {
|
|
1344
|
-
await this.insert({ tableName, record });
|
|
1703
|
+
await this.insert({ tableName, record, transaction });
|
|
1345
1704
|
}
|
|
1346
1705
|
await transaction.commit();
|
|
1347
1706
|
} catch (error$1) {
|
|
1348
1707
|
await transaction.rollback();
|
|
1349
1708
|
throw new error.MastraError(
|
|
1350
1709
|
{
|
|
1351
|
-
id: "
|
|
1710
|
+
id: storage.createStorageErrorId("MSSQL", "BATCH_INSERT", "FAILED"),
|
|
1352
1711
|
domain: error.ErrorDomain.STORAGE,
|
|
1353
1712
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1354
1713
|
details: {
|
|
@@ -1367,7 +1726,7 @@ ${columns}
|
|
|
1367
1726
|
} catch (error$1) {
|
|
1368
1727
|
throw new error.MastraError(
|
|
1369
1728
|
{
|
|
1370
|
-
id: "
|
|
1729
|
+
id: storage.createStorageErrorId("MSSQL", "DROP_TABLE", "FAILED"),
|
|
1371
1730
|
domain: error.ErrorDomain.STORAGE,
|
|
1372
1731
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1373
1732
|
details: {
|
|
@@ -1378,29 +1737,568 @@ ${columns}
|
|
|
1378
1737
|
);
|
|
1379
1738
|
}
|
|
1380
1739
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1740
|
+
/**
|
|
1741
|
+
* Prepares a value for database operations, handling Date objects and JSON serialization
|
|
1742
|
+
*/
|
|
1743
|
+
prepareValue(value, columnName, tableName) {
|
|
1744
|
+
if (value === null || value === void 0) {
|
|
1745
|
+
return value;
|
|
1746
|
+
}
|
|
1747
|
+
if (value instanceof Date) {
|
|
1748
|
+
return value;
|
|
1749
|
+
}
|
|
1750
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
1751
|
+
const columnSchema = schema?.[columnName];
|
|
1752
|
+
if (columnSchema?.type === "boolean") {
|
|
1753
|
+
return value ? 1 : 0;
|
|
1754
|
+
}
|
|
1755
|
+
if (columnSchema?.type === "jsonb") {
|
|
1756
|
+
if (typeof value === "string") {
|
|
1757
|
+
const trimmed = value.trim();
|
|
1758
|
+
if (trimmed.length > 0) {
|
|
1759
|
+
try {
|
|
1760
|
+
JSON.parse(trimmed);
|
|
1761
|
+
return trimmed;
|
|
1762
|
+
} catch {
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
return JSON.stringify(value);
|
|
1766
|
+
}
|
|
1767
|
+
if (typeof value === "bigint") {
|
|
1768
|
+
return value.toString();
|
|
1769
|
+
}
|
|
1770
|
+
return JSON.stringify(value);
|
|
1771
|
+
}
|
|
1772
|
+
if (typeof value === "object") {
|
|
1773
|
+
return JSON.stringify(value);
|
|
1774
|
+
}
|
|
1775
|
+
return value;
|
|
1387
1776
|
}
|
|
1388
|
-
|
|
1777
|
+
/**
|
|
1778
|
+
* Maps TABLE_SCHEMAS types to mssql param types (used when value is null)
|
|
1779
|
+
*/
|
|
1780
|
+
getMssqlType(tableName, columnName) {
|
|
1781
|
+
const col = storage.TABLE_SCHEMAS[tableName]?.[columnName];
|
|
1782
|
+
switch (col?.type) {
|
|
1783
|
+
case "text":
|
|
1784
|
+
return sql3__default.default.NVarChar;
|
|
1785
|
+
case "timestamp":
|
|
1786
|
+
return sql3__default.default.DateTime2;
|
|
1787
|
+
case "uuid":
|
|
1788
|
+
return sql3__default.default.UniqueIdentifier;
|
|
1789
|
+
case "jsonb":
|
|
1790
|
+
return sql3__default.default.NVarChar;
|
|
1791
|
+
case "integer":
|
|
1792
|
+
return sql3__default.default.Int;
|
|
1793
|
+
case "bigint":
|
|
1794
|
+
return sql3__default.default.BigInt;
|
|
1795
|
+
case "float":
|
|
1796
|
+
return sql3__default.default.Float;
|
|
1797
|
+
case "boolean":
|
|
1798
|
+
return sql3__default.default.Bit;
|
|
1799
|
+
default:
|
|
1800
|
+
return sql3__default.default.NVarChar;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
/**
|
|
1804
|
+
* Update a single record in the database
|
|
1805
|
+
*/
|
|
1806
|
+
async update({
|
|
1807
|
+
tableName,
|
|
1808
|
+
keys,
|
|
1809
|
+
data,
|
|
1810
|
+
transaction
|
|
1811
|
+
}) {
|
|
1812
|
+
try {
|
|
1813
|
+
if (!data || Object.keys(data).length === 0) {
|
|
1814
|
+
throw new error.MastraError({
|
|
1815
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE", "EMPTY_DATA"),
|
|
1816
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1817
|
+
category: error.ErrorCategory.USER,
|
|
1818
|
+
text: "Cannot update with empty data payload"
|
|
1819
|
+
});
|
|
1820
|
+
}
|
|
1821
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
1822
|
+
throw new error.MastraError({
|
|
1823
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE", "EMPTY_KEYS"),
|
|
1824
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1825
|
+
category: error.ErrorCategory.USER,
|
|
1826
|
+
text: "Cannot update without keys to identify records"
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
const setClauses = [];
|
|
1830
|
+
const request = transaction ? transaction.request() : this.pool.request();
|
|
1831
|
+
let paramIndex = 0;
|
|
1832
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
1833
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1834
|
+
const paramName = `set${paramIndex++}`;
|
|
1835
|
+
setClauses.push(`[${parsedKey}] = @${paramName}`);
|
|
1836
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1837
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1838
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1839
|
+
} else {
|
|
1840
|
+
request.input(paramName, preparedValue);
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1843
|
+
const whereConditions = [];
|
|
1844
|
+
Object.entries(keys).forEach(([key, value]) => {
|
|
1845
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1846
|
+
const paramName = `where${paramIndex++}`;
|
|
1847
|
+
whereConditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1848
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1849
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1850
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1851
|
+
} else {
|
|
1852
|
+
request.input(paramName, preparedValue);
|
|
1853
|
+
}
|
|
1854
|
+
});
|
|
1855
|
+
const tableName_ = getTableName({
|
|
1856
|
+
indexName: tableName,
|
|
1857
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1858
|
+
});
|
|
1859
|
+
const updateSql = `UPDATE ${tableName_} SET ${setClauses.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
|
|
1860
|
+
await request.query(updateSql);
|
|
1861
|
+
} catch (error$1) {
|
|
1862
|
+
throw new error.MastraError(
|
|
1863
|
+
{
|
|
1864
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE", "FAILED"),
|
|
1865
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1866
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1867
|
+
details: {
|
|
1868
|
+
tableName
|
|
1869
|
+
}
|
|
1870
|
+
},
|
|
1871
|
+
error$1
|
|
1872
|
+
);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Update multiple records in a single batch transaction
|
|
1877
|
+
*/
|
|
1878
|
+
async batchUpdate({
|
|
1879
|
+
tableName,
|
|
1880
|
+
updates
|
|
1881
|
+
}) {
|
|
1882
|
+
const transaction = this.pool.transaction();
|
|
1883
|
+
try {
|
|
1884
|
+
await transaction.begin();
|
|
1885
|
+
for (const { keys, data } of updates) {
|
|
1886
|
+
await this.update({ tableName, keys, data, transaction });
|
|
1887
|
+
}
|
|
1888
|
+
await transaction.commit();
|
|
1889
|
+
} catch (error$1) {
|
|
1890
|
+
await transaction.rollback();
|
|
1891
|
+
throw new error.MastraError(
|
|
1892
|
+
{
|
|
1893
|
+
id: storage.createStorageErrorId("MSSQL", "BATCH_UPDATE", "FAILED"),
|
|
1894
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1895
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1896
|
+
details: {
|
|
1897
|
+
tableName,
|
|
1898
|
+
numberOfRecords: updates.length
|
|
1899
|
+
}
|
|
1900
|
+
},
|
|
1901
|
+
error$1
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
/**
|
|
1906
|
+
* Delete multiple records by keys
|
|
1907
|
+
*/
|
|
1908
|
+
async batchDelete({ tableName, keys }) {
|
|
1909
|
+
if (keys.length === 0) {
|
|
1910
|
+
return;
|
|
1911
|
+
}
|
|
1912
|
+
const tableName_ = getTableName({
|
|
1913
|
+
indexName: tableName,
|
|
1914
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1915
|
+
});
|
|
1916
|
+
const transaction = this.pool.transaction();
|
|
1917
|
+
try {
|
|
1918
|
+
await transaction.begin();
|
|
1919
|
+
for (const keySet of keys) {
|
|
1920
|
+
const conditions = [];
|
|
1921
|
+
const request = transaction.request();
|
|
1922
|
+
let paramIndex = 0;
|
|
1923
|
+
Object.entries(keySet).forEach(([key, value]) => {
|
|
1924
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1925
|
+
const paramName = `p${paramIndex++}`;
|
|
1926
|
+
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1927
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1928
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1929
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1930
|
+
} else {
|
|
1931
|
+
request.input(paramName, preparedValue);
|
|
1932
|
+
}
|
|
1933
|
+
});
|
|
1934
|
+
const deleteSql = `DELETE FROM ${tableName_} WHERE ${conditions.join(" AND ")}`;
|
|
1935
|
+
await request.query(deleteSql);
|
|
1936
|
+
}
|
|
1937
|
+
await transaction.commit();
|
|
1938
|
+
} catch (error$1) {
|
|
1939
|
+
await transaction.rollback();
|
|
1940
|
+
throw new error.MastraError(
|
|
1941
|
+
{
|
|
1942
|
+
id: storage.createStorageErrorId("MSSQL", "BATCH_DELETE", "FAILED"),
|
|
1943
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1944
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1945
|
+
details: {
|
|
1946
|
+
tableName,
|
|
1947
|
+
numberOfRecords: keys.length
|
|
1948
|
+
}
|
|
1949
|
+
},
|
|
1950
|
+
error$1
|
|
1951
|
+
);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
/**
|
|
1955
|
+
* Create a new index on a table
|
|
1956
|
+
*/
|
|
1957
|
+
async createIndex(options) {
|
|
1958
|
+
try {
|
|
1959
|
+
const { name, table, columns, unique = false, where } = options;
|
|
1960
|
+
const schemaName = this.schemaName || "dbo";
|
|
1961
|
+
const fullTableName = getTableName({
|
|
1962
|
+
indexName: table,
|
|
1963
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1964
|
+
});
|
|
1965
|
+
const indexNameSafe = utils.parseSqlIdentifier(name, "index name");
|
|
1966
|
+
const checkRequest = this.pool.request();
|
|
1967
|
+
checkRequest.input("indexName", indexNameSafe);
|
|
1968
|
+
checkRequest.input("schemaName", schemaName);
|
|
1969
|
+
checkRequest.input("tableName", table);
|
|
1970
|
+
const indexExists = await checkRequest.query(`
|
|
1971
|
+
SELECT 1 as found
|
|
1972
|
+
FROM sys.indexes i
|
|
1973
|
+
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
1974
|
+
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
1975
|
+
WHERE i.name = @indexName
|
|
1976
|
+
AND s.name = @schemaName
|
|
1977
|
+
AND t.name = @tableName
|
|
1978
|
+
`);
|
|
1979
|
+
if (indexExists.recordset && indexExists.recordset.length > 0) {
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
const uniqueStr = unique ? "UNIQUE " : "";
|
|
1983
|
+
const columnsStr = columns.map((col) => {
|
|
1984
|
+
if (col.includes(" DESC") || col.includes(" ASC")) {
|
|
1985
|
+
const [colName, ...modifiers] = col.split(" ");
|
|
1986
|
+
if (!colName) {
|
|
1987
|
+
throw new Error(`Invalid column specification: ${col}`);
|
|
1988
|
+
}
|
|
1989
|
+
return `[${utils.parseSqlIdentifier(colName, "column name")}] ${modifiers.join(" ")}`;
|
|
1990
|
+
}
|
|
1991
|
+
return `[${utils.parseSqlIdentifier(col, "column name")}]`;
|
|
1992
|
+
}).join(", ");
|
|
1993
|
+
const whereStr = where ? ` WHERE ${where}` : "";
|
|
1994
|
+
const createIndexSql = `CREATE ${uniqueStr}INDEX [${indexNameSafe}] ON ${fullTableName} (${columnsStr})${whereStr}`;
|
|
1995
|
+
await this.pool.request().query(createIndexSql);
|
|
1996
|
+
} catch (error$1) {
|
|
1997
|
+
throw new error.MastraError(
|
|
1998
|
+
{
|
|
1999
|
+
id: storage.createStorageErrorId("MSSQL", "INDEX_CREATE", "FAILED"),
|
|
2000
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2001
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2002
|
+
details: {
|
|
2003
|
+
indexName: options.name,
|
|
2004
|
+
tableName: options.table
|
|
2005
|
+
}
|
|
2006
|
+
},
|
|
2007
|
+
error$1
|
|
2008
|
+
);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
/**
|
|
2012
|
+
* Drop an existing index
|
|
2013
|
+
*/
|
|
2014
|
+
async dropIndex(indexName) {
|
|
2015
|
+
try {
|
|
2016
|
+
const schemaName = this.schemaName || "dbo";
|
|
2017
|
+
const indexNameSafe = utils.parseSqlIdentifier(indexName, "index name");
|
|
2018
|
+
const checkRequest = this.pool.request();
|
|
2019
|
+
checkRequest.input("indexName", indexNameSafe);
|
|
2020
|
+
checkRequest.input("schemaName", schemaName);
|
|
2021
|
+
const result = await checkRequest.query(`
|
|
2022
|
+
SELECT t.name as table_name
|
|
2023
|
+
FROM sys.indexes i
|
|
2024
|
+
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
2025
|
+
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
2026
|
+
WHERE i.name = @indexName
|
|
2027
|
+
AND s.name = @schemaName
|
|
2028
|
+
`);
|
|
2029
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
if (result.recordset.length > 1) {
|
|
2033
|
+
const tables = result.recordset.map((r) => r.table_name).join(", ");
|
|
2034
|
+
throw new error.MastraError({
|
|
2035
|
+
id: storage.createStorageErrorId("MSSQL", "INDEX", "AMBIGUOUS"),
|
|
2036
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2037
|
+
category: error.ErrorCategory.USER,
|
|
2038
|
+
text: `Index "${indexNameSafe}" exists on multiple tables (${tables}) in schema "${schemaName}". Please drop indexes manually or ensure unique index names.`
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
const tableName = result.recordset[0].table_name;
|
|
2042
|
+
const fullTableName = getTableName({
|
|
2043
|
+
indexName: tableName,
|
|
2044
|
+
schemaName: getSchemaName(this.schemaName)
|
|
2045
|
+
});
|
|
2046
|
+
const dropSql = `DROP INDEX [${indexNameSafe}] ON ${fullTableName}`;
|
|
2047
|
+
await this.pool.request().query(dropSql);
|
|
2048
|
+
} catch (error$1) {
|
|
2049
|
+
throw new error.MastraError(
|
|
2050
|
+
{
|
|
2051
|
+
id: storage.createStorageErrorId("MSSQL", "INDEX_DROP", "FAILED"),
|
|
2052
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2053
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2054
|
+
details: {
|
|
2055
|
+
indexName
|
|
2056
|
+
}
|
|
2057
|
+
},
|
|
2058
|
+
error$1
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
/**
|
|
2063
|
+
* List indexes for a specific table or all tables
|
|
2064
|
+
*/
|
|
2065
|
+
async listIndexes(tableName) {
|
|
2066
|
+
try {
|
|
2067
|
+
const schemaName = this.schemaName || "dbo";
|
|
2068
|
+
let query;
|
|
2069
|
+
const request = this.pool.request();
|
|
2070
|
+
request.input("schemaName", schemaName);
|
|
2071
|
+
if (tableName) {
|
|
2072
|
+
query = `
|
|
2073
|
+
SELECT
|
|
2074
|
+
i.name as name,
|
|
2075
|
+
o.name as [table],
|
|
2076
|
+
i.is_unique as is_unique,
|
|
2077
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
|
|
2078
|
+
FROM sys.indexes i
|
|
2079
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2080
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2081
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2082
|
+
WHERE sch.name = @schemaName
|
|
2083
|
+
AND o.name = @tableName
|
|
2084
|
+
AND i.name IS NOT NULL
|
|
2085
|
+
GROUP BY i.name, o.name, i.is_unique
|
|
2086
|
+
`;
|
|
2087
|
+
request.input("tableName", tableName);
|
|
2088
|
+
} else {
|
|
2089
|
+
query = `
|
|
2090
|
+
SELECT
|
|
2091
|
+
i.name as name,
|
|
2092
|
+
o.name as [table],
|
|
2093
|
+
i.is_unique as is_unique,
|
|
2094
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
|
|
2095
|
+
FROM sys.indexes i
|
|
2096
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2097
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2098
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2099
|
+
WHERE sch.name = @schemaName
|
|
2100
|
+
AND i.name IS NOT NULL
|
|
2101
|
+
GROUP BY i.name, o.name, i.is_unique
|
|
2102
|
+
`;
|
|
2103
|
+
}
|
|
2104
|
+
const result = await request.query(query);
|
|
2105
|
+
const indexes = [];
|
|
2106
|
+
for (const row of result.recordset) {
|
|
2107
|
+
const colRequest = this.pool.request();
|
|
2108
|
+
colRequest.input("indexName", row.name);
|
|
2109
|
+
colRequest.input("schemaName", schemaName);
|
|
2110
|
+
const colResult = await colRequest.query(`
|
|
2111
|
+
SELECT c.name as column_name
|
|
2112
|
+
FROM sys.indexes i
|
|
2113
|
+
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
2114
|
+
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
2115
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2116
|
+
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
2117
|
+
WHERE i.name = @indexName
|
|
2118
|
+
AND s.name = @schemaName
|
|
2119
|
+
ORDER BY ic.key_ordinal
|
|
2120
|
+
`);
|
|
2121
|
+
indexes.push({
|
|
2122
|
+
name: row.name,
|
|
2123
|
+
table: row.table,
|
|
2124
|
+
columns: colResult.recordset.map((c) => c.column_name),
|
|
2125
|
+
unique: row.is_unique || false,
|
|
2126
|
+
size: row.size || "0 MB",
|
|
2127
|
+
definition: ""
|
|
2128
|
+
// MSSQL doesn't store definition like PG
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
return indexes;
|
|
2132
|
+
} catch (error$1) {
|
|
2133
|
+
throw new error.MastraError(
|
|
2134
|
+
{
|
|
2135
|
+
id: storage.createStorageErrorId("MSSQL", "INDEX_LIST", "FAILED"),
|
|
2136
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2137
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2138
|
+
details: tableName ? {
|
|
2139
|
+
tableName
|
|
2140
|
+
} : {}
|
|
2141
|
+
},
|
|
2142
|
+
error$1
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Get detailed statistics for a specific index
|
|
2148
|
+
*/
|
|
2149
|
+
async describeIndex(indexName) {
|
|
2150
|
+
try {
|
|
2151
|
+
const schemaName = this.schemaName || "dbo";
|
|
2152
|
+
const request = this.pool.request();
|
|
2153
|
+
request.input("indexName", indexName);
|
|
2154
|
+
request.input("schemaName", schemaName);
|
|
2155
|
+
const query = `
|
|
2156
|
+
SELECT
|
|
2157
|
+
i.name as name,
|
|
2158
|
+
o.name as [table],
|
|
2159
|
+
i.is_unique as is_unique,
|
|
2160
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size,
|
|
2161
|
+
i.type_desc as method,
|
|
2162
|
+
ISNULL(us.user_scans, 0) as scans,
|
|
2163
|
+
ISNULL(us.user_seeks + us.user_scans, 0) as tuples_read,
|
|
2164
|
+
ISNULL(us.user_lookups, 0) as tuples_fetched
|
|
2165
|
+
FROM sys.indexes i
|
|
2166
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2167
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2168
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2169
|
+
LEFT JOIN sys.dm_db_index_usage_stats us ON i.object_id = us.object_id AND i.index_id = us.index_id
|
|
2170
|
+
WHERE i.name = @indexName
|
|
2171
|
+
AND sch.name = @schemaName
|
|
2172
|
+
GROUP BY i.name, o.name, i.is_unique, i.type_desc, us.user_seeks, us.user_scans, us.user_lookups
|
|
2173
|
+
`;
|
|
2174
|
+
const result = await request.query(query);
|
|
2175
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2176
|
+
throw new Error(`Index "${indexName}" not found in schema "${schemaName}"`);
|
|
2177
|
+
}
|
|
2178
|
+
const row = result.recordset[0];
|
|
2179
|
+
const colRequest = this.pool.request();
|
|
2180
|
+
colRequest.input("indexName", indexName);
|
|
2181
|
+
colRequest.input("schemaName", schemaName);
|
|
2182
|
+
const colResult = await colRequest.query(`
|
|
2183
|
+
SELECT c.name as column_name
|
|
2184
|
+
FROM sys.indexes i
|
|
2185
|
+
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
2186
|
+
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
2187
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2188
|
+
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
2189
|
+
WHERE i.name = @indexName
|
|
2190
|
+
AND s.name = @schemaName
|
|
2191
|
+
ORDER BY ic.key_ordinal
|
|
2192
|
+
`);
|
|
2193
|
+
return {
|
|
2194
|
+
name: row.name,
|
|
2195
|
+
table: row.table,
|
|
2196
|
+
columns: colResult.recordset.map((c) => c.column_name),
|
|
2197
|
+
unique: row.is_unique || false,
|
|
2198
|
+
size: row.size || "0 MB",
|
|
2199
|
+
definition: "",
|
|
2200
|
+
method: row.method?.toLowerCase() || "nonclustered",
|
|
2201
|
+
scans: Number(row.scans) || 0,
|
|
2202
|
+
tuples_read: Number(row.tuples_read) || 0,
|
|
2203
|
+
tuples_fetched: Number(row.tuples_fetched) || 0
|
|
2204
|
+
};
|
|
2205
|
+
} catch (error$1) {
|
|
2206
|
+
throw new error.MastraError(
|
|
2207
|
+
{
|
|
2208
|
+
id: storage.createStorageErrorId("MSSQL", "INDEX_DESCRIBE", "FAILED"),
|
|
2209
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2210
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2211
|
+
details: {
|
|
2212
|
+
indexName
|
|
2213
|
+
}
|
|
2214
|
+
},
|
|
2215
|
+
error$1
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Returns definitions for automatic performance indexes
|
|
2221
|
+
* IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
|
|
2222
|
+
* NOTE: Using NVARCHAR(400) for text columns (800 bytes) leaves room for composite indexes
|
|
2223
|
+
*/
|
|
2224
|
+
getAutomaticIndexDefinitions() {
|
|
2225
|
+
const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
|
|
2226
|
+
return [
|
|
2227
|
+
// Composite indexes for optimal filtering + sorting performance
|
|
2228
|
+
// NVARCHAR(400) = 800 bytes, plus BIGINT (8 bytes) = 808 bytes total (under 900-byte limit)
|
|
2229
|
+
{
|
|
2230
|
+
name: `${schemaPrefix}mastra_threads_resourceid_seqid_idx`,
|
|
2231
|
+
table: storage.TABLE_THREADS,
|
|
2232
|
+
columns: ["resourceId", "seq_id DESC"]
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
name: `${schemaPrefix}mastra_messages_thread_id_seqid_idx`,
|
|
2236
|
+
table: storage.TABLE_MESSAGES,
|
|
2237
|
+
columns: ["thread_id", "seq_id DESC"]
|
|
2238
|
+
},
|
|
2239
|
+
{
|
|
2240
|
+
name: `${schemaPrefix}mastra_traces_name_seqid_idx`,
|
|
2241
|
+
table: storage.TABLE_TRACES,
|
|
2242
|
+
columns: ["name", "seq_id DESC"]
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
name: `${schemaPrefix}mastra_scores_trace_id_span_id_seqid_idx`,
|
|
2246
|
+
table: storage.TABLE_SCORERS,
|
|
2247
|
+
columns: ["traceId", "spanId", "seq_id DESC"]
|
|
2248
|
+
},
|
|
2249
|
+
// Spans indexes for optimal trace querying
|
|
2250
|
+
{
|
|
2251
|
+
name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
|
|
2252
|
+
table: storage.TABLE_SPANS,
|
|
2253
|
+
columns: ["traceId", "startedAt DESC"]
|
|
2254
|
+
},
|
|
2255
|
+
{
|
|
2256
|
+
name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
|
|
2257
|
+
table: storage.TABLE_SPANS,
|
|
2258
|
+
columns: ["parentSpanId", "startedAt DESC"]
|
|
2259
|
+
},
|
|
2260
|
+
{
|
|
2261
|
+
name: `${schemaPrefix}mastra_ai_spans_name_idx`,
|
|
2262
|
+
table: storage.TABLE_SPANS,
|
|
2263
|
+
columns: ["name"]
|
|
2264
|
+
},
|
|
2265
|
+
{
|
|
2266
|
+
name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
|
|
2267
|
+
table: storage.TABLE_SPANS,
|
|
2268
|
+
columns: ["spanType", "startedAt DESC"]
|
|
2269
|
+
}
|
|
2270
|
+
];
|
|
2271
|
+
}
|
|
2272
|
+
/**
|
|
2273
|
+
* Creates automatic indexes for optimal query performance
|
|
2274
|
+
* Uses getAutomaticIndexDefinitions() to determine which indexes to create
|
|
2275
|
+
*/
|
|
2276
|
+
async createAutomaticIndexes() {
|
|
2277
|
+
try {
|
|
2278
|
+
const indexes = this.getAutomaticIndexDefinitions();
|
|
2279
|
+
for (const indexOptions of indexes) {
|
|
2280
|
+
try {
|
|
2281
|
+
await this.createIndex(indexOptions);
|
|
2282
|
+
} catch (error) {
|
|
2283
|
+
this.logger?.warn?.(`Failed to create index ${indexOptions.name}:`, error);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
} catch (error$1) {
|
|
2287
|
+
throw new error.MastraError(
|
|
2288
|
+
{
|
|
2289
|
+
id: storage.createStorageErrorId("MSSQL", "CREATE_PERFORMANCE_INDEXES", "FAILED"),
|
|
2290
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2291
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
2292
|
+
},
|
|
2293
|
+
error$1
|
|
2294
|
+
);
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
1389
2298
|
function transformScoreRow(row) {
|
|
1390
|
-
return {
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
scorer: parseJSON(row.scorer),
|
|
1394
|
-
preprocessStepResult: parseJSON(row.preprocessStepResult),
|
|
1395
|
-
analyzeStepResult: parseJSON(row.analyzeStepResult),
|
|
1396
|
-
metadata: parseJSON(row.metadata),
|
|
1397
|
-
output: parseJSON(row.output),
|
|
1398
|
-
additionalContext: parseJSON(row.additionalContext),
|
|
1399
|
-
runtimeContext: parseJSON(row.runtimeContext),
|
|
1400
|
-
entity: parseJSON(row.entity),
|
|
1401
|
-
createdAt: row.createdAt,
|
|
1402
|
-
updatedAt: row.updatedAt
|
|
1403
|
-
};
|
|
2299
|
+
return storage.transformScoreRow(row, {
|
|
2300
|
+
convertTimestamps: true
|
|
2301
|
+
});
|
|
1404
2302
|
}
|
|
1405
2303
|
var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
1406
2304
|
pool;
|
|
@@ -1430,7 +2328,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1430
2328
|
} catch (error$1) {
|
|
1431
2329
|
throw new error.MastraError(
|
|
1432
2330
|
{
|
|
1433
|
-
id: "
|
|
2331
|
+
id: storage.createStorageErrorId("MSSQL", "GET_SCORE_BY_ID", "FAILED"),
|
|
1434
2332
|
domain: error.ErrorDomain.STORAGE,
|
|
1435
2333
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1436
2334
|
details: { id }
|
|
@@ -1438,10 +2336,31 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1438
2336
|
error$1
|
|
1439
2337
|
);
|
|
1440
2338
|
}
|
|
1441
|
-
}
|
|
1442
|
-
async saveScore(score) {
|
|
2339
|
+
}
|
|
2340
|
+
async saveScore(score) {
|
|
2341
|
+
let validatedScore;
|
|
2342
|
+
try {
|
|
2343
|
+
validatedScore = evals.saveScorePayloadSchema.parse(score);
|
|
2344
|
+
} catch (error$1) {
|
|
2345
|
+
throw new error.MastraError(
|
|
2346
|
+
{
|
|
2347
|
+
id: storage.createStorageErrorId("MSSQL", "SAVE_SCORE", "VALIDATION_FAILED"),
|
|
2348
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2349
|
+
category: error.ErrorCategory.USER,
|
|
2350
|
+
details: {
|
|
2351
|
+
scorer: score.scorer?.id ?? "unknown",
|
|
2352
|
+
entityId: score.entityId ?? "unknown",
|
|
2353
|
+
entityType: score.entityType ?? "unknown",
|
|
2354
|
+
traceId: score.traceId ?? "",
|
|
2355
|
+
spanId: score.spanId ?? ""
|
|
2356
|
+
}
|
|
2357
|
+
},
|
|
2358
|
+
error$1
|
|
2359
|
+
);
|
|
2360
|
+
}
|
|
1443
2361
|
try {
|
|
1444
2362
|
const scoreId = crypto.randomUUID();
|
|
2363
|
+
const now = /* @__PURE__ */ new Date();
|
|
1445
2364
|
const {
|
|
1446
2365
|
scorer,
|
|
1447
2366
|
preprocessStepResult,
|
|
@@ -1450,34 +2369,33 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1450
2369
|
input,
|
|
1451
2370
|
output,
|
|
1452
2371
|
additionalContext,
|
|
1453
|
-
|
|
2372
|
+
requestContext,
|
|
1454
2373
|
entity,
|
|
1455
2374
|
...rest
|
|
1456
|
-
} =
|
|
2375
|
+
} = validatedScore;
|
|
1457
2376
|
await this.operations.insert({
|
|
1458
2377
|
tableName: storage.TABLE_SCORERS,
|
|
1459
2378
|
record: {
|
|
1460
2379
|
id: scoreId,
|
|
1461
2380
|
...rest,
|
|
1462
|
-
input:
|
|
1463
|
-
output:
|
|
1464
|
-
preprocessStepResult: preprocessStepResult
|
|
1465
|
-
analyzeStepResult: analyzeStepResult
|
|
1466
|
-
metadata: metadata
|
|
1467
|
-
additionalContext: additionalContext
|
|
1468
|
-
|
|
1469
|
-
entity: entity
|
|
1470
|
-
scorer: scorer
|
|
1471
|
-
createdAt:
|
|
1472
|
-
updatedAt:
|
|
2381
|
+
input: input || "",
|
|
2382
|
+
output: output || "",
|
|
2383
|
+
preprocessStepResult: preprocessStepResult || null,
|
|
2384
|
+
analyzeStepResult: analyzeStepResult || null,
|
|
2385
|
+
metadata: metadata || null,
|
|
2386
|
+
additionalContext: additionalContext || null,
|
|
2387
|
+
requestContext: requestContext || null,
|
|
2388
|
+
entity: entity || null,
|
|
2389
|
+
scorer: scorer || null,
|
|
2390
|
+
createdAt: now.toISOString(),
|
|
2391
|
+
updatedAt: now.toISOString()
|
|
1473
2392
|
}
|
|
1474
2393
|
});
|
|
1475
|
-
|
|
1476
|
-
return { score: scoreFromDb };
|
|
2394
|
+
return { score: { ...validatedScore, id: scoreId, createdAt: now, updatedAt: now } };
|
|
1477
2395
|
} catch (error$1) {
|
|
1478
2396
|
throw new error.MastraError(
|
|
1479
2397
|
{
|
|
1480
|
-
id: "
|
|
2398
|
+
id: storage.createStorageErrorId("MSSQL", "SAVE_SCORE", "FAILED"),
|
|
1481
2399
|
domain: error.ErrorDomain.STORAGE,
|
|
1482
2400
|
category: error.ErrorCategory.THIRD_PARTY
|
|
1483
2401
|
},
|
|
@@ -1485,48 +2403,77 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1485
2403
|
);
|
|
1486
2404
|
}
|
|
1487
2405
|
}
|
|
1488
|
-
async
|
|
2406
|
+
async listScoresByScorerId({
|
|
1489
2407
|
scorerId,
|
|
1490
|
-
pagination
|
|
2408
|
+
pagination,
|
|
2409
|
+
entityId,
|
|
2410
|
+
entityType,
|
|
2411
|
+
source
|
|
1491
2412
|
}) {
|
|
1492
2413
|
try {
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
2414
|
+
const conditions = ["[scorerId] = @p1"];
|
|
2415
|
+
const params = { p1: scorerId };
|
|
2416
|
+
let paramIndex = 2;
|
|
2417
|
+
if (entityId) {
|
|
2418
|
+
conditions.push(`[entityId] = @p${paramIndex}`);
|
|
2419
|
+
params[`p${paramIndex}`] = entityId;
|
|
2420
|
+
paramIndex++;
|
|
2421
|
+
}
|
|
2422
|
+
if (entityType) {
|
|
2423
|
+
conditions.push(`[entityType] = @p${paramIndex}`);
|
|
2424
|
+
params[`p${paramIndex}`] = entityType;
|
|
2425
|
+
paramIndex++;
|
|
2426
|
+
}
|
|
2427
|
+
if (source) {
|
|
2428
|
+
conditions.push(`[source] = @p${paramIndex}`);
|
|
2429
|
+
params[`p${paramIndex}`] = source;
|
|
2430
|
+
paramIndex++;
|
|
2431
|
+
}
|
|
2432
|
+
const whereClause = conditions.join(" AND ");
|
|
2433
|
+
const tableName = getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) });
|
|
2434
|
+
const countRequest = this.pool.request();
|
|
2435
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
2436
|
+
countRequest.input(key, value);
|
|
2437
|
+
});
|
|
2438
|
+
const totalResult = await countRequest.query(`SELECT COUNT(*) as count FROM ${tableName} WHERE ${whereClause}`);
|
|
1498
2439
|
const total = totalResult.recordset[0]?.count || 0;
|
|
2440
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1499
2441
|
if (total === 0) {
|
|
1500
2442
|
return {
|
|
1501
2443
|
pagination: {
|
|
1502
2444
|
total: 0,
|
|
1503
|
-
page
|
|
1504
|
-
perPage:
|
|
2445
|
+
page,
|
|
2446
|
+
perPage: perPageInput,
|
|
1505
2447
|
hasMore: false
|
|
1506
2448
|
},
|
|
1507
2449
|
scores: []
|
|
1508
2450
|
};
|
|
1509
2451
|
}
|
|
2452
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2453
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2454
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2455
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1510
2456
|
const dataRequest = this.pool.request();
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
2457
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
2458
|
+
dataRequest.input(key, value);
|
|
2459
|
+
});
|
|
2460
|
+
dataRequest.input("perPage", limitValue);
|
|
2461
|
+
dataRequest.input("offset", start);
|
|
2462
|
+
const dataQuery = `SELECT * FROM ${tableName} WHERE ${whereClause} ORDER BY [createdAt] DESC OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
2463
|
+
const result = await dataRequest.query(dataQuery);
|
|
1517
2464
|
return {
|
|
1518
2465
|
pagination: {
|
|
1519
2466
|
total: Number(total),
|
|
1520
|
-
page
|
|
1521
|
-
perPage:
|
|
1522
|
-
hasMore:
|
|
2467
|
+
page,
|
|
2468
|
+
perPage: perPageForResponse,
|
|
2469
|
+
hasMore: end < total
|
|
1523
2470
|
},
|
|
1524
2471
|
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
1525
2472
|
};
|
|
1526
2473
|
} catch (error$1) {
|
|
1527
2474
|
throw new error.MastraError(
|
|
1528
2475
|
{
|
|
1529
|
-
id: "
|
|
2476
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
|
|
1530
2477
|
domain: error.ErrorDomain.STORAGE,
|
|
1531
2478
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1532
2479
|
details: { scorerId }
|
|
@@ -1535,7 +2482,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1535
2482
|
);
|
|
1536
2483
|
}
|
|
1537
2484
|
}
|
|
1538
|
-
async
|
|
2485
|
+
async listScoresByRunId({
|
|
1539
2486
|
runId,
|
|
1540
2487
|
pagination
|
|
1541
2488
|
}) {
|
|
@@ -1546,37 +2493,42 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1546
2493
|
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [runId] = @p1`
|
|
1547
2494
|
);
|
|
1548
2495
|
const total = totalResult.recordset[0]?.count || 0;
|
|
2496
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1549
2497
|
if (total === 0) {
|
|
1550
2498
|
return {
|
|
1551
2499
|
pagination: {
|
|
1552
2500
|
total: 0,
|
|
1553
|
-
page
|
|
1554
|
-
perPage:
|
|
2501
|
+
page,
|
|
2502
|
+
perPage: perPageInput,
|
|
1555
2503
|
hasMore: false
|
|
1556
2504
|
},
|
|
1557
2505
|
scores: []
|
|
1558
2506
|
};
|
|
1559
2507
|
}
|
|
2508
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2509
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2510
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2511
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1560
2512
|
const dataRequest = this.pool.request();
|
|
1561
2513
|
dataRequest.input("p1", runId);
|
|
1562
|
-
dataRequest.input("p2",
|
|
1563
|
-
dataRequest.input("p3",
|
|
2514
|
+
dataRequest.input("p2", limitValue);
|
|
2515
|
+
dataRequest.input("p3", start);
|
|
1564
2516
|
const result = await dataRequest.query(
|
|
1565
2517
|
`SELECT * FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [runId] = @p1 ORDER BY [createdAt] DESC OFFSET @p3 ROWS FETCH NEXT @p2 ROWS ONLY`
|
|
1566
2518
|
);
|
|
1567
2519
|
return {
|
|
1568
2520
|
pagination: {
|
|
1569
2521
|
total: Number(total),
|
|
1570
|
-
page
|
|
1571
|
-
perPage:
|
|
1572
|
-
hasMore:
|
|
2522
|
+
page,
|
|
2523
|
+
perPage: perPageForResponse,
|
|
2524
|
+
hasMore: end < total
|
|
1573
2525
|
},
|
|
1574
2526
|
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
1575
2527
|
};
|
|
1576
2528
|
} catch (error$1) {
|
|
1577
2529
|
throw new error.MastraError(
|
|
1578
2530
|
{
|
|
1579
|
-
id: "
|
|
2531
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_SCORES_BY_RUN_ID", "FAILED"),
|
|
1580
2532
|
domain: error.ErrorDomain.STORAGE,
|
|
1581
2533
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1582
2534
|
details: { runId }
|
|
@@ -1585,7 +2537,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1585
2537
|
);
|
|
1586
2538
|
}
|
|
1587
2539
|
}
|
|
1588
|
-
async
|
|
2540
|
+
async listScoresByEntityId({
|
|
1589
2541
|
entityId,
|
|
1590
2542
|
entityType,
|
|
1591
2543
|
pagination
|
|
@@ -1598,38 +2550,43 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1598
2550
|
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [entityId] = @p1 AND [entityType] = @p2`
|
|
1599
2551
|
);
|
|
1600
2552
|
const total = totalResult.recordset[0]?.count || 0;
|
|
2553
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2554
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2555
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1601
2556
|
if (total === 0) {
|
|
1602
2557
|
return {
|
|
1603
2558
|
pagination: {
|
|
1604
2559
|
total: 0,
|
|
1605
|
-
page
|
|
1606
|
-
perPage:
|
|
2560
|
+
page,
|
|
2561
|
+
perPage: perPageForResponse,
|
|
1607
2562
|
hasMore: false
|
|
1608
2563
|
},
|
|
1609
2564
|
scores: []
|
|
1610
2565
|
};
|
|
1611
2566
|
}
|
|
2567
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2568
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1612
2569
|
const dataRequest = this.pool.request();
|
|
1613
2570
|
dataRequest.input("p1", entityId);
|
|
1614
2571
|
dataRequest.input("p2", entityType);
|
|
1615
|
-
dataRequest.input("p3",
|
|
1616
|
-
dataRequest.input("p4",
|
|
2572
|
+
dataRequest.input("p3", limitValue);
|
|
2573
|
+
dataRequest.input("p4", start);
|
|
1617
2574
|
const result = await dataRequest.query(
|
|
1618
2575
|
`SELECT * FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [entityId] = @p1 AND [entityType] = @p2 ORDER BY [createdAt] DESC OFFSET @p4 ROWS FETCH NEXT @p3 ROWS ONLY`
|
|
1619
2576
|
);
|
|
1620
2577
|
return {
|
|
1621
2578
|
pagination: {
|
|
1622
2579
|
total: Number(total),
|
|
1623
|
-
page
|
|
1624
|
-
perPage:
|
|
1625
|
-
hasMore:
|
|
2580
|
+
page,
|
|
2581
|
+
perPage: perPageForResponse,
|
|
2582
|
+
hasMore: end < total
|
|
1626
2583
|
},
|
|
1627
2584
|
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
1628
2585
|
};
|
|
1629
2586
|
} catch (error$1) {
|
|
1630
2587
|
throw new error.MastraError(
|
|
1631
2588
|
{
|
|
1632
|
-
id: "
|
|
2589
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
|
|
1633
2590
|
domain: error.ErrorDomain.STORAGE,
|
|
1634
2591
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1635
2592
|
details: { entityId, entityType }
|
|
@@ -1638,8 +2595,66 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1638
2595
|
);
|
|
1639
2596
|
}
|
|
1640
2597
|
}
|
|
2598
|
+
async listScoresBySpan({
|
|
2599
|
+
traceId,
|
|
2600
|
+
spanId,
|
|
2601
|
+
pagination
|
|
2602
|
+
}) {
|
|
2603
|
+
try {
|
|
2604
|
+
const request = this.pool.request();
|
|
2605
|
+
request.input("p1", traceId);
|
|
2606
|
+
request.input("p2", spanId);
|
|
2607
|
+
const totalResult = await request.query(
|
|
2608
|
+
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [traceId] = @p1 AND [spanId] = @p2`
|
|
2609
|
+
);
|
|
2610
|
+
const total = totalResult.recordset[0]?.count || 0;
|
|
2611
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2612
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2613
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2614
|
+
if (total === 0) {
|
|
2615
|
+
return {
|
|
2616
|
+
pagination: {
|
|
2617
|
+
total: 0,
|
|
2618
|
+
page,
|
|
2619
|
+
perPage: perPageForResponse,
|
|
2620
|
+
hasMore: false
|
|
2621
|
+
},
|
|
2622
|
+
scores: []
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2626
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
2627
|
+
const dataRequest = this.pool.request();
|
|
2628
|
+
dataRequest.input("p1", traceId);
|
|
2629
|
+
dataRequest.input("p2", spanId);
|
|
2630
|
+
dataRequest.input("p3", limitValue);
|
|
2631
|
+
dataRequest.input("p4", start);
|
|
2632
|
+
const result = await dataRequest.query(
|
|
2633
|
+
`SELECT * FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [traceId] = @p1 AND [spanId] = @p2 ORDER BY [createdAt] DESC OFFSET @p4 ROWS FETCH NEXT @p3 ROWS ONLY`
|
|
2634
|
+
);
|
|
2635
|
+
return {
|
|
2636
|
+
pagination: {
|
|
2637
|
+
total: Number(total),
|
|
2638
|
+
page,
|
|
2639
|
+
perPage: perPageForResponse,
|
|
2640
|
+
hasMore: end < total
|
|
2641
|
+
},
|
|
2642
|
+
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
2643
|
+
};
|
|
2644
|
+
} catch (error$1) {
|
|
2645
|
+
throw new error.MastraError(
|
|
2646
|
+
{
|
|
2647
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_SCORES_BY_SPAN", "FAILED"),
|
|
2648
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2649
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2650
|
+
details: { traceId, spanId }
|
|
2651
|
+
},
|
|
2652
|
+
error$1
|
|
2653
|
+
);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
1641
2656
|
};
|
|
1642
|
-
var
|
|
2657
|
+
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
1643
2658
|
pool;
|
|
1644
2659
|
operations;
|
|
1645
2660
|
schema;
|
|
@@ -1653,194 +2668,170 @@ var TracesMSSQL = class extends storage.TracesStorage {
|
|
|
1653
2668
|
this.operations = operations;
|
|
1654
2669
|
this.schema = schema;
|
|
1655
2670
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
if (
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
2671
|
+
parseWorkflowRun(row) {
|
|
2672
|
+
let parsedSnapshot = row.snapshot;
|
|
2673
|
+
if (typeof parsedSnapshot === "string") {
|
|
2674
|
+
try {
|
|
2675
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
2676
|
+
} catch (e) {
|
|
2677
|
+
this.logger?.warn?.(`Failed to parse snapshot for workflow ${row.workflow_name}:`, e);
|
|
2678
|
+
}
|
|
1663
2679
|
}
|
|
1664
|
-
|
|
1665
|
-
|
|
2680
|
+
return {
|
|
2681
|
+
workflowName: row.workflow_name,
|
|
2682
|
+
runId: row.run_id,
|
|
2683
|
+
snapshot: parsedSnapshot,
|
|
2684
|
+
createdAt: row.createdAt,
|
|
2685
|
+
updatedAt: row.updatedAt,
|
|
2686
|
+
resourceId: row.resourceId
|
|
2687
|
+
};
|
|
1666
2688
|
}
|
|
1667
|
-
async
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
const
|
|
1675
|
-
|
|
1676
|
-
if (name) {
|
|
1677
|
-
const paramName = `p${paramIndex++}`;
|
|
1678
|
-
conditions.push(`[name] LIKE @${paramName}`);
|
|
1679
|
-
paramMap[paramName] = `${name}%`;
|
|
1680
|
-
}
|
|
1681
|
-
if (scope) {
|
|
1682
|
-
const paramName = `p${paramIndex++}`;
|
|
1683
|
-
conditions.push(`[scope] = @${paramName}`);
|
|
1684
|
-
paramMap[paramName] = scope;
|
|
1685
|
-
}
|
|
1686
|
-
if (attributes) {
|
|
1687
|
-
Object.entries(attributes).forEach(([key, value]) => {
|
|
1688
|
-
const parsedKey = utils.parseFieldKey(key);
|
|
1689
|
-
const paramName = `p${paramIndex++}`;
|
|
1690
|
-
conditions.push(`JSON_VALUE([attributes], '$.${parsedKey}') = @${paramName}`);
|
|
1691
|
-
paramMap[paramName] = value;
|
|
1692
|
-
});
|
|
1693
|
-
}
|
|
1694
|
-
if (filters) {
|
|
1695
|
-
Object.entries(filters).forEach(([key, value]) => {
|
|
1696
|
-
const parsedKey = utils.parseFieldKey(key);
|
|
1697
|
-
const paramName = `p${paramIndex++}`;
|
|
1698
|
-
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1699
|
-
paramMap[paramName] = value;
|
|
1700
|
-
});
|
|
1701
|
-
}
|
|
1702
|
-
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
1703
|
-
const paramName = `p${paramIndex++}`;
|
|
1704
|
-
conditions.push(`[createdAt] >= @${paramName}`);
|
|
1705
|
-
paramMap[paramName] = fromDate.toISOString();
|
|
1706
|
-
}
|
|
1707
|
-
if (toDate instanceof Date && !isNaN(toDate.getTime())) {
|
|
1708
|
-
const paramName = `p${paramIndex++}`;
|
|
1709
|
-
conditions.push(`[createdAt] <= @${paramName}`);
|
|
1710
|
-
paramMap[paramName] = toDate.toISOString();
|
|
1711
|
-
}
|
|
1712
|
-
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1713
|
-
const countQuery = `SELECT COUNT(*) as total FROM ${getTableName({ indexName: storage.TABLE_TRACES, schemaName: getSchemaName(this.schema) })} ${whereClause}`;
|
|
1714
|
-
let total = 0;
|
|
2689
|
+
async updateWorkflowResults({
|
|
2690
|
+
workflowName,
|
|
2691
|
+
runId,
|
|
2692
|
+
stepId,
|
|
2693
|
+
result,
|
|
2694
|
+
requestContext
|
|
2695
|
+
}) {
|
|
2696
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2697
|
+
const transaction = this.pool.transaction();
|
|
1715
2698
|
try {
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
2699
|
+
await transaction.begin();
|
|
2700
|
+
const selectRequest = new sql3__default.default.Request(transaction);
|
|
2701
|
+
selectRequest.input("workflow_name", workflowName);
|
|
2702
|
+
selectRequest.input("run_id", runId);
|
|
2703
|
+
const existingSnapshotResult = await selectRequest.query(
|
|
2704
|
+
`SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2705
|
+
);
|
|
2706
|
+
let snapshot;
|
|
2707
|
+
if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
|
|
2708
|
+
snapshot = {
|
|
2709
|
+
context: {},
|
|
2710
|
+
activePaths: [],
|
|
2711
|
+
activeStepsPath: {},
|
|
2712
|
+
timestamp: Date.now(),
|
|
2713
|
+
suspendedPaths: {},
|
|
2714
|
+
resumeLabels: {},
|
|
2715
|
+
serializedStepGraph: [],
|
|
2716
|
+
status: "pending",
|
|
2717
|
+
value: {},
|
|
2718
|
+
waitingPaths: {},
|
|
2719
|
+
runId,
|
|
2720
|
+
requestContext: {}
|
|
2721
|
+
};
|
|
2722
|
+
} else {
|
|
2723
|
+
const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
|
|
2724
|
+
snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
2725
|
+
}
|
|
2726
|
+
snapshot.context[stepId] = result;
|
|
2727
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
2728
|
+
const upsertReq = new sql3__default.default.Request(transaction);
|
|
2729
|
+
upsertReq.input("workflow_name", workflowName);
|
|
2730
|
+
upsertReq.input("run_id", runId);
|
|
2731
|
+
upsertReq.input("snapshot", JSON.stringify(snapshot));
|
|
2732
|
+
upsertReq.input("createdAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2733
|
+
upsertReq.input("updatedAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2734
|
+
await upsertReq.query(
|
|
2735
|
+
`MERGE ${table} AS target
|
|
2736
|
+
USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
|
|
2737
|
+
ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
|
|
2738
|
+
WHEN MATCHED THEN UPDATE SET snapshot = @snapshot, [updatedAt] = @updatedAt
|
|
2739
|
+
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
|
|
2740
|
+
VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`
|
|
2741
|
+
);
|
|
2742
|
+
await transaction.commit();
|
|
2743
|
+
return snapshot.context;
|
|
1726
2744
|
} catch (error$1) {
|
|
2745
|
+
try {
|
|
2746
|
+
await transaction.rollback();
|
|
2747
|
+
} catch {
|
|
2748
|
+
}
|
|
1727
2749
|
throw new error.MastraError(
|
|
1728
2750
|
{
|
|
1729
|
-
id: "
|
|
2751
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
|
|
1730
2752
|
domain: error.ErrorDomain.STORAGE,
|
|
1731
2753
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1732
2754
|
details: {
|
|
1733
|
-
|
|
1734
|
-
|
|
2755
|
+
workflowName,
|
|
2756
|
+
runId,
|
|
2757
|
+
stepId
|
|
1735
2758
|
}
|
|
1736
2759
|
},
|
|
1737
2760
|
error$1
|
|
1738
2761
|
);
|
|
1739
2762
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
}
|
|
1749
|
-
const dataQuery = `SELECT * FROM ${getTableName({ indexName: storage.TABLE_TRACES, schemaName: getSchemaName(this.schema) })} ${whereClause} ORDER BY [seq_id] DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`;
|
|
1750
|
-
const dataRequest = this.pool.request();
|
|
1751
|
-
Object.entries(paramMap).forEach(([key, value]) => {
|
|
1752
|
-
if (value instanceof Date) {
|
|
1753
|
-
dataRequest.input(key, sql2__default.default.DateTime, value);
|
|
1754
|
-
} else {
|
|
1755
|
-
dataRequest.input(key, value);
|
|
1756
|
-
}
|
|
1757
|
-
});
|
|
1758
|
-
dataRequest.input("offset", currentOffset);
|
|
1759
|
-
dataRequest.input("limit", perPage);
|
|
2763
|
+
}
|
|
2764
|
+
async updateWorkflowState({
|
|
2765
|
+
workflowName,
|
|
2766
|
+
runId,
|
|
2767
|
+
opts
|
|
2768
|
+
}) {
|
|
2769
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2770
|
+
const transaction = this.pool.transaction();
|
|
1760
2771
|
try {
|
|
1761
|
-
|
|
1762
|
-
const
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
2772
|
+
await transaction.begin();
|
|
2773
|
+
const selectRequest = new sql3__default.default.Request(transaction);
|
|
2774
|
+
selectRequest.input("workflow_name", workflowName);
|
|
2775
|
+
selectRequest.input("run_id", runId);
|
|
2776
|
+
const existingSnapshotResult = await selectRequest.query(
|
|
2777
|
+
`SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2778
|
+
);
|
|
2779
|
+
if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
|
|
2780
|
+
await transaction.rollback();
|
|
2781
|
+
return void 0;
|
|
2782
|
+
}
|
|
2783
|
+
const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
|
|
2784
|
+
const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
2785
|
+
if (!snapshot || !snapshot?.context) {
|
|
2786
|
+
await transaction.rollback();
|
|
2787
|
+
throw new error.MastraError(
|
|
2788
|
+
{
|
|
2789
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_WORKFLOW_STATE", "SNAPSHOT_NOT_FOUND"),
|
|
2790
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2791
|
+
category: error.ErrorCategory.SYSTEM,
|
|
2792
|
+
details: {
|
|
2793
|
+
workflowName,
|
|
2794
|
+
runId
|
|
2795
|
+
}
|
|
2796
|
+
},
|
|
2797
|
+
new Error(`Snapshot not found for runId ${runId}`)
|
|
2798
|
+
);
|
|
2799
|
+
}
|
|
2800
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
2801
|
+
const updateRequest = new sql3__default.default.Request(transaction);
|
|
2802
|
+
updateRequest.input("snapshot", JSON.stringify(updatedSnapshot));
|
|
2803
|
+
updateRequest.input("workflow_name", workflowName);
|
|
2804
|
+
updateRequest.input("run_id", runId);
|
|
2805
|
+
updateRequest.input("updatedAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2806
|
+
await updateRequest.query(
|
|
2807
|
+
`UPDATE ${table} SET snapshot = @snapshot, [updatedAt] = @updatedAt WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2808
|
+
);
|
|
2809
|
+
await transaction.commit();
|
|
2810
|
+
return updatedSnapshot;
|
|
1786
2811
|
} catch (error$1) {
|
|
2812
|
+
try {
|
|
2813
|
+
await transaction.rollback();
|
|
2814
|
+
} catch {
|
|
2815
|
+
}
|
|
2816
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
1787
2817
|
throw new error.MastraError(
|
|
1788
2818
|
{
|
|
1789
|
-
id: "
|
|
2819
|
+
id: storage.createStorageErrorId("MSSQL", "UPDATE_WORKFLOW_STATE", "FAILED"),
|
|
1790
2820
|
domain: error.ErrorDomain.STORAGE,
|
|
1791
2821
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1792
2822
|
details: {
|
|
1793
|
-
|
|
1794
|
-
|
|
2823
|
+
workflowName,
|
|
2824
|
+
runId
|
|
1795
2825
|
}
|
|
1796
2826
|
},
|
|
1797
2827
|
error$1
|
|
1798
2828
|
);
|
|
1799
2829
|
}
|
|
1800
2830
|
}
|
|
1801
|
-
async batchTraceInsert({ records }) {
|
|
1802
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1803
|
-
await this.operations.batchInsert({
|
|
1804
|
-
tableName: storage.TABLE_TRACES,
|
|
1805
|
-
records
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
|
-
};
|
|
1809
|
-
function parseWorkflowRun(row) {
|
|
1810
|
-
let parsedSnapshot = row.snapshot;
|
|
1811
|
-
if (typeof parsedSnapshot === "string") {
|
|
1812
|
-
try {
|
|
1813
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1814
|
-
} catch (e) {
|
|
1815
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
return {
|
|
1819
|
-
workflowName: row.workflow_name,
|
|
1820
|
-
runId: row.run_id,
|
|
1821
|
-
snapshot: parsedSnapshot,
|
|
1822
|
-
createdAt: row.createdAt,
|
|
1823
|
-
updatedAt: row.updatedAt,
|
|
1824
|
-
resourceId: row.resourceId
|
|
1825
|
-
};
|
|
1826
|
-
}
|
|
1827
|
-
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
1828
|
-
pool;
|
|
1829
|
-
operations;
|
|
1830
|
-
schema;
|
|
1831
|
-
constructor({
|
|
1832
|
-
pool,
|
|
1833
|
-
operations,
|
|
1834
|
-
schema
|
|
1835
|
-
}) {
|
|
1836
|
-
super();
|
|
1837
|
-
this.pool = pool;
|
|
1838
|
-
this.operations = operations;
|
|
1839
|
-
this.schema = schema;
|
|
1840
|
-
}
|
|
1841
2831
|
async persistWorkflowSnapshot({
|
|
1842
2832
|
workflowName,
|
|
1843
2833
|
runId,
|
|
2834
|
+
resourceId,
|
|
1844
2835
|
snapshot
|
|
1845
2836
|
}) {
|
|
1846
2837
|
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
@@ -1849,22 +2840,24 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1849
2840
|
const request = this.pool.request();
|
|
1850
2841
|
request.input("workflow_name", workflowName);
|
|
1851
2842
|
request.input("run_id", runId);
|
|
2843
|
+
request.input("resourceId", resourceId);
|
|
1852
2844
|
request.input("snapshot", JSON.stringify(snapshot));
|
|
1853
|
-
request.input("createdAt",
|
|
1854
|
-
request.input("updatedAt",
|
|
2845
|
+
request.input("createdAt", sql3__default.default.DateTime2, new Date(now));
|
|
2846
|
+
request.input("updatedAt", sql3__default.default.DateTime2, new Date(now));
|
|
1855
2847
|
const mergeSql = `MERGE INTO ${table} AS target
|
|
1856
2848
|
USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
|
|
1857
2849
|
ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
|
|
1858
2850
|
WHEN MATCHED THEN UPDATE SET
|
|
2851
|
+
resourceId = @resourceId,
|
|
1859
2852
|
snapshot = @snapshot,
|
|
1860
2853
|
[updatedAt] = @updatedAt
|
|
1861
|
-
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
|
|
1862
|
-
VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`;
|
|
2854
|
+
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, resourceId, snapshot, [createdAt], [updatedAt])
|
|
2855
|
+
VALUES (@workflow_name, @run_id, @resourceId, @snapshot, @createdAt, @updatedAt);`;
|
|
1863
2856
|
await request.query(mergeSql);
|
|
1864
2857
|
} catch (error$1) {
|
|
1865
2858
|
throw new error.MastraError(
|
|
1866
2859
|
{
|
|
1867
|
-
id: "
|
|
2860
|
+
id: storage.createStorageErrorId("MSSQL", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1868
2861
|
domain: error.ErrorDomain.STORAGE,
|
|
1869
2862
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1870
2863
|
details: {
|
|
@@ -1895,7 +2888,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1895
2888
|
} catch (error$1) {
|
|
1896
2889
|
throw new error.MastraError(
|
|
1897
2890
|
{
|
|
1898
|
-
id: "
|
|
2891
|
+
id: storage.createStorageErrorId("MSSQL", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1899
2892
|
domain: error.ErrorDomain.STORAGE,
|
|
1900
2893
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1901
2894
|
details: {
|
|
@@ -1931,11 +2924,11 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1931
2924
|
if (!result.recordset || result.recordset.length === 0) {
|
|
1932
2925
|
return null;
|
|
1933
2926
|
}
|
|
1934
|
-
return parseWorkflowRun(result.recordset[0]);
|
|
2927
|
+
return this.parseWorkflowRun(result.recordset[0]);
|
|
1935
2928
|
} catch (error$1) {
|
|
1936
2929
|
throw new error.MastraError(
|
|
1937
2930
|
{
|
|
1938
|
-
id: "
|
|
2931
|
+
id: storage.createStorageErrorId("MSSQL", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1939
2932
|
domain: error.ErrorDomain.STORAGE,
|
|
1940
2933
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1941
2934
|
details: {
|
|
@@ -1947,13 +2940,43 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1947
2940
|
);
|
|
1948
2941
|
}
|
|
1949
2942
|
}
|
|
1950
|
-
async
|
|
2943
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
2944
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2945
|
+
const transaction = this.pool.transaction();
|
|
2946
|
+
try {
|
|
2947
|
+
await transaction.begin();
|
|
2948
|
+
const deleteRequest = new sql3__default.default.Request(transaction);
|
|
2949
|
+
deleteRequest.input("workflow_name", workflowName);
|
|
2950
|
+
deleteRequest.input("run_id", runId);
|
|
2951
|
+
await deleteRequest.query(`DELETE FROM ${table} WHERE workflow_name = @workflow_name AND run_id = @run_id`);
|
|
2952
|
+
await transaction.commit();
|
|
2953
|
+
} catch (error$1) {
|
|
2954
|
+
try {
|
|
2955
|
+
await transaction.rollback();
|
|
2956
|
+
} catch {
|
|
2957
|
+
}
|
|
2958
|
+
throw new error.MastraError(
|
|
2959
|
+
{
|
|
2960
|
+
id: storage.createStorageErrorId("MSSQL", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
2961
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2962
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2963
|
+
details: {
|
|
2964
|
+
runId,
|
|
2965
|
+
workflowName
|
|
2966
|
+
}
|
|
2967
|
+
},
|
|
2968
|
+
error$1
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
async listWorkflowRuns({
|
|
1951
2973
|
workflowName,
|
|
1952
2974
|
fromDate,
|
|
1953
2975
|
toDate,
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
resourceId
|
|
2976
|
+
page,
|
|
2977
|
+
perPage,
|
|
2978
|
+
resourceId,
|
|
2979
|
+
status
|
|
1957
2980
|
} = {}) {
|
|
1958
2981
|
try {
|
|
1959
2982
|
const conditions = [];
|
|
@@ -1962,13 +2985,17 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1962
2985
|
conditions.push(`[workflow_name] = @workflowName`);
|
|
1963
2986
|
paramMap["workflowName"] = workflowName;
|
|
1964
2987
|
}
|
|
2988
|
+
if (status) {
|
|
2989
|
+
conditions.push(`JSON_VALUE([snapshot], '$.status') = @status`);
|
|
2990
|
+
paramMap["status"] = status;
|
|
2991
|
+
}
|
|
1965
2992
|
if (resourceId) {
|
|
1966
2993
|
const hasResourceId = await this.operations.hasColumn(storage.TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
1967
2994
|
if (hasResourceId) {
|
|
1968
2995
|
conditions.push(`[resourceId] = @resourceId`);
|
|
1969
2996
|
paramMap["resourceId"] = resourceId;
|
|
1970
2997
|
} else {
|
|
1971
|
-
|
|
2998
|
+
this.logger?.warn?.(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
1972
2999
|
}
|
|
1973
3000
|
}
|
|
1974
3001
|
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
@@ -1985,29 +3012,32 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1985
3012
|
const request = this.pool.request();
|
|
1986
3013
|
Object.entries(paramMap).forEach(([key, value]) => {
|
|
1987
3014
|
if (value instanceof Date) {
|
|
1988
|
-
request.input(key,
|
|
3015
|
+
request.input(key, sql3__default.default.DateTime, value);
|
|
1989
3016
|
} else {
|
|
1990
3017
|
request.input(key, value);
|
|
1991
3018
|
}
|
|
1992
3019
|
});
|
|
1993
|
-
|
|
3020
|
+
const usePagination = typeof perPage === "number" && typeof page === "number";
|
|
3021
|
+
if (usePagination) {
|
|
1994
3022
|
const countQuery = `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`;
|
|
1995
3023
|
const countResult = await request.query(countQuery);
|
|
1996
3024
|
total = Number(countResult.recordset[0]?.count || 0);
|
|
1997
3025
|
}
|
|
1998
3026
|
let query = `SELECT * FROM ${tableName} ${whereClause} ORDER BY [seq_id] DESC`;
|
|
1999
|
-
if (
|
|
2000
|
-
|
|
2001
|
-
|
|
3027
|
+
if (usePagination) {
|
|
3028
|
+
const normalizedPerPage = storage.normalizePerPage(perPage, Number.MAX_SAFE_INTEGER);
|
|
3029
|
+
const offset = page * normalizedPerPage;
|
|
3030
|
+
query += ` OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
3031
|
+
request.input("perPage", normalizedPerPage);
|
|
2002
3032
|
request.input("offset", offset);
|
|
2003
3033
|
}
|
|
2004
3034
|
const result = await request.query(query);
|
|
2005
|
-
const runs = (result.recordset || []).map((row) => parseWorkflowRun(row));
|
|
3035
|
+
const runs = (result.recordset || []).map((row) => this.parseWorkflowRun(row));
|
|
2006
3036
|
return { runs, total: total || runs.length };
|
|
2007
3037
|
} catch (error$1) {
|
|
2008
3038
|
throw new error.MastraError(
|
|
2009
3039
|
{
|
|
2010
|
-
id: "
|
|
3040
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
2011
3041
|
domain: error.ErrorDomain.STORAGE,
|
|
2012
3042
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2013
3043
|
details: {
|
|
@@ -2027,7 +3057,10 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2027
3057
|
isConnected = null;
|
|
2028
3058
|
stores;
|
|
2029
3059
|
constructor(config) {
|
|
2030
|
-
|
|
3060
|
+
if (!config.id || typeof config.id !== "string" || config.id.trim() === "") {
|
|
3061
|
+
throw new Error("MSSQLStore: id must be provided and cannot be empty.");
|
|
3062
|
+
}
|
|
3063
|
+
super({ id: config.id, name: "MSSQLStore", disableInit: config.disableInit });
|
|
2031
3064
|
try {
|
|
2032
3065
|
if ("connectionString" in config) {
|
|
2033
3066
|
if (!config.connectionString || typeof config.connectionString !== "string" || config.connectionString.trim() === "") {
|
|
@@ -2042,7 +3075,7 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2042
3075
|
}
|
|
2043
3076
|
}
|
|
2044
3077
|
this.schema = config.schemaName || "dbo";
|
|
2045
|
-
this.pool = "connectionString" in config ? new
|
|
3078
|
+
this.pool = "connectionString" in config ? new sql3__default.default.ConnectionPool(config.connectionString) : new sql3__default.default.ConnectionPool({
|
|
2046
3079
|
server: config.server,
|
|
2047
3080
|
database: config.database,
|
|
2048
3081
|
user: config.user,
|
|
@@ -2050,24 +3083,22 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2050
3083
|
port: config.port,
|
|
2051
3084
|
options: config.options || { encrypt: true, trustServerCertificate: true }
|
|
2052
3085
|
});
|
|
2053
|
-
const legacyEvals = new LegacyEvalsMSSQL({ pool: this.pool, schema: this.schema });
|
|
2054
3086
|
const operations = new StoreOperationsMSSQL({ pool: this.pool, schemaName: this.schema });
|
|
2055
3087
|
const scores = new ScoresMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2056
|
-
const traces = new TracesMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2057
3088
|
const workflows = new WorkflowsMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2058
3089
|
const memory = new MemoryMSSQL({ pool: this.pool, schema: this.schema, operations });
|
|
3090
|
+
const observability = new ObservabilityMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2059
3091
|
this.stores = {
|
|
2060
3092
|
operations,
|
|
2061
3093
|
scores,
|
|
2062
|
-
traces,
|
|
2063
3094
|
workflows,
|
|
2064
|
-
|
|
2065
|
-
|
|
3095
|
+
memory,
|
|
3096
|
+
observability
|
|
2066
3097
|
};
|
|
2067
3098
|
} catch (e) {
|
|
2068
3099
|
throw new error.MastraError(
|
|
2069
3100
|
{
|
|
2070
|
-
id: "
|
|
3101
|
+
id: storage.createStorageErrorId("MSSQL", "INITIALIZATION", "FAILED"),
|
|
2071
3102
|
domain: error.ErrorDomain.STORAGE,
|
|
2072
3103
|
category: error.ErrorCategory.USER
|
|
2073
3104
|
},
|
|
@@ -2082,11 +3113,16 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2082
3113
|
try {
|
|
2083
3114
|
await this.isConnected;
|
|
2084
3115
|
await super.init();
|
|
3116
|
+
try {
|
|
3117
|
+
await this.stores.operations.createAutomaticIndexes();
|
|
3118
|
+
} catch (indexError) {
|
|
3119
|
+
this.logger?.warn?.("Failed to create indexes:", indexError);
|
|
3120
|
+
}
|
|
2085
3121
|
} catch (error$1) {
|
|
2086
3122
|
this.isConnected = null;
|
|
2087
3123
|
throw new error.MastraError(
|
|
2088
3124
|
{
|
|
2089
|
-
id: "
|
|
3125
|
+
id: storage.createStorageErrorId("MSSQL", "INIT", "FAILED"),
|
|
2090
3126
|
domain: error.ErrorDomain.STORAGE,
|
|
2091
3127
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2092
3128
|
},
|
|
@@ -2108,28 +3144,12 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2108
3144
|
resourceWorkingMemory: true,
|
|
2109
3145
|
hasColumn: true,
|
|
2110
3146
|
createTable: true,
|
|
2111
|
-
deleteMessages: true
|
|
3147
|
+
deleteMessages: true,
|
|
3148
|
+
listScoresBySpan: true,
|
|
3149
|
+
observabilityInstance: true,
|
|
3150
|
+
indexManagement: true
|
|
2112
3151
|
};
|
|
2113
3152
|
}
|
|
2114
|
-
/** @deprecated use getEvals instead */
|
|
2115
|
-
async getEvalsByAgentName(agentName, type) {
|
|
2116
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2117
|
-
}
|
|
2118
|
-
async getEvals(options = {}) {
|
|
2119
|
-
return this.stores.legacyEvals.getEvals(options);
|
|
2120
|
-
}
|
|
2121
|
-
/**
|
|
2122
|
-
* @deprecated use getTracesPaginated instead
|
|
2123
|
-
*/
|
|
2124
|
-
async getTraces(args) {
|
|
2125
|
-
return this.stores.traces.getTraces(args);
|
|
2126
|
-
}
|
|
2127
|
-
async getTracesPaginated(args) {
|
|
2128
|
-
return this.stores.traces.getTracesPaginated(args);
|
|
2129
|
-
}
|
|
2130
|
-
async batchTraceInsert({ records }) {
|
|
2131
|
-
return this.stores.traces.batchTraceInsert({ records });
|
|
2132
|
-
}
|
|
2133
3153
|
async createTable({
|
|
2134
3154
|
tableName,
|
|
2135
3155
|
schema
|
|
@@ -2164,15 +3184,6 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2164
3184
|
async getThreadById({ threadId }) {
|
|
2165
3185
|
return this.stores.memory.getThreadById({ threadId });
|
|
2166
3186
|
}
|
|
2167
|
-
/**
|
|
2168
|
-
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
2169
|
-
*/
|
|
2170
|
-
async getThreadsByResourceId(args) {
|
|
2171
|
-
return this.stores.memory.getThreadsByResourceId(args);
|
|
2172
|
-
}
|
|
2173
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
2174
|
-
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2175
|
-
}
|
|
2176
3187
|
async saveThread({ thread }) {
|
|
2177
3188
|
return this.stores.memory.saveThread({ thread });
|
|
2178
3189
|
}
|
|
@@ -2186,11 +3197,8 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2186
3197
|
async deleteThread({ threadId }) {
|
|
2187
3198
|
return this.stores.memory.deleteThread({ threadId });
|
|
2188
3199
|
}
|
|
2189
|
-
async
|
|
2190
|
-
return this.stores.memory.
|
|
2191
|
-
}
|
|
2192
|
-
async getMessagesPaginated(args) {
|
|
2193
|
-
return this.stores.memory.getMessagesPaginated(args);
|
|
3200
|
+
async listMessagesById({ messageIds }) {
|
|
3201
|
+
return this.stores.memory.listMessagesById({ messageIds });
|
|
2194
3202
|
}
|
|
2195
3203
|
async saveMessages(args) {
|
|
2196
3204
|
return this.stores.memory.saveMessages(args);
|
|
@@ -2219,12 +3227,29 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2219
3227
|
/**
|
|
2220
3228
|
* Workflows
|
|
2221
3229
|
*/
|
|
3230
|
+
async updateWorkflowResults({
|
|
3231
|
+
workflowName,
|
|
3232
|
+
runId,
|
|
3233
|
+
stepId,
|
|
3234
|
+
result,
|
|
3235
|
+
requestContext
|
|
3236
|
+
}) {
|
|
3237
|
+
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
3238
|
+
}
|
|
3239
|
+
async updateWorkflowState({
|
|
3240
|
+
workflowName,
|
|
3241
|
+
runId,
|
|
3242
|
+
opts
|
|
3243
|
+
}) {
|
|
3244
|
+
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
3245
|
+
}
|
|
2222
3246
|
async persistWorkflowSnapshot({
|
|
2223
3247
|
workflowName,
|
|
2224
3248
|
runId,
|
|
3249
|
+
resourceId,
|
|
2225
3250
|
snapshot
|
|
2226
3251
|
}) {
|
|
2227
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
3252
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
2228
3253
|
}
|
|
2229
3254
|
async loadWorkflowSnapshot({
|
|
2230
3255
|
workflowName,
|
|
@@ -2232,15 +3257,8 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2232
3257
|
}) {
|
|
2233
3258
|
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
2234
3259
|
}
|
|
2235
|
-
async
|
|
2236
|
-
|
|
2237
|
-
fromDate,
|
|
2238
|
-
toDate,
|
|
2239
|
-
limit,
|
|
2240
|
-
offset,
|
|
2241
|
-
resourceId
|
|
2242
|
-
} = {}) {
|
|
2243
|
-
return this.stores.workflows.getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
|
|
3260
|
+
async listWorkflowRuns(args = {}) {
|
|
3261
|
+
return this.stores.workflows.listWorkflowRuns(args);
|
|
2244
3262
|
}
|
|
2245
3263
|
async getWorkflowRunById({
|
|
2246
3264
|
runId,
|
|
@@ -2248,41 +3266,114 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2248
3266
|
}) {
|
|
2249
3267
|
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
2250
3268
|
}
|
|
3269
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
3270
|
+
return this.stores.workflows.deleteWorkflowRunById({ runId, workflowName });
|
|
3271
|
+
}
|
|
2251
3272
|
async close() {
|
|
2252
3273
|
await this.pool.close();
|
|
2253
3274
|
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Index Management
|
|
3277
|
+
*/
|
|
3278
|
+
async createIndex(options) {
|
|
3279
|
+
return this.stores.operations.createIndex(options);
|
|
3280
|
+
}
|
|
3281
|
+
async listIndexes(tableName) {
|
|
3282
|
+
return this.stores.operations.listIndexes(tableName);
|
|
3283
|
+
}
|
|
3284
|
+
async describeIndex(indexName) {
|
|
3285
|
+
return this.stores.operations.describeIndex(indexName);
|
|
3286
|
+
}
|
|
3287
|
+
async dropIndex(indexName) {
|
|
3288
|
+
return this.stores.operations.dropIndex(indexName);
|
|
3289
|
+
}
|
|
3290
|
+
/**
|
|
3291
|
+
* Tracing / Observability
|
|
3292
|
+
*/
|
|
3293
|
+
getObservabilityStore() {
|
|
3294
|
+
if (!this.stores.observability) {
|
|
3295
|
+
throw new error.MastraError({
|
|
3296
|
+
id: storage.createStorageErrorId("MSSQL", "OBSERVABILITY", "NOT_INITIALIZED"),
|
|
3297
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3298
|
+
category: error.ErrorCategory.SYSTEM,
|
|
3299
|
+
text: "Observability storage is not initialized"
|
|
3300
|
+
});
|
|
3301
|
+
}
|
|
3302
|
+
return this.stores.observability;
|
|
3303
|
+
}
|
|
3304
|
+
async createSpan(span) {
|
|
3305
|
+
return this.getObservabilityStore().createSpan(span);
|
|
3306
|
+
}
|
|
3307
|
+
async updateSpan({
|
|
3308
|
+
spanId,
|
|
3309
|
+
traceId,
|
|
3310
|
+
updates
|
|
3311
|
+
}) {
|
|
3312
|
+
return this.getObservabilityStore().updateSpan({ spanId, traceId, updates });
|
|
3313
|
+
}
|
|
3314
|
+
async getTrace(traceId) {
|
|
3315
|
+
return this.getObservabilityStore().getTrace(traceId);
|
|
3316
|
+
}
|
|
3317
|
+
async getTracesPaginated(args) {
|
|
3318
|
+
return this.getObservabilityStore().getTracesPaginated(args);
|
|
3319
|
+
}
|
|
3320
|
+
async batchCreateSpans(args) {
|
|
3321
|
+
return this.getObservabilityStore().batchCreateSpans(args);
|
|
3322
|
+
}
|
|
3323
|
+
async batchUpdateSpans(args) {
|
|
3324
|
+
return this.getObservabilityStore().batchUpdateSpans(args);
|
|
3325
|
+
}
|
|
3326
|
+
async batchDeleteTraces(args) {
|
|
3327
|
+
return this.getObservabilityStore().batchDeleteTraces(args);
|
|
3328
|
+
}
|
|
2254
3329
|
/**
|
|
2255
3330
|
* Scorers
|
|
2256
3331
|
*/
|
|
2257
3332
|
async getScoreById({ id: _id }) {
|
|
2258
3333
|
return this.stores.scores.getScoreById({ id: _id });
|
|
2259
3334
|
}
|
|
2260
|
-
async
|
|
3335
|
+
async listScoresByScorerId({
|
|
2261
3336
|
scorerId: _scorerId,
|
|
2262
|
-
pagination: _pagination
|
|
3337
|
+
pagination: _pagination,
|
|
3338
|
+
entityId: _entityId,
|
|
3339
|
+
entityType: _entityType,
|
|
3340
|
+
source: _source
|
|
2263
3341
|
}) {
|
|
2264
|
-
return this.stores.scores.
|
|
3342
|
+
return this.stores.scores.listScoresByScorerId({
|
|
3343
|
+
scorerId: _scorerId,
|
|
3344
|
+
pagination: _pagination,
|
|
3345
|
+
entityId: _entityId,
|
|
3346
|
+
entityType: _entityType,
|
|
3347
|
+
source: _source
|
|
3348
|
+
});
|
|
2265
3349
|
}
|
|
2266
|
-
async saveScore(
|
|
2267
|
-
return this.stores.scores.saveScore(
|
|
3350
|
+
async saveScore(score) {
|
|
3351
|
+
return this.stores.scores.saveScore(score);
|
|
2268
3352
|
}
|
|
2269
|
-
async
|
|
3353
|
+
async listScoresByRunId({
|
|
2270
3354
|
runId: _runId,
|
|
2271
3355
|
pagination: _pagination
|
|
2272
3356
|
}) {
|
|
2273
|
-
return this.stores.scores.
|
|
3357
|
+
return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
|
|
2274
3358
|
}
|
|
2275
|
-
async
|
|
3359
|
+
async listScoresByEntityId({
|
|
2276
3360
|
entityId: _entityId,
|
|
2277
3361
|
entityType: _entityType,
|
|
2278
3362
|
pagination: _pagination
|
|
2279
3363
|
}) {
|
|
2280
|
-
return this.stores.scores.
|
|
3364
|
+
return this.stores.scores.listScoresByEntityId({
|
|
2281
3365
|
entityId: _entityId,
|
|
2282
3366
|
entityType: _entityType,
|
|
2283
3367
|
pagination: _pagination
|
|
2284
3368
|
});
|
|
2285
3369
|
}
|
|
3370
|
+
async listScoresBySpan({
|
|
3371
|
+
traceId,
|
|
3372
|
+
spanId,
|
|
3373
|
+
pagination: _pagination
|
|
3374
|
+
}) {
|
|
3375
|
+
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination: _pagination });
|
|
3376
|
+
}
|
|
2286
3377
|
};
|
|
2287
3378
|
|
|
2288
3379
|
exports.MSSQLStore = MSSQLStore;
|