@mastra/mssql 0.0.0-mssql-store-20250804200341 → 0.0.0-netlify-no-bundle-20251127120354
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 +938 -3
- package/README.md +324 -37
- package/dist/index.cjs +1741 -688
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1743 -690
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +16 -37
- 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 +25 -11
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +91 -73
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +31 -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 -289
- 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 -22
- package/vitest.config.ts +0 -12
package/dist/index.cjs
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
var error = require('@mastra/core/error');
|
|
4
4
|
var storage = require('@mastra/core/storage');
|
|
5
5
|
var sql2 = require('mssql');
|
|
6
|
-
var utils = require('@mastra/core/utils');
|
|
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
|
|
|
@@ -20,154 +22,71 @@ 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
|
}
|
|
33
|
+
return filters;
|
|
34
|
+
}
|
|
35
|
+
function prepareWhereClause(filters, _schema) {
|
|
36
|
+
const conditions = [];
|
|
37
|
+
const params = {};
|
|
38
|
+
let paramIndex = 1;
|
|
39
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
40
|
+
if (value === void 0) return;
|
|
41
|
+
const paramName = `p${paramIndex++}`;
|
|
42
|
+
if (key.endsWith("_gte")) {
|
|
43
|
+
const fieldName = key.slice(0, -4);
|
|
44
|
+
conditions.push(`[${utils.parseSqlIdentifier(fieldName, "field name")}] >= @${paramName}`);
|
|
45
|
+
params[paramName] = value instanceof Date ? value.toISOString() : value;
|
|
46
|
+
} else if (key.endsWith("_lte")) {
|
|
47
|
+
const fieldName = key.slice(0, -4);
|
|
48
|
+
conditions.push(`[${utils.parseSqlIdentifier(fieldName, "field name")}] <= @${paramName}`);
|
|
49
|
+
params[paramName] = value instanceof Date ? value.toISOString() : value;
|
|
50
|
+
} else if (value === null) {
|
|
51
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IS NULL`);
|
|
52
|
+
} else {
|
|
53
|
+
conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
|
|
54
|
+
params[paramName] = value instanceof Date ? value.toISOString() : value;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
39
57
|
return {
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
58
|
+
sql: conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "",
|
|
59
|
+
params
|
|
50
60
|
};
|
|
51
61
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
query += " AND test_info IS NOT NULL AND JSON_VALUE(test_info, '$.testPath') IS NOT NULL";
|
|
66
|
-
} else if (type === "live") {
|
|
67
|
-
query += " AND (test_info IS NULL OR JSON_VALUE(test_info, '$.testPath') IS NULL)";
|
|
68
|
-
}
|
|
69
|
-
query += " ORDER BY created_at DESC";
|
|
70
|
-
const request = this.pool.request();
|
|
71
|
-
request.input("p1", agentName);
|
|
72
|
-
const result = await request.query(query);
|
|
73
|
-
const rows = result.recordset;
|
|
74
|
-
return typeof transformEvalRow === "function" ? rows?.map((row) => transformEvalRow(row)) ?? [] : rows ?? [];
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if (error && error.number === 208 && error.message && error.message.includes("Invalid object name")) {
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
console.error("Failed to get evals for the specified agent: " + error?.message);
|
|
80
|
-
throw error;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async getEvals(options = {}) {
|
|
84
|
-
const { agentName, type, page = 0, perPage = 100, dateRange } = options;
|
|
85
|
-
const fromDate = dateRange?.start;
|
|
86
|
-
const toDate = dateRange?.end;
|
|
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);
|
|
118
|
-
}
|
|
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
|
-
};
|
|
62
|
+
function transformFromSqlRow({
|
|
63
|
+
tableName,
|
|
64
|
+
sqlRow
|
|
65
|
+
}) {
|
|
66
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
67
|
+
const result = {};
|
|
68
|
+
Object.entries(sqlRow).forEach(([key, value]) => {
|
|
69
|
+
const columnSchema = schema?.[key];
|
|
70
|
+
if (columnSchema?.type === "jsonb" && typeof value === "string") {
|
|
71
|
+
try {
|
|
72
|
+
result[key] = JSON.parse(value);
|
|
73
|
+
} catch {
|
|
74
|
+
result[key] = value;
|
|
130
75
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
req.input("offset", offset);
|
|
140
|
-
req.input("perPage", perPage);
|
|
141
|
-
const result = await req.query(dataQuery);
|
|
142
|
-
const rows = result.recordset;
|
|
143
|
-
return {
|
|
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;
|
|
76
|
+
} else if (columnSchema?.type === "timestamp" && value && typeof value === "string") {
|
|
77
|
+
result[key] = new Date(value);
|
|
78
|
+
} else if (columnSchema?.type === "timestamp" && value instanceof Date) {
|
|
79
|
+
result[key] = value;
|
|
80
|
+
} else if (columnSchema?.type === "boolean") {
|
|
81
|
+
result[key] = Boolean(value);
|
|
82
|
+
} else {
|
|
83
|
+
result[key] = value;
|
|
168
84
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
85
|
+
});
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/storage/domains/memory/index.ts
|
|
171
90
|
var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
172
91
|
pool;
|
|
173
92
|
schema;
|
|
@@ -185,7 +104,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
185
104
|
});
|
|
186
105
|
const cleanMessages = messagesWithParsedContent.map(({ seq_id, ...rest }) => rest);
|
|
187
106
|
const list = new agent.MessageList().add(cleanMessages, "memory");
|
|
188
|
-
return format === "v2" ? list.get.all.
|
|
107
|
+
return format === "v2" ? list.get.all.db() : list.get.all.v1();
|
|
189
108
|
}
|
|
190
109
|
constructor({
|
|
191
110
|
pool,
|
|
@@ -199,7 +118,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
199
118
|
}
|
|
200
119
|
async getThreadById({ threadId }) {
|
|
201
120
|
try {
|
|
202
|
-
const
|
|
121
|
+
const sql5 = `SELECT
|
|
203
122
|
id,
|
|
204
123
|
[resourceId],
|
|
205
124
|
title,
|
|
@@ -210,7 +129,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
210
129
|
WHERE id = @threadId`;
|
|
211
130
|
const request = this.pool.request();
|
|
212
131
|
request.input("threadId", threadId);
|
|
213
|
-
const resultSet = await request.query(
|
|
132
|
+
const resultSet = await request.query(sql5);
|
|
214
133
|
const thread = resultSet.recordset[0] || null;
|
|
215
134
|
if (!thread) {
|
|
216
135
|
return null;
|
|
@@ -235,11 +154,24 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
235
154
|
);
|
|
236
155
|
}
|
|
237
156
|
}
|
|
238
|
-
async
|
|
239
|
-
const { resourceId, page = 0, perPage: perPageInput, orderBy
|
|
157
|
+
async listThreadsByResourceId(args) {
|
|
158
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
159
|
+
if (page < 0) {
|
|
160
|
+
throw new error.MastraError({
|
|
161
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_INVALID_PAGE",
|
|
162
|
+
domain: error.ErrorDomain.STORAGE,
|
|
163
|
+
category: error.ErrorCategory.USER,
|
|
164
|
+
text: "Page number must be non-negative",
|
|
165
|
+
details: {
|
|
166
|
+
resourceId,
|
|
167
|
+
page
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
172
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
173
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
240
174
|
try {
|
|
241
|
-
const perPage = perPageInput !== void 0 ? perPageInput : 100;
|
|
242
|
-
const currentOffset = page * perPage;
|
|
243
175
|
const baseQuery = `FROM ${getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) })} WHERE [resourceId] = @resourceId`;
|
|
244
176
|
const countQuery = `SELECT COUNT(*) as count ${baseQuery}`;
|
|
245
177
|
const countRequest = this.pool.request();
|
|
@@ -251,16 +183,22 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
251
183
|
threads: [],
|
|
252
184
|
total: 0,
|
|
253
185
|
page,
|
|
254
|
-
perPage,
|
|
186
|
+
perPage: perPageForResponse,
|
|
255
187
|
hasMore: false
|
|
256
188
|
};
|
|
257
189
|
}
|
|
258
|
-
const orderByField =
|
|
259
|
-
const
|
|
190
|
+
const orderByField = field === "createdAt" ? "[createdAt]" : "[updatedAt]";
|
|
191
|
+
const dir = (direction || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
|
|
192
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
193
|
+
const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir} OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
260
194
|
const dataRequest = this.pool.request();
|
|
261
195
|
dataRequest.input("resourceId", resourceId);
|
|
262
|
-
dataRequest.input("
|
|
263
|
-
|
|
196
|
+
dataRequest.input("offset", offset);
|
|
197
|
+
if (limitValue > 2147483647) {
|
|
198
|
+
dataRequest.input("perPage", sql2__default.default.BigInt, limitValue);
|
|
199
|
+
} else {
|
|
200
|
+
dataRequest.input("perPage", limitValue);
|
|
201
|
+
}
|
|
264
202
|
const rowsResult = await dataRequest.query(dataQuery);
|
|
265
203
|
const rows = rowsResult.recordset || [];
|
|
266
204
|
const threads = rows.map((thread) => ({
|
|
@@ -273,13 +211,13 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
273
211
|
threads,
|
|
274
212
|
total,
|
|
275
213
|
page,
|
|
276
|
-
perPage,
|
|
277
|
-
hasMore:
|
|
214
|
+
perPage: perPageForResponse,
|
|
215
|
+
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
278
216
|
};
|
|
279
217
|
} catch (error$1) {
|
|
280
218
|
const mastraError = new error.MastraError(
|
|
281
219
|
{
|
|
282
|
-
id: "
|
|
220
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_LIST_THREADS_BY_RESOURCE_ID_FAILED",
|
|
283
221
|
domain: error.ErrorDomain.STORAGE,
|
|
284
222
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
285
223
|
details: {
|
|
@@ -291,7 +229,13 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
291
229
|
);
|
|
292
230
|
this.logger?.error?.(mastraError.toString());
|
|
293
231
|
this.logger?.trackException?.(mastraError);
|
|
294
|
-
return {
|
|
232
|
+
return {
|
|
233
|
+
threads: [],
|
|
234
|
+
total: 0,
|
|
235
|
+
page,
|
|
236
|
+
perPage: perPageForResponse,
|
|
237
|
+
hasMore: false
|
|
238
|
+
};
|
|
295
239
|
}
|
|
296
240
|
}
|
|
297
241
|
async saveThread({ thread }) {
|
|
@@ -313,7 +257,12 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
313
257
|
req.input("id", thread.id);
|
|
314
258
|
req.input("resourceId", thread.resourceId);
|
|
315
259
|
req.input("title", thread.title);
|
|
316
|
-
|
|
260
|
+
const metadata = thread.metadata ? JSON.stringify(thread.metadata) : null;
|
|
261
|
+
if (metadata === null) {
|
|
262
|
+
req.input("metadata", sql2__default.default.NVarChar, null);
|
|
263
|
+
} else {
|
|
264
|
+
req.input("metadata", metadata);
|
|
265
|
+
}
|
|
317
266
|
req.input("createdAt", sql2__default.default.DateTime2, thread.createdAt);
|
|
318
267
|
req.input("updatedAt", sql2__default.default.DateTime2, thread.updatedAt);
|
|
319
268
|
await req.query(mergeSql);
|
|
@@ -332,30 +281,6 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
332
281
|
);
|
|
333
282
|
}
|
|
334
283
|
}
|
|
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
284
|
/**
|
|
360
285
|
* Updates a thread's title and metadata, merging with existing metadata. Returns the updated thread.
|
|
361
286
|
*/
|
|
@@ -383,7 +308,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
383
308
|
};
|
|
384
309
|
try {
|
|
385
310
|
const table = getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) });
|
|
386
|
-
const
|
|
311
|
+
const sql5 = `UPDATE ${table}
|
|
387
312
|
SET title = @title,
|
|
388
313
|
metadata = @metadata,
|
|
389
314
|
[updatedAt] = @updatedAt
|
|
@@ -394,7 +319,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
394
319
|
req.input("title", title);
|
|
395
320
|
req.input("metadata", JSON.stringify(mergedMetadata));
|
|
396
321
|
req.input("updatedAt", /* @__PURE__ */ new Date());
|
|
397
|
-
const result = await req.query(
|
|
322
|
+
const result = await req.query(sql5);
|
|
398
323
|
let thread = result.recordset && result.recordset[0];
|
|
399
324
|
if (thread && "seq_id" in thread) {
|
|
400
325
|
const { seq_id, ...rest } = thread;
|
|
@@ -464,10 +389,9 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
464
389
|
}
|
|
465
390
|
async _getIncludedMessages({
|
|
466
391
|
threadId,
|
|
467
|
-
|
|
468
|
-
orderByStatement
|
|
392
|
+
include
|
|
469
393
|
}) {
|
|
470
|
-
|
|
394
|
+
if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
|
|
471
395
|
if (!include) return null;
|
|
472
396
|
const unionQueries = [];
|
|
473
397
|
const paramValues = [];
|
|
@@ -492,7 +416,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
492
416
|
m.[resourceId],
|
|
493
417
|
m.seq_id
|
|
494
418
|
FROM (
|
|
495
|
-
SELECT *, ROW_NUMBER() OVER (
|
|
419
|
+
SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
|
|
496
420
|
FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
|
|
497
421
|
WHERE [thread_id] = ${pThreadId}
|
|
498
422
|
) AS m
|
|
@@ -500,15 +424,17 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
500
424
|
OR EXISTS (
|
|
501
425
|
SELECT 1
|
|
502
426
|
FROM (
|
|
503
|
-
SELECT *, ROW_NUMBER() OVER (
|
|
427
|
+
SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
|
|
504
428
|
FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
|
|
505
429
|
WHERE [thread_id] = ${pThreadId}
|
|
506
430
|
) AS target
|
|
507
431
|
WHERE target.id = ${pId}
|
|
508
432
|
AND (
|
|
509
|
-
|
|
433
|
+
-- Get previous messages (messages that come BEFORE the target)
|
|
434
|
+
(m.row_num < target.row_num AND m.row_num >= target.row_num - ${pPrev})
|
|
510
435
|
OR
|
|
511
|
-
|
|
436
|
+
-- Get next messages (messages that come AFTER the target)
|
|
437
|
+
(m.row_num > target.row_num AND m.row_num <= target.row_num + ${pNext})
|
|
512
438
|
)
|
|
513
439
|
)
|
|
514
440
|
`
|
|
@@ -537,33 +463,16 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
537
463
|
});
|
|
538
464
|
return dedupedRows;
|
|
539
465
|
}
|
|
540
|
-
async
|
|
541
|
-
|
|
466
|
+
async listMessagesById({ messageIds }) {
|
|
467
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
542
468
|
const selectStatement = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId`;
|
|
543
469
|
const orderByStatement = `ORDER BY [seq_id] DESC`;
|
|
544
|
-
const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
545
470
|
try {
|
|
546
471
|
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`;
|
|
472
|
+
let query = `${selectStatement} FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })} WHERE [id] IN (${messageIds.map((_, i) => `@id${i}`).join(", ")})`;
|
|
556
473
|
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);
|
|
474
|
+
messageIds.forEach((id, i) => request.input(`id${i}`, id));
|
|
475
|
+
query += ` ${orderByStatement}`;
|
|
567
476
|
const result = await request.query(query);
|
|
568
477
|
const remainingRows = result.recordset || [];
|
|
569
478
|
rows.push(...remainingRows);
|
|
@@ -571,116 +480,171 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
571
480
|
const timeDiff = a.seq_id - b.seq_id;
|
|
572
481
|
return timeDiff;
|
|
573
482
|
});
|
|
574
|
-
|
|
575
|
-
|
|
483
|
+
const messagesWithParsedContent = rows.map((row) => {
|
|
484
|
+
if (typeof row.content === "string") {
|
|
485
|
+
try {
|
|
486
|
+
return { ...row, content: JSON.parse(row.content) };
|
|
487
|
+
} catch {
|
|
488
|
+
return row;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return row;
|
|
492
|
+
});
|
|
493
|
+
const cleanMessages = messagesWithParsedContent.map(({ seq_id, ...rest }) => rest);
|
|
494
|
+
const list = new agent.MessageList().add(cleanMessages, "memory");
|
|
495
|
+
return { messages: list.get.all.db() };
|
|
576
496
|
} catch (error$1) {
|
|
577
497
|
const mastraError = new error.MastraError(
|
|
578
498
|
{
|
|
579
|
-
id: "
|
|
499
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_LIST_MESSAGES_BY_ID_FAILED",
|
|
580
500
|
domain: error.ErrorDomain.STORAGE,
|
|
581
501
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
582
502
|
details: {
|
|
583
|
-
|
|
503
|
+
messageIds: JSON.stringify(messageIds)
|
|
584
504
|
}
|
|
585
505
|
},
|
|
586
506
|
error$1
|
|
587
507
|
);
|
|
588
508
|
this.logger?.error?.(mastraError.toString());
|
|
589
|
-
this.logger?.trackException(mastraError);
|
|
590
|
-
return [];
|
|
509
|
+
this.logger?.trackException?.(mastraError);
|
|
510
|
+
return { messages: [] };
|
|
591
511
|
}
|
|
592
512
|
}
|
|
593
|
-
async
|
|
594
|
-
const { threadId,
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
513
|
+
async listMessages(args) {
|
|
514
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
515
|
+
if (!threadId.trim()) {
|
|
516
|
+
throw new error.MastraError(
|
|
517
|
+
{
|
|
518
|
+
id: "STORAGE_MSSQL_LIST_MESSAGES_INVALID_THREAD_ID",
|
|
519
|
+
domain: error.ErrorDomain.STORAGE,
|
|
520
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
521
|
+
details: { threadId }
|
|
522
|
+
},
|
|
523
|
+
new Error("threadId must be a non-empty string")
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
if (page < 0) {
|
|
527
|
+
throw new error.MastraError({
|
|
528
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_INVALID_PAGE",
|
|
529
|
+
domain: error.ErrorDomain.STORAGE,
|
|
530
|
+
category: error.ErrorCategory.USER,
|
|
531
|
+
text: "Page number must be non-negative",
|
|
532
|
+
details: {
|
|
533
|
+
threadId,
|
|
534
|
+
page
|
|
535
|
+
}
|
|
536
|
+
});
|
|
599
537
|
}
|
|
538
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
539
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
600
540
|
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);
|
|
541
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
542
|
+
const orderByStatement = `ORDER BY [${field}] ${direction}, [seq_id] ${direction}`;
|
|
543
|
+
const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
|
|
544
|
+
const baseQuery = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId FROM ${tableName}`;
|
|
545
|
+
const filters = {
|
|
546
|
+
thread_id: threadId,
|
|
547
|
+
...resourceId ? { resourceId } : {},
|
|
548
|
+
...buildDateRangeFilter(filter?.dateRange, "createdAt")
|
|
549
|
+
};
|
|
550
|
+
const { sql: actualWhereClause = "", params: whereParams } = prepareWhereClause(
|
|
551
|
+
filters);
|
|
552
|
+
const bindWhereParams = (req) => {
|
|
553
|
+
Object.entries(whereParams).forEach(([paramName, paramValue]) => req.input(paramName, paramValue));
|
|
554
|
+
};
|
|
555
|
+
const countRequest = this.pool.request();
|
|
556
|
+
bindWhereParams(countRequest);
|
|
557
|
+
const countResult = await countRequest.query(`SELECT COUNT(*) as total FROM ${tableName}${actualWhereClause}`);
|
|
628
558
|
const total = parseInt(countResult.recordset[0]?.total, 10) || 0;
|
|
629
|
-
|
|
630
|
-
const
|
|
559
|
+
const fetchBaseMessages = async () => {
|
|
560
|
+
const request = this.pool.request();
|
|
561
|
+
bindWhereParams(request);
|
|
562
|
+
if (perPageInput === false) {
|
|
563
|
+
const result2 = await request.query(`${baseQuery}${actualWhereClause} ${orderByStatement}`);
|
|
564
|
+
return result2.recordset || [];
|
|
565
|
+
}
|
|
566
|
+
request.input("offset", offset);
|
|
567
|
+
request.input("limit", perPage > 2147483647 ? sql2__default.default.BigInt : sql2__default.default.Int, perPage);
|
|
568
|
+
const result = await request.query(
|
|
569
|
+
`${baseQuery}${actualWhereClause} ${orderByStatement} OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
|
|
570
|
+
);
|
|
571
|
+
return result.recordset || [];
|
|
572
|
+
};
|
|
573
|
+
const baseRows = perPage === 0 ? [] : await fetchBaseMessages();
|
|
574
|
+
const messages = [...baseRows];
|
|
575
|
+
const seqById = /* @__PURE__ */ new Map();
|
|
576
|
+
messages.forEach((msg) => {
|
|
577
|
+
if (typeof msg.seq_id === "number") seqById.set(msg.id, msg.seq_id);
|
|
578
|
+
});
|
|
579
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
631
580
|
return {
|
|
632
|
-
messages:
|
|
633
|
-
total:
|
|
634
|
-
page
|
|
635
|
-
perPage,
|
|
581
|
+
messages: [],
|
|
582
|
+
total: 0,
|
|
583
|
+
page,
|
|
584
|
+
perPage: perPageForResponse,
|
|
636
585
|
hasMore: false
|
|
637
586
|
};
|
|
638
587
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
588
|
+
if (include?.length) {
|
|
589
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
590
|
+
const includeMessages = await this._getIncludedMessages({ threadId, include });
|
|
591
|
+
includeMessages?.forEach((msg) => {
|
|
592
|
+
if (!messageIds.has(msg.id)) {
|
|
593
|
+
messages.push(msg);
|
|
594
|
+
messageIds.add(msg.id);
|
|
595
|
+
if (typeof msg.seq_id === "number") seqById.set(msg.id, msg.seq_id);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
const parsed = this._parseAndFormatMessages(messages, "v2");
|
|
600
|
+
const mult = direction === "ASC" ? 1 : -1;
|
|
601
|
+
const finalMessages = parsed.sort((a, b) => {
|
|
602
|
+
const aVal = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
603
|
+
const bVal = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
604
|
+
if (aVal == null || bVal == null) {
|
|
605
|
+
return aVal == null && bVal == null ? a.id.localeCompare(b.id) : aVal == null ? 1 : -1;
|
|
606
|
+
}
|
|
607
|
+
const diff = (typeof aVal === "number" && typeof bVal === "number" ? aVal - bVal : String(aVal).localeCompare(String(bVal))) * mult;
|
|
608
|
+
if (diff !== 0) return diff;
|
|
609
|
+
const seqA = seqById.get(a.id);
|
|
610
|
+
const seqB = seqById.get(b.id);
|
|
611
|
+
return seqA != null && seqB != null ? (seqA - seqB) * mult : a.id.localeCompare(b.id);
|
|
612
|
+
});
|
|
613
|
+
const returnedThreadMessageCount = finalMessages.filter((m) => m.threadId === threadId).length;
|
|
614
|
+
const hasMore = perPageInput !== false && returnedThreadMessageCount < total && offset + perPage < total;
|
|
654
615
|
return {
|
|
655
|
-
messages:
|
|
656
|
-
total
|
|
657
|
-
page
|
|
658
|
-
perPage,
|
|
659
|
-
hasMore
|
|
616
|
+
messages: finalMessages,
|
|
617
|
+
total,
|
|
618
|
+
page,
|
|
619
|
+
perPage: perPageForResponse,
|
|
620
|
+
hasMore
|
|
660
621
|
};
|
|
661
622
|
} catch (error$1) {
|
|
662
623
|
const mastraError = new error.MastraError(
|
|
663
624
|
{
|
|
664
|
-
id: "
|
|
625
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_LIST_MESSAGES_FAILED",
|
|
665
626
|
domain: error.ErrorDomain.STORAGE,
|
|
666
627
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
667
628
|
details: {
|
|
668
629
|
threadId,
|
|
669
|
-
|
|
630
|
+
resourceId: resourceId ?? ""
|
|
670
631
|
}
|
|
671
632
|
},
|
|
672
633
|
error$1
|
|
673
634
|
);
|
|
674
635
|
this.logger?.error?.(mastraError.toString());
|
|
675
|
-
this.logger?.trackException(mastraError);
|
|
676
|
-
return {
|
|
636
|
+
this.logger?.trackException?.(mastraError);
|
|
637
|
+
return {
|
|
638
|
+
messages: [],
|
|
639
|
+
total: 0,
|
|
640
|
+
page,
|
|
641
|
+
perPage: perPageForResponse,
|
|
642
|
+
hasMore: false
|
|
643
|
+
};
|
|
677
644
|
}
|
|
678
645
|
}
|
|
679
|
-
async saveMessages({
|
|
680
|
-
messages
|
|
681
|
-
format
|
|
682
|
-
}) {
|
|
683
|
-
if (messages.length === 0) return messages;
|
|
646
|
+
async saveMessages({ messages }) {
|
|
647
|
+
if (messages.length === 0) return { messages: [] };
|
|
684
648
|
const threadId = messages[0]?.threadId;
|
|
685
649
|
if (!threadId) {
|
|
686
650
|
throw new error.MastraError({
|
|
@@ -762,8 +726,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
762
726
|
return message;
|
|
763
727
|
});
|
|
764
728
|
const list = new agent.MessageList().add(messagesWithParsedContent, "memory");
|
|
765
|
-
|
|
766
|
-
return list.get.all.v1();
|
|
729
|
+
return { messages: list.get.all.db() };
|
|
767
730
|
} catch (error$1) {
|
|
768
731
|
throw new error.MastraError(
|
|
769
732
|
{
|
|
@@ -939,8 +902,10 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
939
902
|
return null;
|
|
940
903
|
}
|
|
941
904
|
return {
|
|
942
|
-
|
|
943
|
-
|
|
905
|
+
id: result.id,
|
|
906
|
+
createdAt: result.createdAt,
|
|
907
|
+
updatedAt: result.updatedAt,
|
|
908
|
+
workingMemory: result.workingMemory,
|
|
944
909
|
metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
|
|
945
910
|
};
|
|
946
911
|
} catch (error$1) {
|
|
@@ -954,7 +919,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
954
919
|
error$1
|
|
955
920
|
);
|
|
956
921
|
this.logger?.error?.(mastraError.toString());
|
|
957
|
-
this.logger?.trackException(mastraError);
|
|
922
|
+
this.logger?.trackException?.(mastraError);
|
|
958
923
|
throw mastraError;
|
|
959
924
|
}
|
|
960
925
|
}
|
|
@@ -963,7 +928,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
963
928
|
tableName: storage.TABLE_RESOURCES,
|
|
964
929
|
record: {
|
|
965
930
|
...resource,
|
|
966
|
-
metadata:
|
|
931
|
+
metadata: resource.metadata
|
|
967
932
|
}
|
|
968
933
|
});
|
|
969
934
|
return resource;
|
|
@@ -1021,132 +986,457 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1021
986
|
error$1
|
|
1022
987
|
);
|
|
1023
988
|
this.logger?.error?.(mastraError.toString());
|
|
1024
|
-
this.logger?.trackException(mastraError);
|
|
989
|
+
this.logger?.trackException?.(mastraError);
|
|
1025
990
|
throw mastraError;
|
|
1026
991
|
}
|
|
1027
992
|
}
|
|
1028
993
|
};
|
|
1029
|
-
var
|
|
994
|
+
var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
1030
995
|
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 }) {
|
|
996
|
+
operations;
|
|
997
|
+
schema;
|
|
998
|
+
constructor({
|
|
999
|
+
pool,
|
|
1000
|
+
operations,
|
|
1001
|
+
schema
|
|
1002
|
+
}) {
|
|
1059
1003
|
super();
|
|
1060
1004
|
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;
|
|
1005
|
+
this.operations = operations;
|
|
1006
|
+
this.schema = schema;
|
|
1074
1007
|
}
|
|
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;
|
|
1008
|
+
get tracingStrategy() {
|
|
1009
|
+
return {
|
|
1010
|
+
preferred: "batch-with-updates",
|
|
1011
|
+
supported: ["batch-with-updates", "insert-only"]
|
|
1012
|
+
};
|
|
1111
1013
|
}
|
|
1112
|
-
async
|
|
1014
|
+
async createSpan(span) {
|
|
1113
1015
|
try {
|
|
1114
|
-
const
|
|
1115
|
-
const
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
request.input(`param${i}`, JSON.stringify(value));
|
|
1124
|
-
} else {
|
|
1125
|
-
request.input(`param${i}`, value);
|
|
1126
|
-
}
|
|
1127
|
-
});
|
|
1128
|
-
await request.query(insertSql);
|
|
1016
|
+
const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
|
|
1017
|
+
const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
|
|
1018
|
+
const record = {
|
|
1019
|
+
...span,
|
|
1020
|
+
startedAt,
|
|
1021
|
+
endedAt
|
|
1022
|
+
// Note: createdAt/updatedAt will be set by default values
|
|
1023
|
+
};
|
|
1024
|
+
return this.operations.insert({ tableName: storage.TABLE_SPANS, record });
|
|
1129
1025
|
} catch (error$1) {
|
|
1130
1026
|
throw new error.MastraError(
|
|
1131
1027
|
{
|
|
1132
|
-
id: "
|
|
1028
|
+
id: "MSSQL_STORE_CREATE_SPAN_FAILED",
|
|
1133
1029
|
domain: error.ErrorDomain.STORAGE,
|
|
1134
|
-
category: error.ErrorCategory.
|
|
1030
|
+
category: error.ErrorCategory.USER,
|
|
1135
1031
|
details: {
|
|
1136
|
-
|
|
1032
|
+
spanId: span.spanId,
|
|
1033
|
+
traceId: span.traceId,
|
|
1034
|
+
spanType: span.spanType,
|
|
1035
|
+
spanName: span.name
|
|
1137
1036
|
}
|
|
1138
1037
|
},
|
|
1139
1038
|
error$1
|
|
1140
1039
|
);
|
|
1141
1040
|
}
|
|
1142
1041
|
}
|
|
1143
|
-
async
|
|
1042
|
+
async getTrace(traceId) {
|
|
1043
|
+
try {
|
|
1044
|
+
const tableName = getTableName({
|
|
1045
|
+
indexName: storage.TABLE_SPANS,
|
|
1046
|
+
schemaName: getSchemaName(this.schema)
|
|
1047
|
+
});
|
|
1048
|
+
const request = this.pool.request();
|
|
1049
|
+
request.input("traceId", traceId);
|
|
1050
|
+
const result = await request.query(
|
|
1051
|
+
`SELECT
|
|
1052
|
+
[traceId], [spanId], [parentSpanId], [name], [scope], [spanType],
|
|
1053
|
+
[attributes], [metadata], [links], [input], [output], [error], [isEvent],
|
|
1054
|
+
[startedAt], [endedAt], [createdAt], [updatedAt]
|
|
1055
|
+
FROM ${tableName}
|
|
1056
|
+
WHERE [traceId] = @traceId
|
|
1057
|
+
ORDER BY [startedAt] DESC`
|
|
1058
|
+
);
|
|
1059
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
1060
|
+
return null;
|
|
1061
|
+
}
|
|
1062
|
+
return {
|
|
1063
|
+
traceId,
|
|
1064
|
+
spans: result.recordset.map(
|
|
1065
|
+
(span) => transformFromSqlRow({
|
|
1066
|
+
tableName: storage.TABLE_SPANS,
|
|
1067
|
+
sqlRow: span
|
|
1068
|
+
})
|
|
1069
|
+
)
|
|
1070
|
+
};
|
|
1071
|
+
} catch (error$1) {
|
|
1072
|
+
throw new error.MastraError(
|
|
1073
|
+
{
|
|
1074
|
+
id: "MSSQL_STORE_GET_TRACE_FAILED",
|
|
1075
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1076
|
+
category: error.ErrorCategory.USER,
|
|
1077
|
+
details: {
|
|
1078
|
+
traceId
|
|
1079
|
+
}
|
|
1080
|
+
},
|
|
1081
|
+
error$1
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
async updateSpan({
|
|
1086
|
+
spanId,
|
|
1087
|
+
traceId,
|
|
1088
|
+
updates
|
|
1089
|
+
}) {
|
|
1090
|
+
try {
|
|
1091
|
+
const data = { ...updates };
|
|
1092
|
+
if (data.endedAt instanceof Date) {
|
|
1093
|
+
data.endedAt = data.endedAt.toISOString();
|
|
1094
|
+
}
|
|
1095
|
+
if (data.startedAt instanceof Date) {
|
|
1096
|
+
data.startedAt = data.startedAt.toISOString();
|
|
1097
|
+
}
|
|
1098
|
+
await this.operations.update({
|
|
1099
|
+
tableName: storage.TABLE_SPANS,
|
|
1100
|
+
keys: { spanId, traceId },
|
|
1101
|
+
data
|
|
1102
|
+
});
|
|
1103
|
+
} catch (error$1) {
|
|
1104
|
+
throw new error.MastraError(
|
|
1105
|
+
{
|
|
1106
|
+
id: "MSSQL_STORE_UPDATE_SPAN_FAILED",
|
|
1107
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1108
|
+
category: error.ErrorCategory.USER,
|
|
1109
|
+
details: {
|
|
1110
|
+
spanId,
|
|
1111
|
+
traceId
|
|
1112
|
+
}
|
|
1113
|
+
},
|
|
1114
|
+
error$1
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
async getTracesPaginated({
|
|
1119
|
+
filters,
|
|
1120
|
+
pagination
|
|
1121
|
+
}) {
|
|
1122
|
+
const page = pagination?.page ?? 0;
|
|
1123
|
+
const perPage = pagination?.perPage ?? 10;
|
|
1124
|
+
const { entityId, entityType, ...actualFilters } = filters || {};
|
|
1125
|
+
const filtersWithDateRange = {
|
|
1126
|
+
...actualFilters,
|
|
1127
|
+
...buildDateRangeFilter(pagination?.dateRange, "startedAt"),
|
|
1128
|
+
parentSpanId: null
|
|
1129
|
+
// Only get root spans for traces
|
|
1130
|
+
};
|
|
1131
|
+
const whereClause = prepareWhereClause(filtersWithDateRange);
|
|
1132
|
+
let actualWhereClause = whereClause.sql;
|
|
1133
|
+
const params = { ...whereClause.params };
|
|
1134
|
+
let currentParamIndex = Object.keys(params).length + 1;
|
|
1135
|
+
if (entityId && entityType) {
|
|
1136
|
+
let name = "";
|
|
1137
|
+
if (entityType === "workflow") {
|
|
1138
|
+
name = `workflow run: '${entityId}'`;
|
|
1139
|
+
} else if (entityType === "agent") {
|
|
1140
|
+
name = `agent run: '${entityId}'`;
|
|
1141
|
+
} else {
|
|
1142
|
+
const error$1 = new error.MastraError({
|
|
1143
|
+
id: "MSSQL_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
1144
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1145
|
+
category: error.ErrorCategory.USER,
|
|
1146
|
+
details: {
|
|
1147
|
+
entityType
|
|
1148
|
+
},
|
|
1149
|
+
text: `Cannot filter by entity type: ${entityType}`
|
|
1150
|
+
});
|
|
1151
|
+
throw error$1;
|
|
1152
|
+
}
|
|
1153
|
+
const entityParam = `p${currentParamIndex++}`;
|
|
1154
|
+
if (actualWhereClause) {
|
|
1155
|
+
actualWhereClause += ` AND [name] = @${entityParam}`;
|
|
1156
|
+
} else {
|
|
1157
|
+
actualWhereClause = ` WHERE [name] = @${entityParam}`;
|
|
1158
|
+
}
|
|
1159
|
+
params[entityParam] = name;
|
|
1160
|
+
}
|
|
1161
|
+
const tableName = getTableName({
|
|
1162
|
+
indexName: storage.TABLE_SPANS,
|
|
1163
|
+
schemaName: getSchemaName(this.schema)
|
|
1164
|
+
});
|
|
1165
|
+
try {
|
|
1166
|
+
const countRequest = this.pool.request();
|
|
1167
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1168
|
+
countRequest.input(key, value);
|
|
1169
|
+
});
|
|
1170
|
+
const countResult = await countRequest.query(
|
|
1171
|
+
`SELECT COUNT(*) as count FROM ${tableName}${actualWhereClause}`
|
|
1172
|
+
);
|
|
1173
|
+
const total = countResult.recordset[0]?.count ?? 0;
|
|
1174
|
+
if (total === 0) {
|
|
1175
|
+
return {
|
|
1176
|
+
pagination: {
|
|
1177
|
+
total: 0,
|
|
1178
|
+
page,
|
|
1179
|
+
perPage,
|
|
1180
|
+
hasMore: false
|
|
1181
|
+
},
|
|
1182
|
+
spans: []
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
const dataRequest = this.pool.request();
|
|
1186
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1187
|
+
dataRequest.input(key, value);
|
|
1188
|
+
});
|
|
1189
|
+
dataRequest.input("offset", page * perPage);
|
|
1190
|
+
dataRequest.input("limit", perPage);
|
|
1191
|
+
const dataResult = await dataRequest.query(
|
|
1192
|
+
`SELECT * FROM ${tableName}${actualWhereClause} ORDER BY [startedAt] DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
|
|
1193
|
+
);
|
|
1194
|
+
const spans = dataResult.recordset.map(
|
|
1195
|
+
(row) => transformFromSqlRow({
|
|
1196
|
+
tableName: storage.TABLE_SPANS,
|
|
1197
|
+
sqlRow: row
|
|
1198
|
+
})
|
|
1199
|
+
);
|
|
1200
|
+
return {
|
|
1201
|
+
pagination: {
|
|
1202
|
+
total,
|
|
1203
|
+
page,
|
|
1204
|
+
perPage,
|
|
1205
|
+
hasMore: (page + 1) * perPage < total
|
|
1206
|
+
},
|
|
1207
|
+
spans
|
|
1208
|
+
};
|
|
1209
|
+
} catch (error$1) {
|
|
1210
|
+
throw new error.MastraError(
|
|
1211
|
+
{
|
|
1212
|
+
id: "MSSQL_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
1213
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1214
|
+
category: error.ErrorCategory.USER
|
|
1215
|
+
},
|
|
1216
|
+
error$1
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
async batchCreateSpans(args) {
|
|
1221
|
+
if (!args.records || args.records.length === 0) {
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
try {
|
|
1225
|
+
await this.operations.batchInsert({
|
|
1226
|
+
tableName: storage.TABLE_SPANS,
|
|
1227
|
+
records: args.records.map((span) => ({
|
|
1228
|
+
...span,
|
|
1229
|
+
startedAt: span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt,
|
|
1230
|
+
endedAt: span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt
|
|
1231
|
+
}))
|
|
1232
|
+
});
|
|
1233
|
+
} catch (error$1) {
|
|
1234
|
+
throw new error.MastraError(
|
|
1235
|
+
{
|
|
1236
|
+
id: "MSSQL_STORE_BATCH_CREATE_SPANS_FAILED",
|
|
1237
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1238
|
+
category: error.ErrorCategory.USER,
|
|
1239
|
+
details: {
|
|
1240
|
+
count: args.records.length
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
error$1
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
async batchUpdateSpans(args) {
|
|
1248
|
+
if (!args.records || args.records.length === 0) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
try {
|
|
1252
|
+
const updates = args.records.map(({ traceId, spanId, updates: data }) => {
|
|
1253
|
+
const processedData = { ...data };
|
|
1254
|
+
if (processedData.endedAt instanceof Date) {
|
|
1255
|
+
processedData.endedAt = processedData.endedAt.toISOString();
|
|
1256
|
+
}
|
|
1257
|
+
if (processedData.startedAt instanceof Date) {
|
|
1258
|
+
processedData.startedAt = processedData.startedAt.toISOString();
|
|
1259
|
+
}
|
|
1260
|
+
return {
|
|
1261
|
+
keys: { spanId, traceId },
|
|
1262
|
+
data: processedData
|
|
1263
|
+
};
|
|
1264
|
+
});
|
|
1265
|
+
await this.operations.batchUpdate({
|
|
1266
|
+
tableName: storage.TABLE_SPANS,
|
|
1267
|
+
updates
|
|
1268
|
+
});
|
|
1269
|
+
} catch (error$1) {
|
|
1270
|
+
throw new error.MastraError(
|
|
1271
|
+
{
|
|
1272
|
+
id: "MSSQL_STORE_BATCH_UPDATE_SPANS_FAILED",
|
|
1273
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1274
|
+
category: error.ErrorCategory.USER,
|
|
1275
|
+
details: {
|
|
1276
|
+
count: args.records.length
|
|
1277
|
+
}
|
|
1278
|
+
},
|
|
1279
|
+
error$1
|
|
1280
|
+
);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
async batchDeleteTraces(args) {
|
|
1284
|
+
if (!args.traceIds || args.traceIds.length === 0) {
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
try {
|
|
1288
|
+
const keys = args.traceIds.map((traceId) => ({ traceId }));
|
|
1289
|
+
await this.operations.batchDelete({
|
|
1290
|
+
tableName: storage.TABLE_SPANS,
|
|
1291
|
+
keys
|
|
1292
|
+
});
|
|
1293
|
+
} catch (error$1) {
|
|
1294
|
+
throw new error.MastraError(
|
|
1295
|
+
{
|
|
1296
|
+
id: "MSSQL_STORE_BATCH_DELETE_TRACES_FAILED",
|
|
1297
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1298
|
+
category: error.ErrorCategory.USER,
|
|
1299
|
+
details: {
|
|
1300
|
+
count: args.traceIds.length
|
|
1301
|
+
}
|
|
1302
|
+
},
|
|
1303
|
+
error$1
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
};
|
|
1308
|
+
var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
1309
|
+
pool;
|
|
1310
|
+
schemaName;
|
|
1311
|
+
setupSchemaPromise = null;
|
|
1312
|
+
schemaSetupComplete = void 0;
|
|
1313
|
+
getSqlType(type, isPrimaryKey = false, useLargeStorage = false) {
|
|
1314
|
+
switch (type) {
|
|
1315
|
+
case "text":
|
|
1316
|
+
if (useLargeStorage) {
|
|
1317
|
+
return "NVARCHAR(MAX)";
|
|
1318
|
+
}
|
|
1319
|
+
return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(400)";
|
|
1320
|
+
case "timestamp":
|
|
1321
|
+
return "DATETIME2(7)";
|
|
1322
|
+
case "uuid":
|
|
1323
|
+
return "UNIQUEIDENTIFIER";
|
|
1324
|
+
case "jsonb":
|
|
1325
|
+
return "NVARCHAR(MAX)";
|
|
1326
|
+
case "integer":
|
|
1327
|
+
return "INT";
|
|
1328
|
+
case "bigint":
|
|
1329
|
+
return "BIGINT";
|
|
1330
|
+
case "float":
|
|
1331
|
+
return "FLOAT";
|
|
1332
|
+
case "boolean":
|
|
1333
|
+
return "BIT";
|
|
1334
|
+
default:
|
|
1335
|
+
throw new error.MastraError({
|
|
1336
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_TYPE_NOT_SUPPORTED",
|
|
1337
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1338
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
constructor({ pool, schemaName }) {
|
|
1343
|
+
super();
|
|
1344
|
+
this.pool = pool;
|
|
1345
|
+
this.schemaName = schemaName;
|
|
1346
|
+
}
|
|
1347
|
+
async hasColumn(table, column) {
|
|
1348
|
+
const schema = this.schemaName || "dbo";
|
|
1349
|
+
const request = this.pool.request();
|
|
1350
|
+
request.input("schema", schema);
|
|
1351
|
+
request.input("table", table);
|
|
1352
|
+
request.input("column", column);
|
|
1353
|
+
request.input("columnLower", column.toLowerCase());
|
|
1354
|
+
const result = await request.query(
|
|
1355
|
+
`SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND (COLUMN_NAME = @column OR COLUMN_NAME = @columnLower)`
|
|
1356
|
+
);
|
|
1357
|
+
return result.recordset.length > 0;
|
|
1358
|
+
}
|
|
1359
|
+
async setupSchema() {
|
|
1360
|
+
if (!this.schemaName || this.schemaSetupComplete) {
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (!this.setupSchemaPromise) {
|
|
1364
|
+
this.setupSchemaPromise = (async () => {
|
|
1365
|
+
try {
|
|
1366
|
+
const checkRequest = this.pool.request();
|
|
1367
|
+
checkRequest.input("schemaName", this.schemaName);
|
|
1368
|
+
const checkResult = await checkRequest.query(`
|
|
1369
|
+
SELECT 1 AS found FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = @schemaName
|
|
1370
|
+
`);
|
|
1371
|
+
const schemaExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1372
|
+
if (!schemaExists) {
|
|
1373
|
+
try {
|
|
1374
|
+
await this.pool.request().query(`CREATE SCHEMA [${this.schemaName}]`);
|
|
1375
|
+
this.logger?.info?.(`Schema "${this.schemaName}" created successfully`);
|
|
1376
|
+
} catch (error) {
|
|
1377
|
+
this.logger?.error?.(`Failed to create schema "${this.schemaName}"`, { error });
|
|
1378
|
+
throw new Error(
|
|
1379
|
+
`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.`
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
this.schemaSetupComplete = true;
|
|
1384
|
+
this.logger?.debug?.(`Schema "${this.schemaName}" is ready for use`);
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
this.schemaSetupComplete = void 0;
|
|
1387
|
+
this.setupSchemaPromise = null;
|
|
1388
|
+
throw error;
|
|
1389
|
+
} finally {
|
|
1390
|
+
this.setupSchemaPromise = null;
|
|
1391
|
+
}
|
|
1392
|
+
})();
|
|
1393
|
+
}
|
|
1394
|
+
await this.setupSchemaPromise;
|
|
1395
|
+
}
|
|
1396
|
+
async insert({
|
|
1397
|
+
tableName,
|
|
1398
|
+
record,
|
|
1399
|
+
transaction
|
|
1400
|
+
}) {
|
|
1401
|
+
try {
|
|
1402
|
+
const columns = Object.keys(record);
|
|
1403
|
+
const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
1404
|
+
const paramNames = columns.map((_, i) => `@param${i}`);
|
|
1405
|
+
const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${parsedColumns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
|
|
1406
|
+
const request = transaction ? transaction.request() : this.pool.request();
|
|
1407
|
+
columns.forEach((col, i) => {
|
|
1408
|
+
const value = record[col];
|
|
1409
|
+
const preparedValue = this.prepareValue(value, col, tableName);
|
|
1410
|
+
if (preparedValue instanceof Date) {
|
|
1411
|
+
request.input(`param${i}`, sql2__default.default.DateTime2, preparedValue);
|
|
1412
|
+
} else if (preparedValue === null || preparedValue === void 0) {
|
|
1413
|
+
request.input(`param${i}`, this.getMssqlType(tableName, col), null);
|
|
1414
|
+
} else {
|
|
1415
|
+
request.input(`param${i}`, preparedValue);
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
await request.query(insertSql);
|
|
1419
|
+
} catch (error$1) {
|
|
1420
|
+
throw new error.MastraError(
|
|
1421
|
+
{
|
|
1422
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_INSERT_FAILED",
|
|
1423
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1424
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1425
|
+
details: {
|
|
1426
|
+
tableName
|
|
1427
|
+
}
|
|
1428
|
+
},
|
|
1429
|
+
error$1
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
async clearTable({ tableName }) {
|
|
1144
1434
|
const fullTableName = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
|
|
1145
1435
|
try {
|
|
1146
1436
|
try {
|
|
1147
1437
|
await this.pool.request().query(`TRUNCATE TABLE ${fullTableName}`);
|
|
1148
1438
|
} catch (truncateError) {
|
|
1149
|
-
if (truncateError
|
|
1439
|
+
if (truncateError?.number === 4712) {
|
|
1150
1440
|
await this.pool.request().query(`DELETE FROM ${fullTableName}`);
|
|
1151
1441
|
} else {
|
|
1152
1442
|
throw truncateError;
|
|
@@ -1169,9 +1459,11 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1169
1459
|
getDefaultValue(type) {
|
|
1170
1460
|
switch (type) {
|
|
1171
1461
|
case "timestamp":
|
|
1172
|
-
return "DEFAULT
|
|
1462
|
+
return "DEFAULT SYSUTCDATETIME()";
|
|
1173
1463
|
case "jsonb":
|
|
1174
1464
|
return "DEFAULT N'{}'";
|
|
1465
|
+
case "boolean":
|
|
1466
|
+
return "DEFAULT 0";
|
|
1175
1467
|
default:
|
|
1176
1468
|
return super.getDefaultValue(type);
|
|
1177
1469
|
}
|
|
@@ -1182,13 +1474,29 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1182
1474
|
}) {
|
|
1183
1475
|
try {
|
|
1184
1476
|
const uniqueConstraintColumns = tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? ["workflow_name", "run_id"] : [];
|
|
1477
|
+
const largeDataColumns = [
|
|
1478
|
+
"workingMemory",
|
|
1479
|
+
"snapshot",
|
|
1480
|
+
"metadata",
|
|
1481
|
+
"content",
|
|
1482
|
+
// messages.content - can be very long conversation content
|
|
1483
|
+
"input",
|
|
1484
|
+
// evals.input - test input data
|
|
1485
|
+
"output",
|
|
1486
|
+
// evals.output - test output data
|
|
1487
|
+
"instructions",
|
|
1488
|
+
// evals.instructions - evaluation instructions
|
|
1489
|
+
"other"
|
|
1490
|
+
// traces.other - additional trace data
|
|
1491
|
+
];
|
|
1185
1492
|
const columns = Object.entries(schema).map(([name, def]) => {
|
|
1186
1493
|
const parsedName = utils.parseSqlIdentifier(name, "column name");
|
|
1187
1494
|
const constraints = [];
|
|
1188
1495
|
if (def.primaryKey) constraints.push("PRIMARY KEY");
|
|
1189
1496
|
if (!def.nullable) constraints.push("NOT NULL");
|
|
1190
1497
|
const isIndexed = !!def.primaryKey || uniqueConstraintColumns.includes(name);
|
|
1191
|
-
|
|
1498
|
+
const useLargeStorage = largeDataColumns.includes(name);
|
|
1499
|
+
return `[${parsedName}] ${this.getSqlType(def.type, isIndexed, useLargeStorage)} ${constraints.join(" ")}`.trim();
|
|
1192
1500
|
}).join(",\n");
|
|
1193
1501
|
if (this.schemaName) {
|
|
1194
1502
|
await this.setupSchema();
|
|
@@ -1275,7 +1583,19 @@ ${columns}
|
|
|
1275
1583
|
const columnExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1276
1584
|
if (!columnExists) {
|
|
1277
1585
|
const columnDef = schema[columnName];
|
|
1278
|
-
const
|
|
1586
|
+
const largeDataColumns = [
|
|
1587
|
+
"workingMemory",
|
|
1588
|
+
"snapshot",
|
|
1589
|
+
"metadata",
|
|
1590
|
+
"content",
|
|
1591
|
+
"input",
|
|
1592
|
+
"output",
|
|
1593
|
+
"instructions",
|
|
1594
|
+
"other"
|
|
1595
|
+
];
|
|
1596
|
+
const useLargeStorage = largeDataColumns.includes(columnName);
|
|
1597
|
+
const isIndexed = !!columnDef.primaryKey;
|
|
1598
|
+
const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage);
|
|
1279
1599
|
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
1280
1600
|
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
1281
1601
|
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
@@ -1303,13 +1623,17 @@ ${columns}
|
|
|
1303
1623
|
try {
|
|
1304
1624
|
const keyEntries = Object.entries(keys).map(([key, value]) => [utils.parseSqlIdentifier(key, "column name"), value]);
|
|
1305
1625
|
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}`;
|
|
1626
|
+
const sql5 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
|
|
1308
1627
|
const request = this.pool.request();
|
|
1309
|
-
|
|
1310
|
-
|
|
1628
|
+
keyEntries.forEach(([key, value], i) => {
|
|
1629
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1630
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1631
|
+
request.input(`param${i}`, this.getMssqlType(tableName, key), null);
|
|
1632
|
+
} else {
|
|
1633
|
+
request.input(`param${i}`, preparedValue);
|
|
1634
|
+
}
|
|
1311
1635
|
});
|
|
1312
|
-
const resultSet = await request.query(
|
|
1636
|
+
const resultSet = await request.query(sql5);
|
|
1313
1637
|
const result = resultSet.recordset[0] || null;
|
|
1314
1638
|
if (!result) {
|
|
1315
1639
|
return null;
|
|
@@ -1341,7 +1665,7 @@ ${columns}
|
|
|
1341
1665
|
try {
|
|
1342
1666
|
await transaction.begin();
|
|
1343
1667
|
for (const record of records) {
|
|
1344
|
-
await this.insert({ tableName, record });
|
|
1668
|
+
await this.insert({ tableName, record, transaction });
|
|
1345
1669
|
}
|
|
1346
1670
|
await transaction.commit();
|
|
1347
1671
|
} catch (error$1) {
|
|
@@ -1360,19 +1684,576 @@ ${columns}
|
|
|
1360
1684
|
);
|
|
1361
1685
|
}
|
|
1362
1686
|
}
|
|
1363
|
-
async dropTable({ tableName }) {
|
|
1687
|
+
async dropTable({ tableName }) {
|
|
1688
|
+
try {
|
|
1689
|
+
const tableNameWithSchema = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
|
|
1690
|
+
await this.pool.request().query(`DROP TABLE IF EXISTS ${tableNameWithSchema}`);
|
|
1691
|
+
} catch (error$1) {
|
|
1692
|
+
throw new error.MastraError(
|
|
1693
|
+
{
|
|
1694
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_DROP_TABLE_FAILED",
|
|
1695
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1696
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1697
|
+
details: {
|
|
1698
|
+
tableName
|
|
1699
|
+
}
|
|
1700
|
+
},
|
|
1701
|
+
error$1
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
* Prepares a value for database operations, handling Date objects and JSON serialization
|
|
1707
|
+
*/
|
|
1708
|
+
prepareValue(value, columnName, tableName) {
|
|
1709
|
+
if (value === null || value === void 0) {
|
|
1710
|
+
return value;
|
|
1711
|
+
}
|
|
1712
|
+
if (value instanceof Date) {
|
|
1713
|
+
return value;
|
|
1714
|
+
}
|
|
1715
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
1716
|
+
const columnSchema = schema?.[columnName];
|
|
1717
|
+
if (columnSchema?.type === "boolean") {
|
|
1718
|
+
return value ? 1 : 0;
|
|
1719
|
+
}
|
|
1720
|
+
if (columnSchema?.type === "jsonb") {
|
|
1721
|
+
if (typeof value === "string") {
|
|
1722
|
+
const trimmed = value.trim();
|
|
1723
|
+
if (trimmed.length > 0) {
|
|
1724
|
+
try {
|
|
1725
|
+
JSON.parse(trimmed);
|
|
1726
|
+
return trimmed;
|
|
1727
|
+
} catch {
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
return JSON.stringify(value);
|
|
1731
|
+
}
|
|
1732
|
+
if (typeof value === "bigint") {
|
|
1733
|
+
return value.toString();
|
|
1734
|
+
}
|
|
1735
|
+
return JSON.stringify(value);
|
|
1736
|
+
}
|
|
1737
|
+
if (typeof value === "object") {
|
|
1738
|
+
return JSON.stringify(value);
|
|
1739
|
+
}
|
|
1740
|
+
return value;
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Maps TABLE_SCHEMAS types to mssql param types (used when value is null)
|
|
1744
|
+
*/
|
|
1745
|
+
getMssqlType(tableName, columnName) {
|
|
1746
|
+
const col = storage.TABLE_SCHEMAS[tableName]?.[columnName];
|
|
1747
|
+
switch (col?.type) {
|
|
1748
|
+
case "text":
|
|
1749
|
+
return sql2__default.default.NVarChar;
|
|
1750
|
+
case "timestamp":
|
|
1751
|
+
return sql2__default.default.DateTime2;
|
|
1752
|
+
case "uuid":
|
|
1753
|
+
return sql2__default.default.UniqueIdentifier;
|
|
1754
|
+
case "jsonb":
|
|
1755
|
+
return sql2__default.default.NVarChar;
|
|
1756
|
+
case "integer":
|
|
1757
|
+
return sql2__default.default.Int;
|
|
1758
|
+
case "bigint":
|
|
1759
|
+
return sql2__default.default.BigInt;
|
|
1760
|
+
case "float":
|
|
1761
|
+
return sql2__default.default.Float;
|
|
1762
|
+
case "boolean":
|
|
1763
|
+
return sql2__default.default.Bit;
|
|
1764
|
+
default:
|
|
1765
|
+
return sql2__default.default.NVarChar;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Update a single record in the database
|
|
1770
|
+
*/
|
|
1771
|
+
async update({
|
|
1772
|
+
tableName,
|
|
1773
|
+
keys,
|
|
1774
|
+
data,
|
|
1775
|
+
transaction
|
|
1776
|
+
}) {
|
|
1777
|
+
try {
|
|
1778
|
+
if (!data || Object.keys(data).length === 0) {
|
|
1779
|
+
throw new error.MastraError({
|
|
1780
|
+
id: "MASTRA_STORAGE_MSSQL_UPDATE_EMPTY_DATA",
|
|
1781
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1782
|
+
category: error.ErrorCategory.USER,
|
|
1783
|
+
text: "Cannot update with empty data payload"
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
1787
|
+
throw new error.MastraError({
|
|
1788
|
+
id: "MASTRA_STORAGE_MSSQL_UPDATE_EMPTY_KEYS",
|
|
1789
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1790
|
+
category: error.ErrorCategory.USER,
|
|
1791
|
+
text: "Cannot update without keys to identify records"
|
|
1792
|
+
});
|
|
1793
|
+
}
|
|
1794
|
+
const setClauses = [];
|
|
1795
|
+
const request = transaction ? transaction.request() : this.pool.request();
|
|
1796
|
+
let paramIndex = 0;
|
|
1797
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
1798
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1799
|
+
const paramName = `set${paramIndex++}`;
|
|
1800
|
+
setClauses.push(`[${parsedKey}] = @${paramName}`);
|
|
1801
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1802
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1803
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1804
|
+
} else {
|
|
1805
|
+
request.input(paramName, preparedValue);
|
|
1806
|
+
}
|
|
1807
|
+
});
|
|
1808
|
+
const whereConditions = [];
|
|
1809
|
+
Object.entries(keys).forEach(([key, value]) => {
|
|
1810
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1811
|
+
const paramName = `where${paramIndex++}`;
|
|
1812
|
+
whereConditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1813
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1814
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1815
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1816
|
+
} else {
|
|
1817
|
+
request.input(paramName, preparedValue);
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
const tableName_ = getTableName({
|
|
1821
|
+
indexName: tableName,
|
|
1822
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1823
|
+
});
|
|
1824
|
+
const updateSql = `UPDATE ${tableName_} SET ${setClauses.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
|
|
1825
|
+
await request.query(updateSql);
|
|
1826
|
+
} catch (error$1) {
|
|
1827
|
+
throw new error.MastraError(
|
|
1828
|
+
{
|
|
1829
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_FAILED",
|
|
1830
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1831
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1832
|
+
details: {
|
|
1833
|
+
tableName
|
|
1834
|
+
}
|
|
1835
|
+
},
|
|
1836
|
+
error$1
|
|
1837
|
+
);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
/**
|
|
1841
|
+
* Update multiple records in a single batch transaction
|
|
1842
|
+
*/
|
|
1843
|
+
async batchUpdate({
|
|
1844
|
+
tableName,
|
|
1845
|
+
updates
|
|
1846
|
+
}) {
|
|
1847
|
+
const transaction = this.pool.transaction();
|
|
1848
|
+
try {
|
|
1849
|
+
await transaction.begin();
|
|
1850
|
+
for (const { keys, data } of updates) {
|
|
1851
|
+
await this.update({ tableName, keys, data, transaction });
|
|
1852
|
+
}
|
|
1853
|
+
await transaction.commit();
|
|
1854
|
+
} catch (error$1) {
|
|
1855
|
+
await transaction.rollback();
|
|
1856
|
+
throw new error.MastraError(
|
|
1857
|
+
{
|
|
1858
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_UPDATE_FAILED",
|
|
1859
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1860
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1861
|
+
details: {
|
|
1862
|
+
tableName,
|
|
1863
|
+
numberOfRecords: updates.length
|
|
1864
|
+
}
|
|
1865
|
+
},
|
|
1866
|
+
error$1
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Delete multiple records by keys
|
|
1872
|
+
*/
|
|
1873
|
+
async batchDelete({ tableName, keys }) {
|
|
1874
|
+
if (keys.length === 0) {
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
const tableName_ = getTableName({
|
|
1878
|
+
indexName: tableName,
|
|
1879
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1880
|
+
});
|
|
1881
|
+
const transaction = this.pool.transaction();
|
|
1882
|
+
try {
|
|
1883
|
+
await transaction.begin();
|
|
1884
|
+
for (const keySet of keys) {
|
|
1885
|
+
const conditions = [];
|
|
1886
|
+
const request = transaction.request();
|
|
1887
|
+
let paramIndex = 0;
|
|
1888
|
+
Object.entries(keySet).forEach(([key, value]) => {
|
|
1889
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1890
|
+
const paramName = `p${paramIndex++}`;
|
|
1891
|
+
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1892
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1893
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1894
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1895
|
+
} else {
|
|
1896
|
+
request.input(paramName, preparedValue);
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
const deleteSql = `DELETE FROM ${tableName_} WHERE ${conditions.join(" AND ")}`;
|
|
1900
|
+
await request.query(deleteSql);
|
|
1901
|
+
}
|
|
1902
|
+
await transaction.commit();
|
|
1903
|
+
} catch (error$1) {
|
|
1904
|
+
await transaction.rollback();
|
|
1905
|
+
throw new error.MastraError(
|
|
1906
|
+
{
|
|
1907
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_DELETE_FAILED",
|
|
1908
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1909
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1910
|
+
details: {
|
|
1911
|
+
tableName,
|
|
1912
|
+
numberOfRecords: keys.length
|
|
1913
|
+
}
|
|
1914
|
+
},
|
|
1915
|
+
error$1
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Create a new index on a table
|
|
1921
|
+
*/
|
|
1922
|
+
async createIndex(options) {
|
|
1923
|
+
try {
|
|
1924
|
+
const { name, table, columns, unique = false, where } = options;
|
|
1925
|
+
const schemaName = this.schemaName || "dbo";
|
|
1926
|
+
const fullTableName = getTableName({
|
|
1927
|
+
indexName: table,
|
|
1928
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1929
|
+
});
|
|
1930
|
+
const indexNameSafe = utils.parseSqlIdentifier(name, "index name");
|
|
1931
|
+
const checkRequest = this.pool.request();
|
|
1932
|
+
checkRequest.input("indexName", indexNameSafe);
|
|
1933
|
+
checkRequest.input("schemaName", schemaName);
|
|
1934
|
+
checkRequest.input("tableName", table);
|
|
1935
|
+
const indexExists = await checkRequest.query(`
|
|
1936
|
+
SELECT 1 as found
|
|
1937
|
+
FROM sys.indexes i
|
|
1938
|
+
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
1939
|
+
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
1940
|
+
WHERE i.name = @indexName
|
|
1941
|
+
AND s.name = @schemaName
|
|
1942
|
+
AND t.name = @tableName
|
|
1943
|
+
`);
|
|
1944
|
+
if (indexExists.recordset && indexExists.recordset.length > 0) {
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
const uniqueStr = unique ? "UNIQUE " : "";
|
|
1948
|
+
const columnsStr = columns.map((col) => {
|
|
1949
|
+
if (col.includes(" DESC") || col.includes(" ASC")) {
|
|
1950
|
+
const [colName, ...modifiers] = col.split(" ");
|
|
1951
|
+
if (!colName) {
|
|
1952
|
+
throw new Error(`Invalid column specification: ${col}`);
|
|
1953
|
+
}
|
|
1954
|
+
return `[${utils.parseSqlIdentifier(colName, "column name")}] ${modifiers.join(" ")}`;
|
|
1955
|
+
}
|
|
1956
|
+
return `[${utils.parseSqlIdentifier(col, "column name")}]`;
|
|
1957
|
+
}).join(", ");
|
|
1958
|
+
const whereStr = where ? ` WHERE ${where}` : "";
|
|
1959
|
+
const createIndexSql = `CREATE ${uniqueStr}INDEX [${indexNameSafe}] ON ${fullTableName} (${columnsStr})${whereStr}`;
|
|
1960
|
+
await this.pool.request().query(createIndexSql);
|
|
1961
|
+
} catch (error$1) {
|
|
1962
|
+
throw new error.MastraError(
|
|
1963
|
+
{
|
|
1964
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_CREATE_FAILED",
|
|
1965
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1966
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1967
|
+
details: {
|
|
1968
|
+
indexName: options.name,
|
|
1969
|
+
tableName: options.table
|
|
1970
|
+
}
|
|
1971
|
+
},
|
|
1972
|
+
error$1
|
|
1973
|
+
);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Drop an existing index
|
|
1978
|
+
*/
|
|
1979
|
+
async dropIndex(indexName) {
|
|
1980
|
+
try {
|
|
1981
|
+
const schemaName = this.schemaName || "dbo";
|
|
1982
|
+
const indexNameSafe = utils.parseSqlIdentifier(indexName, "index name");
|
|
1983
|
+
const checkRequest = this.pool.request();
|
|
1984
|
+
checkRequest.input("indexName", indexNameSafe);
|
|
1985
|
+
checkRequest.input("schemaName", schemaName);
|
|
1986
|
+
const result = await checkRequest.query(`
|
|
1987
|
+
SELECT t.name as table_name
|
|
1988
|
+
FROM sys.indexes i
|
|
1989
|
+
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
1990
|
+
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
1991
|
+
WHERE i.name = @indexName
|
|
1992
|
+
AND s.name = @schemaName
|
|
1993
|
+
`);
|
|
1994
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
if (result.recordset.length > 1) {
|
|
1998
|
+
const tables = result.recordset.map((r) => r.table_name).join(", ");
|
|
1999
|
+
throw new error.MastraError({
|
|
2000
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_AMBIGUOUS",
|
|
2001
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2002
|
+
category: error.ErrorCategory.USER,
|
|
2003
|
+
text: `Index "${indexNameSafe}" exists on multiple tables (${tables}) in schema "${schemaName}". Please drop indexes manually or ensure unique index names.`
|
|
2004
|
+
});
|
|
2005
|
+
}
|
|
2006
|
+
const tableName = result.recordset[0].table_name;
|
|
2007
|
+
const fullTableName = getTableName({
|
|
2008
|
+
indexName: tableName,
|
|
2009
|
+
schemaName: getSchemaName(this.schemaName)
|
|
2010
|
+
});
|
|
2011
|
+
const dropSql = `DROP INDEX [${indexNameSafe}] ON ${fullTableName}`;
|
|
2012
|
+
await this.pool.request().query(dropSql);
|
|
2013
|
+
} catch (error$1) {
|
|
2014
|
+
throw new error.MastraError(
|
|
2015
|
+
{
|
|
2016
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_DROP_FAILED",
|
|
2017
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2018
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2019
|
+
details: {
|
|
2020
|
+
indexName
|
|
2021
|
+
}
|
|
2022
|
+
},
|
|
2023
|
+
error$1
|
|
2024
|
+
);
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* List indexes for a specific table or all tables
|
|
2029
|
+
*/
|
|
2030
|
+
async listIndexes(tableName) {
|
|
2031
|
+
try {
|
|
2032
|
+
const schemaName = this.schemaName || "dbo";
|
|
2033
|
+
let query;
|
|
2034
|
+
const request = this.pool.request();
|
|
2035
|
+
request.input("schemaName", schemaName);
|
|
2036
|
+
if (tableName) {
|
|
2037
|
+
query = `
|
|
2038
|
+
SELECT
|
|
2039
|
+
i.name as name,
|
|
2040
|
+
o.name as [table],
|
|
2041
|
+
i.is_unique as is_unique,
|
|
2042
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
|
|
2043
|
+
FROM sys.indexes i
|
|
2044
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2045
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2046
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2047
|
+
WHERE sch.name = @schemaName
|
|
2048
|
+
AND o.name = @tableName
|
|
2049
|
+
AND i.name IS NOT NULL
|
|
2050
|
+
GROUP BY i.name, o.name, i.is_unique
|
|
2051
|
+
`;
|
|
2052
|
+
request.input("tableName", tableName);
|
|
2053
|
+
} else {
|
|
2054
|
+
query = `
|
|
2055
|
+
SELECT
|
|
2056
|
+
i.name as name,
|
|
2057
|
+
o.name as [table],
|
|
2058
|
+
i.is_unique as is_unique,
|
|
2059
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
|
|
2060
|
+
FROM sys.indexes i
|
|
2061
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2062
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2063
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2064
|
+
WHERE sch.name = @schemaName
|
|
2065
|
+
AND i.name IS NOT NULL
|
|
2066
|
+
GROUP BY i.name, o.name, i.is_unique
|
|
2067
|
+
`;
|
|
2068
|
+
}
|
|
2069
|
+
const result = await request.query(query);
|
|
2070
|
+
const indexes = [];
|
|
2071
|
+
for (const row of result.recordset) {
|
|
2072
|
+
const colRequest = this.pool.request();
|
|
2073
|
+
colRequest.input("indexName", row.name);
|
|
2074
|
+
colRequest.input("schemaName", schemaName);
|
|
2075
|
+
const colResult = await colRequest.query(`
|
|
2076
|
+
SELECT c.name as column_name
|
|
2077
|
+
FROM sys.indexes i
|
|
2078
|
+
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
2079
|
+
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
2080
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2081
|
+
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
2082
|
+
WHERE i.name = @indexName
|
|
2083
|
+
AND s.name = @schemaName
|
|
2084
|
+
ORDER BY ic.key_ordinal
|
|
2085
|
+
`);
|
|
2086
|
+
indexes.push({
|
|
2087
|
+
name: row.name,
|
|
2088
|
+
table: row.table,
|
|
2089
|
+
columns: colResult.recordset.map((c) => c.column_name),
|
|
2090
|
+
unique: row.is_unique || false,
|
|
2091
|
+
size: row.size || "0 MB",
|
|
2092
|
+
definition: ""
|
|
2093
|
+
// MSSQL doesn't store definition like PG
|
|
2094
|
+
});
|
|
2095
|
+
}
|
|
2096
|
+
return indexes;
|
|
2097
|
+
} catch (error$1) {
|
|
2098
|
+
throw new error.MastraError(
|
|
2099
|
+
{
|
|
2100
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_LIST_FAILED",
|
|
2101
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2102
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2103
|
+
details: tableName ? {
|
|
2104
|
+
tableName
|
|
2105
|
+
} : {}
|
|
2106
|
+
},
|
|
2107
|
+
error$1
|
|
2108
|
+
);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
/**
|
|
2112
|
+
* Get detailed statistics for a specific index
|
|
2113
|
+
*/
|
|
2114
|
+
async describeIndex(indexName) {
|
|
2115
|
+
try {
|
|
2116
|
+
const schemaName = this.schemaName || "dbo";
|
|
2117
|
+
const request = this.pool.request();
|
|
2118
|
+
request.input("indexName", indexName);
|
|
2119
|
+
request.input("schemaName", schemaName);
|
|
2120
|
+
const query = `
|
|
2121
|
+
SELECT
|
|
2122
|
+
i.name as name,
|
|
2123
|
+
o.name as [table],
|
|
2124
|
+
i.is_unique as is_unique,
|
|
2125
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size,
|
|
2126
|
+
i.type_desc as method,
|
|
2127
|
+
ISNULL(us.user_scans, 0) as scans,
|
|
2128
|
+
ISNULL(us.user_seeks + us.user_scans, 0) as tuples_read,
|
|
2129
|
+
ISNULL(us.user_lookups, 0) as tuples_fetched
|
|
2130
|
+
FROM sys.indexes i
|
|
2131
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2132
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2133
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2134
|
+
LEFT JOIN sys.dm_db_index_usage_stats us ON i.object_id = us.object_id AND i.index_id = us.index_id
|
|
2135
|
+
WHERE i.name = @indexName
|
|
2136
|
+
AND sch.name = @schemaName
|
|
2137
|
+
GROUP BY i.name, o.name, i.is_unique, i.type_desc, us.user_seeks, us.user_scans, us.user_lookups
|
|
2138
|
+
`;
|
|
2139
|
+
const result = await request.query(query);
|
|
2140
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2141
|
+
throw new Error(`Index "${indexName}" not found in schema "${schemaName}"`);
|
|
2142
|
+
}
|
|
2143
|
+
const row = result.recordset[0];
|
|
2144
|
+
const colRequest = this.pool.request();
|
|
2145
|
+
colRequest.input("indexName", indexName);
|
|
2146
|
+
colRequest.input("schemaName", schemaName);
|
|
2147
|
+
const colResult = await colRequest.query(`
|
|
2148
|
+
SELECT c.name as column_name
|
|
2149
|
+
FROM sys.indexes i
|
|
2150
|
+
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
2151
|
+
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
2152
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2153
|
+
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
2154
|
+
WHERE i.name = @indexName
|
|
2155
|
+
AND s.name = @schemaName
|
|
2156
|
+
ORDER BY ic.key_ordinal
|
|
2157
|
+
`);
|
|
2158
|
+
return {
|
|
2159
|
+
name: row.name,
|
|
2160
|
+
table: row.table,
|
|
2161
|
+
columns: colResult.recordset.map((c) => c.column_name),
|
|
2162
|
+
unique: row.is_unique || false,
|
|
2163
|
+
size: row.size || "0 MB",
|
|
2164
|
+
definition: "",
|
|
2165
|
+
method: row.method?.toLowerCase() || "nonclustered",
|
|
2166
|
+
scans: Number(row.scans) || 0,
|
|
2167
|
+
tuples_read: Number(row.tuples_read) || 0,
|
|
2168
|
+
tuples_fetched: Number(row.tuples_fetched) || 0
|
|
2169
|
+
};
|
|
2170
|
+
} catch (error$1) {
|
|
2171
|
+
throw new error.MastraError(
|
|
2172
|
+
{
|
|
2173
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_DESCRIBE_FAILED",
|
|
2174
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2175
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2176
|
+
details: {
|
|
2177
|
+
indexName
|
|
2178
|
+
}
|
|
2179
|
+
},
|
|
2180
|
+
error$1
|
|
2181
|
+
);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
/**
|
|
2185
|
+
* Returns definitions for automatic performance indexes
|
|
2186
|
+
* IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
|
|
2187
|
+
* NOTE: Using NVARCHAR(400) for text columns (800 bytes) leaves room for composite indexes
|
|
2188
|
+
*/
|
|
2189
|
+
getAutomaticIndexDefinitions() {
|
|
2190
|
+
const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
|
|
2191
|
+
return [
|
|
2192
|
+
// Composite indexes for optimal filtering + sorting performance
|
|
2193
|
+
// NVARCHAR(400) = 800 bytes, plus BIGINT (8 bytes) = 808 bytes total (under 900-byte limit)
|
|
2194
|
+
{
|
|
2195
|
+
name: `${schemaPrefix}mastra_threads_resourceid_seqid_idx`,
|
|
2196
|
+
table: storage.TABLE_THREADS,
|
|
2197
|
+
columns: ["resourceId", "seq_id DESC"]
|
|
2198
|
+
},
|
|
2199
|
+
{
|
|
2200
|
+
name: `${schemaPrefix}mastra_messages_thread_id_seqid_idx`,
|
|
2201
|
+
table: storage.TABLE_MESSAGES,
|
|
2202
|
+
columns: ["thread_id", "seq_id DESC"]
|
|
2203
|
+
},
|
|
2204
|
+
{
|
|
2205
|
+
name: `${schemaPrefix}mastra_traces_name_seqid_idx`,
|
|
2206
|
+
table: storage.TABLE_TRACES,
|
|
2207
|
+
columns: ["name", "seq_id DESC"]
|
|
2208
|
+
},
|
|
2209
|
+
{
|
|
2210
|
+
name: `${schemaPrefix}mastra_scores_trace_id_span_id_seqid_idx`,
|
|
2211
|
+
table: storage.TABLE_SCORERS,
|
|
2212
|
+
columns: ["traceId", "spanId", "seq_id DESC"]
|
|
2213
|
+
},
|
|
2214
|
+
// Spans indexes for optimal trace querying
|
|
2215
|
+
{
|
|
2216
|
+
name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
|
|
2217
|
+
table: storage.TABLE_SPANS,
|
|
2218
|
+
columns: ["traceId", "startedAt DESC"]
|
|
2219
|
+
},
|
|
2220
|
+
{
|
|
2221
|
+
name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
|
|
2222
|
+
table: storage.TABLE_SPANS,
|
|
2223
|
+
columns: ["parentSpanId", "startedAt DESC"]
|
|
2224
|
+
},
|
|
2225
|
+
{
|
|
2226
|
+
name: `${schemaPrefix}mastra_ai_spans_name_idx`,
|
|
2227
|
+
table: storage.TABLE_SPANS,
|
|
2228
|
+
columns: ["name"]
|
|
2229
|
+
},
|
|
2230
|
+
{
|
|
2231
|
+
name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
|
|
2232
|
+
table: storage.TABLE_SPANS,
|
|
2233
|
+
columns: ["spanType", "startedAt DESC"]
|
|
2234
|
+
}
|
|
2235
|
+
];
|
|
2236
|
+
}
|
|
2237
|
+
/**
|
|
2238
|
+
* Creates automatic indexes for optimal query performance
|
|
2239
|
+
* Uses getAutomaticIndexDefinitions() to determine which indexes to create
|
|
2240
|
+
*/
|
|
2241
|
+
async createAutomaticIndexes() {
|
|
1364
2242
|
try {
|
|
1365
|
-
const
|
|
1366
|
-
|
|
2243
|
+
const indexes = this.getAutomaticIndexDefinitions();
|
|
2244
|
+
for (const indexOptions of indexes) {
|
|
2245
|
+
try {
|
|
2246
|
+
await this.createIndex(indexOptions);
|
|
2247
|
+
} catch (error) {
|
|
2248
|
+
this.logger?.warn?.(`Failed to create index ${indexOptions.name}:`, error);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
1367
2251
|
} catch (error$1) {
|
|
1368
2252
|
throw new error.MastraError(
|
|
1369
2253
|
{
|
|
1370
|
-
id: "
|
|
2254
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_CREATE_PERFORMANCE_INDEXES_FAILED",
|
|
1371
2255
|
domain: error.ErrorDomain.STORAGE,
|
|
1372
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1373
|
-
details: {
|
|
1374
|
-
tableName
|
|
1375
|
-
}
|
|
2256
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1376
2257
|
},
|
|
1377
2258
|
error$1
|
|
1378
2259
|
);
|
|
@@ -1380,19 +2261,19 @@ ${columns}
|
|
|
1380
2261
|
}
|
|
1381
2262
|
};
|
|
1382
2263
|
function transformScoreRow(row) {
|
|
1383
|
-
let input = void 0;
|
|
1384
|
-
if (row.input) {
|
|
1385
|
-
try {
|
|
1386
|
-
input = JSON.parse(row.input);
|
|
1387
|
-
} catch {
|
|
1388
|
-
input = row.input;
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
2264
|
return {
|
|
1392
2265
|
...row,
|
|
1393
|
-
input,
|
|
1394
|
-
|
|
1395
|
-
|
|
2266
|
+
input: storage.safelyParseJSON(row.input),
|
|
2267
|
+
scorer: storage.safelyParseJSON(row.scorer),
|
|
2268
|
+
preprocessStepResult: storage.safelyParseJSON(row.preprocessStepResult),
|
|
2269
|
+
analyzeStepResult: storage.safelyParseJSON(row.analyzeStepResult),
|
|
2270
|
+
metadata: storage.safelyParseJSON(row.metadata),
|
|
2271
|
+
output: storage.safelyParseJSON(row.output),
|
|
2272
|
+
additionalContext: storage.safelyParseJSON(row.additionalContext),
|
|
2273
|
+
requestContext: storage.safelyParseJSON(row.requestContext),
|
|
2274
|
+
entity: storage.safelyParseJSON(row.entity),
|
|
2275
|
+
createdAt: new Date(row.createdAt),
|
|
2276
|
+
updatedAt: new Date(row.updatedAt)
|
|
1396
2277
|
};
|
|
1397
2278
|
}
|
|
1398
2279
|
var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
@@ -1433,15 +2314,47 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1433
2314
|
}
|
|
1434
2315
|
}
|
|
1435
2316
|
async saveScore(score) {
|
|
2317
|
+
let validatedScore;
|
|
2318
|
+
try {
|
|
2319
|
+
validatedScore = evals.saveScorePayloadSchema.parse(score);
|
|
2320
|
+
} catch (error$1) {
|
|
2321
|
+
throw new error.MastraError(
|
|
2322
|
+
{
|
|
2323
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_SAVE_SCORE_VALIDATION_FAILED",
|
|
2324
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2325
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
2326
|
+
},
|
|
2327
|
+
error$1
|
|
2328
|
+
);
|
|
2329
|
+
}
|
|
1436
2330
|
try {
|
|
1437
2331
|
const scoreId = crypto.randomUUID();
|
|
1438
|
-
const {
|
|
2332
|
+
const {
|
|
2333
|
+
scorer,
|
|
2334
|
+
preprocessStepResult,
|
|
2335
|
+
analyzeStepResult,
|
|
2336
|
+
metadata,
|
|
2337
|
+
input,
|
|
2338
|
+
output,
|
|
2339
|
+
additionalContext,
|
|
2340
|
+
requestContext,
|
|
2341
|
+
entity,
|
|
2342
|
+
...rest
|
|
2343
|
+
} = validatedScore;
|
|
1439
2344
|
await this.operations.insert({
|
|
1440
2345
|
tableName: storage.TABLE_SCORERS,
|
|
1441
2346
|
record: {
|
|
1442
2347
|
id: scoreId,
|
|
1443
2348
|
...rest,
|
|
1444
|
-
input:
|
|
2349
|
+
input: input || "",
|
|
2350
|
+
output: output || "",
|
|
2351
|
+
preprocessStepResult: preprocessStepResult || null,
|
|
2352
|
+
analyzeStepResult: analyzeStepResult || null,
|
|
2353
|
+
metadata: metadata || null,
|
|
2354
|
+
additionalContext: additionalContext || null,
|
|
2355
|
+
requestContext: requestContext || null,
|
|
2356
|
+
entity: entity || null,
|
|
2357
|
+
scorer: scorer || null,
|
|
1445
2358
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1446
2359
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1447
2360
|
}
|
|
@@ -1459,41 +2372,70 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1459
2372
|
);
|
|
1460
2373
|
}
|
|
1461
2374
|
}
|
|
1462
|
-
async
|
|
2375
|
+
async listScoresByScorerId({
|
|
1463
2376
|
scorerId,
|
|
1464
|
-
pagination
|
|
2377
|
+
pagination,
|
|
2378
|
+
entityId,
|
|
2379
|
+
entityType,
|
|
2380
|
+
source
|
|
1465
2381
|
}) {
|
|
1466
2382
|
try {
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
2383
|
+
const conditions = ["[scorerId] = @p1"];
|
|
2384
|
+
const params = { p1: scorerId };
|
|
2385
|
+
let paramIndex = 2;
|
|
2386
|
+
if (entityId) {
|
|
2387
|
+
conditions.push(`[entityId] = @p${paramIndex}`);
|
|
2388
|
+
params[`p${paramIndex}`] = entityId;
|
|
2389
|
+
paramIndex++;
|
|
2390
|
+
}
|
|
2391
|
+
if (entityType) {
|
|
2392
|
+
conditions.push(`[entityType] = @p${paramIndex}`);
|
|
2393
|
+
params[`p${paramIndex}`] = entityType;
|
|
2394
|
+
paramIndex++;
|
|
2395
|
+
}
|
|
2396
|
+
if (source) {
|
|
2397
|
+
conditions.push(`[source] = @p${paramIndex}`);
|
|
2398
|
+
params[`p${paramIndex}`] = source;
|
|
2399
|
+
paramIndex++;
|
|
2400
|
+
}
|
|
2401
|
+
const whereClause = conditions.join(" AND ");
|
|
2402
|
+
const tableName = getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) });
|
|
2403
|
+
const countRequest = this.pool.request();
|
|
2404
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
2405
|
+
countRequest.input(key, value);
|
|
2406
|
+
});
|
|
2407
|
+
const totalResult = await countRequest.query(`SELECT COUNT(*) as count FROM ${tableName} WHERE ${whereClause}`);
|
|
1472
2408
|
const total = totalResult.recordset[0]?.count || 0;
|
|
2409
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1473
2410
|
if (total === 0) {
|
|
1474
2411
|
return {
|
|
1475
2412
|
pagination: {
|
|
1476
2413
|
total: 0,
|
|
1477
|
-
page
|
|
1478
|
-
perPage:
|
|
2414
|
+
page,
|
|
2415
|
+
perPage: perPageInput,
|
|
1479
2416
|
hasMore: false
|
|
1480
2417
|
},
|
|
1481
2418
|
scores: []
|
|
1482
2419
|
};
|
|
1483
2420
|
}
|
|
2421
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2422
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2423
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2424
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1484
2425
|
const dataRequest = this.pool.request();
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
2426
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
2427
|
+
dataRequest.input(key, value);
|
|
2428
|
+
});
|
|
2429
|
+
dataRequest.input("perPage", limitValue);
|
|
2430
|
+
dataRequest.input("offset", start);
|
|
2431
|
+
const dataQuery = `SELECT * FROM ${tableName} WHERE ${whereClause} ORDER BY [createdAt] DESC OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
2432
|
+
const result = await dataRequest.query(dataQuery);
|
|
1491
2433
|
return {
|
|
1492
2434
|
pagination: {
|
|
1493
2435
|
total: Number(total),
|
|
1494
|
-
page
|
|
1495
|
-
perPage:
|
|
1496
|
-
hasMore:
|
|
2436
|
+
page,
|
|
2437
|
+
perPage: perPageForResponse,
|
|
2438
|
+
hasMore: end < total
|
|
1497
2439
|
},
|
|
1498
2440
|
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
1499
2441
|
};
|
|
@@ -1509,7 +2451,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1509
2451
|
);
|
|
1510
2452
|
}
|
|
1511
2453
|
}
|
|
1512
|
-
async
|
|
2454
|
+
async listScoresByRunId({
|
|
1513
2455
|
runId,
|
|
1514
2456
|
pagination
|
|
1515
2457
|
}) {
|
|
@@ -1520,30 +2462,35 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1520
2462
|
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [runId] = @p1`
|
|
1521
2463
|
);
|
|
1522
2464
|
const total = totalResult.recordset[0]?.count || 0;
|
|
2465
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1523
2466
|
if (total === 0) {
|
|
1524
2467
|
return {
|
|
1525
2468
|
pagination: {
|
|
1526
2469
|
total: 0,
|
|
1527
|
-
page
|
|
1528
|
-
perPage:
|
|
2470
|
+
page,
|
|
2471
|
+
perPage: perPageInput,
|
|
1529
2472
|
hasMore: false
|
|
1530
2473
|
},
|
|
1531
2474
|
scores: []
|
|
1532
2475
|
};
|
|
1533
2476
|
}
|
|
2477
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2478
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2479
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2480
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1534
2481
|
const dataRequest = this.pool.request();
|
|
1535
2482
|
dataRequest.input("p1", runId);
|
|
1536
|
-
dataRequest.input("p2",
|
|
1537
|
-
dataRequest.input("p3",
|
|
2483
|
+
dataRequest.input("p2", limitValue);
|
|
2484
|
+
dataRequest.input("p3", start);
|
|
1538
2485
|
const result = await dataRequest.query(
|
|
1539
2486
|
`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`
|
|
1540
2487
|
);
|
|
1541
2488
|
return {
|
|
1542
2489
|
pagination: {
|
|
1543
2490
|
total: Number(total),
|
|
1544
|
-
page
|
|
1545
|
-
perPage:
|
|
1546
|
-
hasMore:
|
|
2491
|
+
page,
|
|
2492
|
+
perPage: perPageForResponse,
|
|
2493
|
+
hasMore: end < total
|
|
1547
2494
|
},
|
|
1548
2495
|
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
1549
2496
|
};
|
|
@@ -1559,7 +2506,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1559
2506
|
);
|
|
1560
2507
|
}
|
|
1561
2508
|
}
|
|
1562
|
-
async
|
|
2509
|
+
async listScoresByEntityId({
|
|
1563
2510
|
entityId,
|
|
1564
2511
|
entityType,
|
|
1565
2512
|
pagination
|
|
@@ -1572,31 +2519,36 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1572
2519
|
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [entityId] = @p1 AND [entityType] = @p2`
|
|
1573
2520
|
);
|
|
1574
2521
|
const total = totalResult.recordset[0]?.count || 0;
|
|
2522
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2523
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2524
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1575
2525
|
if (total === 0) {
|
|
1576
2526
|
return {
|
|
1577
2527
|
pagination: {
|
|
1578
2528
|
total: 0,
|
|
1579
|
-
page
|
|
1580
|
-
perPage:
|
|
2529
|
+
page,
|
|
2530
|
+
perPage: perPageForResponse,
|
|
1581
2531
|
hasMore: false
|
|
1582
2532
|
},
|
|
1583
2533
|
scores: []
|
|
1584
2534
|
};
|
|
1585
2535
|
}
|
|
2536
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2537
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1586
2538
|
const dataRequest = this.pool.request();
|
|
1587
2539
|
dataRequest.input("p1", entityId);
|
|
1588
2540
|
dataRequest.input("p2", entityType);
|
|
1589
|
-
dataRequest.input("p3",
|
|
1590
|
-
dataRequest.input("p4",
|
|
2541
|
+
dataRequest.input("p3", limitValue);
|
|
2542
|
+
dataRequest.input("p4", start);
|
|
1591
2543
|
const result = await dataRequest.query(
|
|
1592
2544
|
`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`
|
|
1593
2545
|
);
|
|
1594
2546
|
return {
|
|
1595
2547
|
pagination: {
|
|
1596
2548
|
total: Number(total),
|
|
1597
|
-
page
|
|
1598
|
-
perPage:
|
|
1599
|
-
hasMore:
|
|
2549
|
+
page,
|
|
2550
|
+
perPage: perPageForResponse,
|
|
2551
|
+
hasMore: end < total
|
|
1600
2552
|
},
|
|
1601
2553
|
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
1602
2554
|
};
|
|
@@ -1612,8 +2564,66 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1612
2564
|
);
|
|
1613
2565
|
}
|
|
1614
2566
|
}
|
|
2567
|
+
async listScoresBySpan({
|
|
2568
|
+
traceId,
|
|
2569
|
+
spanId,
|
|
2570
|
+
pagination
|
|
2571
|
+
}) {
|
|
2572
|
+
try {
|
|
2573
|
+
const request = this.pool.request();
|
|
2574
|
+
request.input("p1", traceId);
|
|
2575
|
+
request.input("p2", spanId);
|
|
2576
|
+
const totalResult = await request.query(
|
|
2577
|
+
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [traceId] = @p1 AND [spanId] = @p2`
|
|
2578
|
+
);
|
|
2579
|
+
const total = totalResult.recordset[0]?.count || 0;
|
|
2580
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2581
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2582
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2583
|
+
if (total === 0) {
|
|
2584
|
+
return {
|
|
2585
|
+
pagination: {
|
|
2586
|
+
total: 0,
|
|
2587
|
+
page,
|
|
2588
|
+
perPage: perPageForResponse,
|
|
2589
|
+
hasMore: false
|
|
2590
|
+
},
|
|
2591
|
+
scores: []
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
2595
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
2596
|
+
const dataRequest = this.pool.request();
|
|
2597
|
+
dataRequest.input("p1", traceId);
|
|
2598
|
+
dataRequest.input("p2", spanId);
|
|
2599
|
+
dataRequest.input("p3", limitValue);
|
|
2600
|
+
dataRequest.input("p4", start);
|
|
2601
|
+
const result = await dataRequest.query(
|
|
2602
|
+
`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`
|
|
2603
|
+
);
|
|
2604
|
+
return {
|
|
2605
|
+
pagination: {
|
|
2606
|
+
total: Number(total),
|
|
2607
|
+
page,
|
|
2608
|
+
perPage: perPageForResponse,
|
|
2609
|
+
hasMore: end < total
|
|
2610
|
+
},
|
|
2611
|
+
scores: result.recordset.map((row) => transformScoreRow(row))
|
|
2612
|
+
};
|
|
2613
|
+
} catch (error$1) {
|
|
2614
|
+
throw new error.MastraError(
|
|
2615
|
+
{
|
|
2616
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_GET_SCORES_BY_SPAN_FAILED",
|
|
2617
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2618
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2619
|
+
details: { traceId, spanId }
|
|
2620
|
+
},
|
|
2621
|
+
error$1
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
1615
2625
|
};
|
|
1616
|
-
var
|
|
2626
|
+
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
1617
2627
|
pool;
|
|
1618
2628
|
operations;
|
|
1619
2629
|
schema;
|
|
@@ -1627,194 +2637,169 @@ var TracesMSSQL = class extends storage.TracesStorage {
|
|
|
1627
2637
|
this.operations = operations;
|
|
1628
2638
|
this.schema = schema;
|
|
1629
2639
|
}
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
if (
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
2640
|
+
parseWorkflowRun(row) {
|
|
2641
|
+
let parsedSnapshot = row.snapshot;
|
|
2642
|
+
if (typeof parsedSnapshot === "string") {
|
|
2643
|
+
try {
|
|
2644
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
2645
|
+
} catch (e) {
|
|
2646
|
+
this.logger?.warn?.(`Failed to parse snapshot for workflow ${row.workflow_name}:`, e);
|
|
2647
|
+
}
|
|
1637
2648
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
2649
|
+
return {
|
|
2650
|
+
workflowName: row.workflow_name,
|
|
2651
|
+
runId: row.run_id,
|
|
2652
|
+
snapshot: parsedSnapshot,
|
|
2653
|
+
createdAt: row.createdAt,
|
|
2654
|
+
updatedAt: row.updatedAt,
|
|
2655
|
+
resourceId: row.resourceId
|
|
2656
|
+
};
|
|
1640
2657
|
}
|
|
1641
|
-
async
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
const
|
|
1649
|
-
|
|
1650
|
-
if (name) {
|
|
1651
|
-
const paramName = `p${paramIndex++}`;
|
|
1652
|
-
conditions.push(`[name] LIKE @${paramName}`);
|
|
1653
|
-
paramMap[paramName] = `${name}%`;
|
|
1654
|
-
}
|
|
1655
|
-
if (scope) {
|
|
1656
|
-
const paramName = `p${paramIndex++}`;
|
|
1657
|
-
conditions.push(`[scope] = @${paramName}`);
|
|
1658
|
-
paramMap[paramName] = scope;
|
|
1659
|
-
}
|
|
1660
|
-
if (attributes) {
|
|
1661
|
-
Object.entries(attributes).forEach(([key, value]) => {
|
|
1662
|
-
const parsedKey = utils.parseFieldKey(key);
|
|
1663
|
-
const paramName = `p${paramIndex++}`;
|
|
1664
|
-
conditions.push(`JSON_VALUE([attributes], '$.${parsedKey}') = @${paramName}`);
|
|
1665
|
-
paramMap[paramName] = value;
|
|
1666
|
-
});
|
|
1667
|
-
}
|
|
1668
|
-
if (filters) {
|
|
1669
|
-
Object.entries(filters).forEach(([key, value]) => {
|
|
1670
|
-
const parsedKey = utils.parseFieldKey(key);
|
|
1671
|
-
const paramName = `p${paramIndex++}`;
|
|
1672
|
-
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1673
|
-
paramMap[paramName] = value;
|
|
1674
|
-
});
|
|
1675
|
-
}
|
|
1676
|
-
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
1677
|
-
const paramName = `p${paramIndex++}`;
|
|
1678
|
-
conditions.push(`[createdAt] >= @${paramName}`);
|
|
1679
|
-
paramMap[paramName] = fromDate.toISOString();
|
|
1680
|
-
}
|
|
1681
|
-
if (toDate instanceof Date && !isNaN(toDate.getTime())) {
|
|
1682
|
-
const paramName = `p${paramIndex++}`;
|
|
1683
|
-
conditions.push(`[createdAt] <= @${paramName}`);
|
|
1684
|
-
paramMap[paramName] = toDate.toISOString();
|
|
1685
|
-
}
|
|
1686
|
-
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1687
|
-
const countQuery = `SELECT COUNT(*) as total FROM ${getTableName({ indexName: storage.TABLE_TRACES, schemaName: getSchemaName(this.schema) })} ${whereClause}`;
|
|
1688
|
-
let total = 0;
|
|
2658
|
+
async updateWorkflowResults({
|
|
2659
|
+
workflowName,
|
|
2660
|
+
runId,
|
|
2661
|
+
stepId,
|
|
2662
|
+
result,
|
|
2663
|
+
requestContext
|
|
2664
|
+
}) {
|
|
2665
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2666
|
+
const transaction = this.pool.transaction();
|
|
1689
2667
|
try {
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
2668
|
+
await transaction.begin();
|
|
2669
|
+
const selectRequest = new sql2__default.default.Request(transaction);
|
|
2670
|
+
selectRequest.input("workflow_name", workflowName);
|
|
2671
|
+
selectRequest.input("run_id", runId);
|
|
2672
|
+
const existingSnapshotResult = await selectRequest.query(
|
|
2673
|
+
`SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2674
|
+
);
|
|
2675
|
+
let snapshot;
|
|
2676
|
+
if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
|
|
2677
|
+
snapshot = {
|
|
2678
|
+
context: {},
|
|
2679
|
+
activePaths: [],
|
|
2680
|
+
activeStepsPath: {},
|
|
2681
|
+
timestamp: Date.now(),
|
|
2682
|
+
suspendedPaths: {},
|
|
2683
|
+
resumeLabels: {},
|
|
2684
|
+
serializedStepGraph: [],
|
|
2685
|
+
status: "pending",
|
|
2686
|
+
value: {},
|
|
2687
|
+
waitingPaths: {},
|
|
2688
|
+
runId,
|
|
2689
|
+
requestContext: {}
|
|
2690
|
+
};
|
|
2691
|
+
} else {
|
|
2692
|
+
const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
|
|
2693
|
+
snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
2694
|
+
}
|
|
2695
|
+
snapshot.context[stepId] = result;
|
|
2696
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
2697
|
+
const upsertReq = new sql2__default.default.Request(transaction);
|
|
2698
|
+
upsertReq.input("workflow_name", workflowName);
|
|
2699
|
+
upsertReq.input("run_id", runId);
|
|
2700
|
+
upsertReq.input("snapshot", JSON.stringify(snapshot));
|
|
2701
|
+
upsertReq.input("createdAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2702
|
+
upsertReq.input("updatedAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2703
|
+
await upsertReq.query(
|
|
2704
|
+
`MERGE ${table} AS target
|
|
2705
|
+
USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
|
|
2706
|
+
ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
|
|
2707
|
+
WHEN MATCHED THEN UPDATE SET snapshot = @snapshot, [updatedAt] = @updatedAt
|
|
2708
|
+
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
|
|
2709
|
+
VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`
|
|
2710
|
+
);
|
|
2711
|
+
await transaction.commit();
|
|
2712
|
+
return snapshot.context;
|
|
1700
2713
|
} catch (error$1) {
|
|
2714
|
+
try {
|
|
2715
|
+
await transaction.rollback();
|
|
2716
|
+
} catch {
|
|
2717
|
+
}
|
|
1701
2718
|
throw new error.MastraError(
|
|
1702
2719
|
{
|
|
1703
|
-
id: "
|
|
2720
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_RESULTS_FAILED",
|
|
1704
2721
|
domain: error.ErrorDomain.STORAGE,
|
|
1705
2722
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1706
2723
|
details: {
|
|
1707
|
-
|
|
1708
|
-
|
|
2724
|
+
workflowName,
|
|
2725
|
+
runId,
|
|
2726
|
+
stepId
|
|
1709
2727
|
}
|
|
1710
2728
|
},
|
|
1711
2729
|
error$1
|
|
1712
2730
|
);
|
|
1713
2731
|
}
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}
|
|
1723
|
-
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`;
|
|
1724
|
-
const dataRequest = this.pool.request();
|
|
1725
|
-
Object.entries(paramMap).forEach(([key, value]) => {
|
|
1726
|
-
if (value instanceof Date) {
|
|
1727
|
-
dataRequest.input(key, sql2__default.default.DateTime, value);
|
|
1728
|
-
} else {
|
|
1729
|
-
dataRequest.input(key, value);
|
|
1730
|
-
}
|
|
1731
|
-
});
|
|
1732
|
-
dataRequest.input("offset", currentOffset);
|
|
1733
|
-
dataRequest.input("limit", perPage);
|
|
2732
|
+
}
|
|
2733
|
+
async updateWorkflowState({
|
|
2734
|
+
workflowName,
|
|
2735
|
+
runId,
|
|
2736
|
+
opts
|
|
2737
|
+
}) {
|
|
2738
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2739
|
+
const transaction = this.pool.transaction();
|
|
1734
2740
|
try {
|
|
1735
|
-
|
|
1736
|
-
const
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
2741
|
+
await transaction.begin();
|
|
2742
|
+
const selectRequest = new sql2__default.default.Request(transaction);
|
|
2743
|
+
selectRequest.input("workflow_name", workflowName);
|
|
2744
|
+
selectRequest.input("run_id", runId);
|
|
2745
|
+
const existingSnapshotResult = await selectRequest.query(
|
|
2746
|
+
`SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2747
|
+
);
|
|
2748
|
+
if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
|
|
2749
|
+
await transaction.rollback();
|
|
2750
|
+
return void 0;
|
|
2751
|
+
}
|
|
2752
|
+
const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
|
|
2753
|
+
const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
2754
|
+
if (!snapshot || !snapshot?.context) {
|
|
2755
|
+
await transaction.rollback();
|
|
2756
|
+
throw new error.MastraError(
|
|
2757
|
+
{
|
|
2758
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_SNAPSHOT_NOT_FOUND",
|
|
2759
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2760
|
+
category: error.ErrorCategory.SYSTEM,
|
|
2761
|
+
details: {
|
|
2762
|
+
workflowName,
|
|
2763
|
+
runId
|
|
2764
|
+
}
|
|
2765
|
+
},
|
|
2766
|
+
new Error(`Snapshot not found for runId ${runId}`)
|
|
2767
|
+
);
|
|
2768
|
+
}
|
|
2769
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
2770
|
+
const updateRequest = new sql2__default.default.Request(transaction);
|
|
2771
|
+
updateRequest.input("snapshot", JSON.stringify(updatedSnapshot));
|
|
2772
|
+
updateRequest.input("workflow_name", workflowName);
|
|
2773
|
+
updateRequest.input("run_id", runId);
|
|
2774
|
+
updateRequest.input("updatedAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2775
|
+
await updateRequest.query(
|
|
2776
|
+
`UPDATE ${table} SET snapshot = @snapshot, [updatedAt] = @updatedAt WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2777
|
+
);
|
|
2778
|
+
await transaction.commit();
|
|
2779
|
+
return updatedSnapshot;
|
|
1760
2780
|
} catch (error$1) {
|
|
2781
|
+
try {
|
|
2782
|
+
await transaction.rollback();
|
|
2783
|
+
} catch {
|
|
2784
|
+
}
|
|
1761
2785
|
throw new error.MastraError(
|
|
1762
2786
|
{
|
|
1763
|
-
id: "
|
|
2787
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_FAILED",
|
|
1764
2788
|
domain: error.ErrorDomain.STORAGE,
|
|
1765
2789
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1766
2790
|
details: {
|
|
1767
|
-
|
|
1768
|
-
|
|
2791
|
+
workflowName,
|
|
2792
|
+
runId
|
|
1769
2793
|
}
|
|
1770
2794
|
},
|
|
1771
2795
|
error$1
|
|
1772
2796
|
);
|
|
1773
2797
|
}
|
|
1774
2798
|
}
|
|
1775
|
-
async batchTraceInsert({ records }) {
|
|
1776
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1777
|
-
await this.operations.batchInsert({
|
|
1778
|
-
tableName: storage.TABLE_TRACES,
|
|
1779
|
-
records
|
|
1780
|
-
});
|
|
1781
|
-
}
|
|
1782
|
-
};
|
|
1783
|
-
function parseWorkflowRun(row) {
|
|
1784
|
-
let parsedSnapshot = row.snapshot;
|
|
1785
|
-
if (typeof parsedSnapshot === "string") {
|
|
1786
|
-
try {
|
|
1787
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1788
|
-
} catch (e) {
|
|
1789
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
return {
|
|
1793
|
-
workflowName: row.workflow_name,
|
|
1794
|
-
runId: row.run_id,
|
|
1795
|
-
snapshot: parsedSnapshot,
|
|
1796
|
-
createdAt: row.createdAt,
|
|
1797
|
-
updatedAt: row.updatedAt,
|
|
1798
|
-
resourceId: row.resourceId
|
|
1799
|
-
};
|
|
1800
|
-
}
|
|
1801
|
-
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
1802
|
-
pool;
|
|
1803
|
-
operations;
|
|
1804
|
-
schema;
|
|
1805
|
-
constructor({
|
|
1806
|
-
pool,
|
|
1807
|
-
operations,
|
|
1808
|
-
schema
|
|
1809
|
-
}) {
|
|
1810
|
-
super();
|
|
1811
|
-
this.pool = pool;
|
|
1812
|
-
this.operations = operations;
|
|
1813
|
-
this.schema = schema;
|
|
1814
|
-
}
|
|
1815
2799
|
async persistWorkflowSnapshot({
|
|
1816
2800
|
workflowName,
|
|
1817
2801
|
runId,
|
|
2802
|
+
resourceId,
|
|
1818
2803
|
snapshot
|
|
1819
2804
|
}) {
|
|
1820
2805
|
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
@@ -1823,6 +2808,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1823
2808
|
const request = this.pool.request();
|
|
1824
2809
|
request.input("workflow_name", workflowName);
|
|
1825
2810
|
request.input("run_id", runId);
|
|
2811
|
+
request.input("resourceId", resourceId);
|
|
1826
2812
|
request.input("snapshot", JSON.stringify(snapshot));
|
|
1827
2813
|
request.input("createdAt", sql2__default.default.DateTime2, new Date(now));
|
|
1828
2814
|
request.input("updatedAt", sql2__default.default.DateTime2, new Date(now));
|
|
@@ -1830,10 +2816,11 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1830
2816
|
USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
|
|
1831
2817
|
ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
|
|
1832
2818
|
WHEN MATCHED THEN UPDATE SET
|
|
2819
|
+
resourceId = @resourceId,
|
|
1833
2820
|
snapshot = @snapshot,
|
|
1834
2821
|
[updatedAt] = @updatedAt
|
|
1835
|
-
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
|
|
1836
|
-
VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`;
|
|
2822
|
+
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, resourceId, snapshot, [createdAt], [updatedAt])
|
|
2823
|
+
VALUES (@workflow_name, @run_id, @resourceId, @snapshot, @createdAt, @updatedAt);`;
|
|
1837
2824
|
await request.query(mergeSql);
|
|
1838
2825
|
} catch (error$1) {
|
|
1839
2826
|
throw new error.MastraError(
|
|
@@ -1905,7 +2892,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1905
2892
|
if (!result.recordset || result.recordset.length === 0) {
|
|
1906
2893
|
return null;
|
|
1907
2894
|
}
|
|
1908
|
-
return parseWorkflowRun(result.recordset[0]);
|
|
2895
|
+
return this.parseWorkflowRun(result.recordset[0]);
|
|
1909
2896
|
} catch (error$1) {
|
|
1910
2897
|
throw new error.MastraError(
|
|
1911
2898
|
{
|
|
@@ -1921,13 +2908,14 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1921
2908
|
);
|
|
1922
2909
|
}
|
|
1923
2910
|
}
|
|
1924
|
-
async
|
|
2911
|
+
async listWorkflowRuns({
|
|
1925
2912
|
workflowName,
|
|
1926
2913
|
fromDate,
|
|
1927
2914
|
toDate,
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
resourceId
|
|
2915
|
+
page,
|
|
2916
|
+
perPage,
|
|
2917
|
+
resourceId,
|
|
2918
|
+
status
|
|
1931
2919
|
} = {}) {
|
|
1932
2920
|
try {
|
|
1933
2921
|
const conditions = [];
|
|
@@ -1936,13 +2924,17 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1936
2924
|
conditions.push(`[workflow_name] = @workflowName`);
|
|
1937
2925
|
paramMap["workflowName"] = workflowName;
|
|
1938
2926
|
}
|
|
2927
|
+
if (status) {
|
|
2928
|
+
conditions.push(`JSON_VALUE([snapshot], '$.status') = @status`);
|
|
2929
|
+
paramMap["status"] = status;
|
|
2930
|
+
}
|
|
1939
2931
|
if (resourceId) {
|
|
1940
2932
|
const hasResourceId = await this.operations.hasColumn(storage.TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
1941
2933
|
if (hasResourceId) {
|
|
1942
2934
|
conditions.push(`[resourceId] = @resourceId`);
|
|
1943
2935
|
paramMap["resourceId"] = resourceId;
|
|
1944
2936
|
} else {
|
|
1945
|
-
|
|
2937
|
+
this.logger?.warn?.(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
1946
2938
|
}
|
|
1947
2939
|
}
|
|
1948
2940
|
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
@@ -1964,24 +2956,27 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1964
2956
|
request.input(key, value);
|
|
1965
2957
|
}
|
|
1966
2958
|
});
|
|
1967
|
-
|
|
2959
|
+
const usePagination = typeof perPage === "number" && typeof page === "number";
|
|
2960
|
+
if (usePagination) {
|
|
1968
2961
|
const countQuery = `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`;
|
|
1969
2962
|
const countResult = await request.query(countQuery);
|
|
1970
2963
|
total = Number(countResult.recordset[0]?.count || 0);
|
|
1971
2964
|
}
|
|
1972
2965
|
let query = `SELECT * FROM ${tableName} ${whereClause} ORDER BY [seq_id] DESC`;
|
|
1973
|
-
if (
|
|
1974
|
-
|
|
1975
|
-
|
|
2966
|
+
if (usePagination) {
|
|
2967
|
+
const normalizedPerPage = storage.normalizePerPage(perPage, Number.MAX_SAFE_INTEGER);
|
|
2968
|
+
const offset = page * normalizedPerPage;
|
|
2969
|
+
query += ` OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
2970
|
+
request.input("perPage", normalizedPerPage);
|
|
1976
2971
|
request.input("offset", offset);
|
|
1977
2972
|
}
|
|
1978
2973
|
const result = await request.query(query);
|
|
1979
|
-
const runs = (result.recordset || []).map((row) => parseWorkflowRun(row));
|
|
2974
|
+
const runs = (result.recordset || []).map((row) => this.parseWorkflowRun(row));
|
|
1980
2975
|
return { runs, total: total || runs.length };
|
|
1981
2976
|
} catch (error$1) {
|
|
1982
2977
|
throw new error.MastraError(
|
|
1983
2978
|
{
|
|
1984
|
-
id: "
|
|
2979
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_LIST_WORKFLOW_RUNS_FAILED",
|
|
1985
2980
|
domain: error.ErrorDomain.STORAGE,
|
|
1986
2981
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1987
2982
|
details: {
|
|
@@ -2001,7 +2996,10 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2001
2996
|
isConnected = null;
|
|
2002
2997
|
stores;
|
|
2003
2998
|
constructor(config) {
|
|
2004
|
-
|
|
2999
|
+
if (!config.id || typeof config.id !== "string" || config.id.trim() === "") {
|
|
3000
|
+
throw new Error("MSSQLStore: id must be provided and cannot be empty.");
|
|
3001
|
+
}
|
|
3002
|
+
super({ id: config.id, name: "MSSQLStore" });
|
|
2005
3003
|
try {
|
|
2006
3004
|
if ("connectionString" in config) {
|
|
2007
3005
|
if (!config.connectionString || typeof config.connectionString !== "string" || config.connectionString.trim() === "") {
|
|
@@ -2024,19 +3022,17 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2024
3022
|
port: config.port,
|
|
2025
3023
|
options: config.options || { encrypt: true, trustServerCertificate: true }
|
|
2026
3024
|
});
|
|
2027
|
-
const legacyEvals = new LegacyEvalsMSSQL({ pool: this.pool, schema: this.schema });
|
|
2028
3025
|
const operations = new StoreOperationsMSSQL({ pool: this.pool, schemaName: this.schema });
|
|
2029
3026
|
const scores = new ScoresMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2030
|
-
const traces = new TracesMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2031
3027
|
const workflows = new WorkflowsMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2032
3028
|
const memory = new MemoryMSSQL({ pool: this.pool, schema: this.schema, operations });
|
|
3029
|
+
const observability = new ObservabilityMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2033
3030
|
this.stores = {
|
|
2034
3031
|
operations,
|
|
2035
3032
|
scores,
|
|
2036
|
-
traces,
|
|
2037
3033
|
workflows,
|
|
2038
|
-
|
|
2039
|
-
|
|
3034
|
+
memory,
|
|
3035
|
+
observability
|
|
2040
3036
|
};
|
|
2041
3037
|
} catch (e) {
|
|
2042
3038
|
throw new error.MastraError(
|
|
@@ -2056,6 +3052,11 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2056
3052
|
try {
|
|
2057
3053
|
await this.isConnected;
|
|
2058
3054
|
await super.init();
|
|
3055
|
+
try {
|
|
3056
|
+
await this.stores.operations.createAutomaticIndexes();
|
|
3057
|
+
} catch (indexError) {
|
|
3058
|
+
this.logger?.warn?.("Failed to create indexes:", indexError);
|
|
3059
|
+
}
|
|
2059
3060
|
} catch (error$1) {
|
|
2060
3061
|
this.isConnected = null;
|
|
2061
3062
|
throw new error.MastraError(
|
|
@@ -2082,28 +3083,12 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2082
3083
|
resourceWorkingMemory: true,
|
|
2083
3084
|
hasColumn: true,
|
|
2084
3085
|
createTable: true,
|
|
2085
|
-
deleteMessages: true
|
|
3086
|
+
deleteMessages: true,
|
|
3087
|
+
listScoresBySpan: true,
|
|
3088
|
+
observabilityInstance: true,
|
|
3089
|
+
indexManagement: true
|
|
2086
3090
|
};
|
|
2087
3091
|
}
|
|
2088
|
-
/** @deprecated use getEvals instead */
|
|
2089
|
-
async getEvalsByAgentName(agentName, type) {
|
|
2090
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2091
|
-
}
|
|
2092
|
-
async getEvals(options = {}) {
|
|
2093
|
-
return this.stores.legacyEvals.getEvals(options);
|
|
2094
|
-
}
|
|
2095
|
-
/**
|
|
2096
|
-
* @deprecated use getTracesPaginated instead
|
|
2097
|
-
*/
|
|
2098
|
-
async getTraces(args) {
|
|
2099
|
-
return this.stores.traces.getTraces(args);
|
|
2100
|
-
}
|
|
2101
|
-
async getTracesPaginated(args) {
|
|
2102
|
-
return this.stores.traces.getTracesPaginated(args);
|
|
2103
|
-
}
|
|
2104
|
-
async batchTraceInsert({ records }) {
|
|
2105
|
-
return this.stores.traces.batchTraceInsert({ records });
|
|
2106
|
-
}
|
|
2107
3092
|
async createTable({
|
|
2108
3093
|
tableName,
|
|
2109
3094
|
schema
|
|
@@ -2138,15 +3123,6 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2138
3123
|
async getThreadById({ threadId }) {
|
|
2139
3124
|
return this.stores.memory.getThreadById({ threadId });
|
|
2140
3125
|
}
|
|
2141
|
-
/**
|
|
2142
|
-
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
2143
|
-
*/
|
|
2144
|
-
async getThreadsByResourceId(args) {
|
|
2145
|
-
return this.stores.memory.getThreadsByResourceId(args);
|
|
2146
|
-
}
|
|
2147
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
2148
|
-
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2149
|
-
}
|
|
2150
3126
|
async saveThread({ thread }) {
|
|
2151
3127
|
return this.stores.memory.saveThread({ thread });
|
|
2152
3128
|
}
|
|
@@ -2160,11 +3136,8 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2160
3136
|
async deleteThread({ threadId }) {
|
|
2161
3137
|
return this.stores.memory.deleteThread({ threadId });
|
|
2162
3138
|
}
|
|
2163
|
-
async
|
|
2164
|
-
return this.stores.memory.
|
|
2165
|
-
}
|
|
2166
|
-
async getMessagesPaginated(args) {
|
|
2167
|
-
return this.stores.memory.getMessagesPaginated(args);
|
|
3139
|
+
async listMessagesById({ messageIds }) {
|
|
3140
|
+
return this.stores.memory.listMessagesById({ messageIds });
|
|
2168
3141
|
}
|
|
2169
3142
|
async saveMessages(args) {
|
|
2170
3143
|
return this.stores.memory.saveMessages(args);
|
|
@@ -2193,12 +3166,29 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2193
3166
|
/**
|
|
2194
3167
|
* Workflows
|
|
2195
3168
|
*/
|
|
3169
|
+
async updateWorkflowResults({
|
|
3170
|
+
workflowName,
|
|
3171
|
+
runId,
|
|
3172
|
+
stepId,
|
|
3173
|
+
result,
|
|
3174
|
+
requestContext
|
|
3175
|
+
}) {
|
|
3176
|
+
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
3177
|
+
}
|
|
3178
|
+
async updateWorkflowState({
|
|
3179
|
+
workflowName,
|
|
3180
|
+
runId,
|
|
3181
|
+
opts
|
|
3182
|
+
}) {
|
|
3183
|
+
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
3184
|
+
}
|
|
2196
3185
|
async persistWorkflowSnapshot({
|
|
2197
3186
|
workflowName,
|
|
2198
3187
|
runId,
|
|
3188
|
+
resourceId,
|
|
2199
3189
|
snapshot
|
|
2200
3190
|
}) {
|
|
2201
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
3191
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
2202
3192
|
}
|
|
2203
3193
|
async loadWorkflowSnapshot({
|
|
2204
3194
|
workflowName,
|
|
@@ -2206,15 +3196,8 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2206
3196
|
}) {
|
|
2207
3197
|
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
2208
3198
|
}
|
|
2209
|
-
async
|
|
2210
|
-
|
|
2211
|
-
fromDate,
|
|
2212
|
-
toDate,
|
|
2213
|
-
limit,
|
|
2214
|
-
offset,
|
|
2215
|
-
resourceId
|
|
2216
|
-
} = {}) {
|
|
2217
|
-
return this.stores.workflows.getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
|
|
3199
|
+
async listWorkflowRuns(args = {}) {
|
|
3200
|
+
return this.stores.workflows.listWorkflowRuns(args);
|
|
2218
3201
|
}
|
|
2219
3202
|
async getWorkflowRunById({
|
|
2220
3203
|
runId,
|
|
@@ -2225,38 +3208,108 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2225
3208
|
async close() {
|
|
2226
3209
|
await this.pool.close();
|
|
2227
3210
|
}
|
|
3211
|
+
/**
|
|
3212
|
+
* Index Management
|
|
3213
|
+
*/
|
|
3214
|
+
async createIndex(options) {
|
|
3215
|
+
return this.stores.operations.createIndex(options);
|
|
3216
|
+
}
|
|
3217
|
+
async listIndexes(tableName) {
|
|
3218
|
+
return this.stores.operations.listIndexes(tableName);
|
|
3219
|
+
}
|
|
3220
|
+
async describeIndex(indexName) {
|
|
3221
|
+
return this.stores.operations.describeIndex(indexName);
|
|
3222
|
+
}
|
|
3223
|
+
async dropIndex(indexName) {
|
|
3224
|
+
return this.stores.operations.dropIndex(indexName);
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Tracing / Observability
|
|
3228
|
+
*/
|
|
3229
|
+
getObservabilityStore() {
|
|
3230
|
+
if (!this.stores.observability) {
|
|
3231
|
+
throw new error.MastraError({
|
|
3232
|
+
id: "MSSQL_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
3233
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3234
|
+
category: error.ErrorCategory.SYSTEM,
|
|
3235
|
+
text: "Observability storage is not initialized"
|
|
3236
|
+
});
|
|
3237
|
+
}
|
|
3238
|
+
return this.stores.observability;
|
|
3239
|
+
}
|
|
3240
|
+
async createSpan(span) {
|
|
3241
|
+
return this.getObservabilityStore().createSpan(span);
|
|
3242
|
+
}
|
|
3243
|
+
async updateSpan({
|
|
3244
|
+
spanId,
|
|
3245
|
+
traceId,
|
|
3246
|
+
updates
|
|
3247
|
+
}) {
|
|
3248
|
+
return this.getObservabilityStore().updateSpan({ spanId, traceId, updates });
|
|
3249
|
+
}
|
|
3250
|
+
async getTrace(traceId) {
|
|
3251
|
+
return this.getObservabilityStore().getTrace(traceId);
|
|
3252
|
+
}
|
|
3253
|
+
async getTracesPaginated(args) {
|
|
3254
|
+
return this.getObservabilityStore().getTracesPaginated(args);
|
|
3255
|
+
}
|
|
3256
|
+
async batchCreateSpans(args) {
|
|
3257
|
+
return this.getObservabilityStore().batchCreateSpans(args);
|
|
3258
|
+
}
|
|
3259
|
+
async batchUpdateSpans(args) {
|
|
3260
|
+
return this.getObservabilityStore().batchUpdateSpans(args);
|
|
3261
|
+
}
|
|
3262
|
+
async batchDeleteTraces(args) {
|
|
3263
|
+
return this.getObservabilityStore().batchDeleteTraces(args);
|
|
3264
|
+
}
|
|
2228
3265
|
/**
|
|
2229
3266
|
* Scorers
|
|
2230
3267
|
*/
|
|
2231
3268
|
async getScoreById({ id: _id }) {
|
|
2232
3269
|
return this.stores.scores.getScoreById({ id: _id });
|
|
2233
3270
|
}
|
|
2234
|
-
async
|
|
3271
|
+
async listScoresByScorerId({
|
|
2235
3272
|
scorerId: _scorerId,
|
|
2236
|
-
pagination: _pagination
|
|
3273
|
+
pagination: _pagination,
|
|
3274
|
+
entityId: _entityId,
|
|
3275
|
+
entityType: _entityType,
|
|
3276
|
+
source: _source
|
|
2237
3277
|
}) {
|
|
2238
|
-
return this.stores.scores.
|
|
3278
|
+
return this.stores.scores.listScoresByScorerId({
|
|
3279
|
+
scorerId: _scorerId,
|
|
3280
|
+
pagination: _pagination,
|
|
3281
|
+
entityId: _entityId,
|
|
3282
|
+
entityType: _entityType,
|
|
3283
|
+
source: _source
|
|
3284
|
+
});
|
|
2239
3285
|
}
|
|
2240
3286
|
async saveScore(_score) {
|
|
2241
3287
|
return this.stores.scores.saveScore(_score);
|
|
2242
3288
|
}
|
|
2243
|
-
async
|
|
3289
|
+
async listScoresByRunId({
|
|
2244
3290
|
runId: _runId,
|
|
2245
3291
|
pagination: _pagination
|
|
2246
3292
|
}) {
|
|
2247
|
-
return this.stores.scores.
|
|
3293
|
+
return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
|
|
2248
3294
|
}
|
|
2249
|
-
async
|
|
3295
|
+
async listScoresByEntityId({
|
|
2250
3296
|
entityId: _entityId,
|
|
2251
3297
|
entityType: _entityType,
|
|
2252
3298
|
pagination: _pagination
|
|
2253
3299
|
}) {
|
|
2254
|
-
return this.stores.scores.
|
|
3300
|
+
return this.stores.scores.listScoresByEntityId({
|
|
2255
3301
|
entityId: _entityId,
|
|
2256
3302
|
entityType: _entityType,
|
|
2257
3303
|
pagination: _pagination
|
|
2258
3304
|
});
|
|
2259
3305
|
}
|
|
3306
|
+
async listScoresBySpan({
|
|
3307
|
+
traceId,
|
|
3308
|
+
spanId,
|
|
3309
|
+
pagination: _pagination
|
|
3310
|
+
}) {
|
|
3311
|
+
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination: _pagination });
|
|
3312
|
+
}
|
|
2260
3313
|
};
|
|
2261
3314
|
|
|
2262
3315
|
exports.MSSQLStore = MSSQLStore;
|