@mastra/mssql 0.0.0-remove-unused-import-20250909212718 → 0.0.0-remove-unused-model-providers-api-20251030210744
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 +179 -3
- package/README.md +315 -36
- package/dist/index.cjs +1602 -549
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1616 -563
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +4 -7
- 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 +11 -2
- 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 +8 -12
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +57 -41
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +7 -7
- 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/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 scores = require('@mastra/core/scores');
|
|
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;
|
|
@@ -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;
|
|
@@ -256,7 +175,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
256
175
|
};
|
|
257
176
|
}
|
|
258
177
|
const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
|
|
259
|
-
const
|
|
178
|
+
const dir = (sortDirection || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
|
|
179
|
+
const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir} OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
260
180
|
const dataRequest = this.pool.request();
|
|
261
181
|
dataRequest.input("resourceId", resourceId);
|
|
262
182
|
dataRequest.input("perPage", perPage);
|
|
@@ -313,7 +233,12 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
313
233
|
req.input("id", thread.id);
|
|
314
234
|
req.input("resourceId", thread.resourceId);
|
|
315
235
|
req.input("title", thread.title);
|
|
316
|
-
|
|
236
|
+
const metadata = thread.metadata ? JSON.stringify(thread.metadata) : null;
|
|
237
|
+
if (metadata === null) {
|
|
238
|
+
req.input("metadata", sql2__default.default.NVarChar, null);
|
|
239
|
+
} else {
|
|
240
|
+
req.input("metadata", metadata);
|
|
241
|
+
}
|
|
317
242
|
req.input("createdAt", sql2__default.default.DateTime2, thread.createdAt);
|
|
318
243
|
req.input("updatedAt", sql2__default.default.DateTime2, thread.updatedAt);
|
|
319
244
|
await req.query(mergeSql);
|
|
@@ -340,7 +265,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
340
265
|
try {
|
|
341
266
|
const baseQuery = `FROM ${getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) })} WHERE [resourceId] = @resourceId`;
|
|
342
267
|
const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
|
|
343
|
-
const
|
|
268
|
+
const dir = (sortDirection || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
|
|
269
|
+
const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir}`;
|
|
344
270
|
const request = this.pool.request();
|
|
345
271
|
request.input("resourceId", resourceId);
|
|
346
272
|
const resultSet = await request.query(dataQuery);
|
|
@@ -383,7 +309,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
383
309
|
};
|
|
384
310
|
try {
|
|
385
311
|
const table = getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) });
|
|
386
|
-
const
|
|
312
|
+
const sql5 = `UPDATE ${table}
|
|
387
313
|
SET title = @title,
|
|
388
314
|
metadata = @metadata,
|
|
389
315
|
[updatedAt] = @updatedAt
|
|
@@ -394,7 +320,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
394
320
|
req.input("title", title);
|
|
395
321
|
req.input("metadata", JSON.stringify(mergedMetadata));
|
|
396
322
|
req.input("updatedAt", /* @__PURE__ */ new Date());
|
|
397
|
-
const result = await req.query(
|
|
323
|
+
const result = await req.query(sql5);
|
|
398
324
|
let thread = result.recordset && result.recordset[0];
|
|
399
325
|
if (thread && "seq_id" in thread) {
|
|
400
326
|
const { seq_id, ...rest } = thread;
|
|
@@ -464,8 +390,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
464
390
|
}
|
|
465
391
|
async _getIncludedMessages({
|
|
466
392
|
threadId,
|
|
467
|
-
selectBy
|
|
468
|
-
orderByStatement
|
|
393
|
+
selectBy
|
|
469
394
|
}) {
|
|
470
395
|
if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
|
|
471
396
|
const include = selectBy?.include;
|
|
@@ -493,7 +418,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
493
418
|
m.[resourceId],
|
|
494
419
|
m.seq_id
|
|
495
420
|
FROM (
|
|
496
|
-
SELECT *, ROW_NUMBER() OVER (
|
|
421
|
+
SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
|
|
497
422
|
FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
|
|
498
423
|
WHERE [thread_id] = ${pThreadId}
|
|
499
424
|
) AS m
|
|
@@ -501,15 +426,17 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
501
426
|
OR EXISTS (
|
|
502
427
|
SELECT 1
|
|
503
428
|
FROM (
|
|
504
|
-
SELECT *, ROW_NUMBER() OVER (
|
|
429
|
+
SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
|
|
505
430
|
FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
|
|
506
431
|
WHERE [thread_id] = ${pThreadId}
|
|
507
432
|
) AS target
|
|
508
433
|
WHERE target.id = ${pId}
|
|
509
434
|
AND (
|
|
510
|
-
|
|
435
|
+
-- Get previous messages (messages that come BEFORE the target)
|
|
436
|
+
(m.row_num < target.row_num AND m.row_num >= target.row_num - ${pPrev})
|
|
511
437
|
OR
|
|
512
|
-
|
|
438
|
+
-- Get next messages (messages that come AFTER the target)
|
|
439
|
+
(m.row_num > target.row_num AND m.row_num <= target.row_num + ${pNext})
|
|
513
440
|
)
|
|
514
441
|
)
|
|
515
442
|
`
|
|
@@ -548,7 +475,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
548
475
|
let rows = [];
|
|
549
476
|
const include = selectBy?.include || [];
|
|
550
477
|
if (include?.length) {
|
|
551
|
-
const includeMessages = await this._getIncludedMessages({ threadId, selectBy
|
|
478
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
|
|
552
479
|
if (includeMessages) {
|
|
553
480
|
rows.push(...includeMessages);
|
|
554
481
|
}
|
|
@@ -589,14 +516,11 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
589
516
|
error$1
|
|
590
517
|
);
|
|
591
518
|
this.logger?.error?.(mastraError.toString());
|
|
592
|
-
this.logger?.trackException(mastraError);
|
|
519
|
+
this.logger?.trackException?.(mastraError);
|
|
593
520
|
return [];
|
|
594
521
|
}
|
|
595
522
|
}
|
|
596
|
-
async
|
|
597
|
-
messageIds,
|
|
598
|
-
format
|
|
599
|
-
}) {
|
|
523
|
+
async listMessagesById({ messageIds }) {
|
|
600
524
|
if (messageIds.length === 0) return [];
|
|
601
525
|
const selectStatement = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId`;
|
|
602
526
|
const orderByStatement = `ORDER BY [seq_id] DESC`;
|
|
@@ -614,8 +538,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
614
538
|
return timeDiff;
|
|
615
539
|
});
|
|
616
540
|
rows = rows.map(({ seq_id, ...rest }) => rest);
|
|
617
|
-
|
|
618
|
-
return
|
|
541
|
+
const messages = this._parseAndFormatMessages(rows, `v2`);
|
|
542
|
+
return messages;
|
|
619
543
|
} catch (error$1) {
|
|
620
544
|
const mastraError = new error.MastraError(
|
|
621
545
|
{
|
|
@@ -629,10 +553,139 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
629
553
|
error$1
|
|
630
554
|
);
|
|
631
555
|
this.logger?.error?.(mastraError.toString());
|
|
632
|
-
this.logger?.trackException(mastraError);
|
|
556
|
+
this.logger?.trackException?.(mastraError);
|
|
633
557
|
return [];
|
|
634
558
|
}
|
|
635
559
|
}
|
|
560
|
+
async listMessages(args) {
|
|
561
|
+
const { threadId, resourceId, include, filter, limit, offset = 0, orderBy } = args;
|
|
562
|
+
if (!threadId.trim()) {
|
|
563
|
+
throw new error.MastraError(
|
|
564
|
+
{
|
|
565
|
+
id: "STORAGE_MSSQL_LIST_MESSAGES_INVALID_THREAD_ID",
|
|
566
|
+
domain: error.ErrorDomain.STORAGE,
|
|
567
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
568
|
+
details: { threadId }
|
|
569
|
+
},
|
|
570
|
+
new Error("threadId must be a non-empty string")
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
try {
|
|
574
|
+
let perPage = 40;
|
|
575
|
+
if (limit !== void 0) {
|
|
576
|
+
if (limit === false) {
|
|
577
|
+
perPage = Number.MAX_SAFE_INTEGER;
|
|
578
|
+
} else if (limit === 0) {
|
|
579
|
+
perPage = 0;
|
|
580
|
+
} else if (typeof limit === "number" && limit > 0) {
|
|
581
|
+
perPage = limit;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
const page = perPage === 0 ? 0 : Math.floor(offset / perPage);
|
|
585
|
+
const sortField = orderBy?.field || "createdAt";
|
|
586
|
+
const sortDirection = orderBy?.direction || "DESC";
|
|
587
|
+
const orderByStatement = `ORDER BY [${sortField}] ${sortDirection}`;
|
|
588
|
+
const selectStatement = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId`;
|
|
589
|
+
const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
|
|
590
|
+
const conditions = ["[thread_id] = @threadId"];
|
|
591
|
+
const request = this.pool.request();
|
|
592
|
+
request.input("threadId", threadId);
|
|
593
|
+
if (resourceId) {
|
|
594
|
+
conditions.push("[resourceId] = @resourceId");
|
|
595
|
+
request.input("resourceId", resourceId);
|
|
596
|
+
}
|
|
597
|
+
if (filter?.dateRange?.start) {
|
|
598
|
+
conditions.push("[createdAt] >= @fromDate");
|
|
599
|
+
request.input("fromDate", filter.dateRange.start);
|
|
600
|
+
}
|
|
601
|
+
if (filter?.dateRange?.end) {
|
|
602
|
+
conditions.push("[createdAt] <= @toDate");
|
|
603
|
+
request.input("toDate", filter.dateRange.end);
|
|
604
|
+
}
|
|
605
|
+
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
606
|
+
const countQuery = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause}`;
|
|
607
|
+
const countResult = await request.query(countQuery);
|
|
608
|
+
const total = parseInt(countResult.recordset[0]?.total, 10) || 0;
|
|
609
|
+
const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`;
|
|
610
|
+
request.input("offset", offset);
|
|
611
|
+
if (perPage > 2147483647) {
|
|
612
|
+
request.input("limit", sql2__default.default.BigInt, perPage);
|
|
613
|
+
} else {
|
|
614
|
+
request.input("limit", perPage);
|
|
615
|
+
}
|
|
616
|
+
const rowsResult = await request.query(dataQuery);
|
|
617
|
+
const rows = rowsResult.recordset || [];
|
|
618
|
+
const messages = [...rows];
|
|
619
|
+
if (total === 0 && messages.length === 0) {
|
|
620
|
+
return {
|
|
621
|
+
messages: [],
|
|
622
|
+
total: 0,
|
|
623
|
+
page,
|
|
624
|
+
perPage,
|
|
625
|
+
hasMore: false
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
629
|
+
if (include && include.length > 0) {
|
|
630
|
+
const selectBy = { include };
|
|
631
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
|
|
632
|
+
if (includeMessages) {
|
|
633
|
+
for (const includeMsg of includeMessages) {
|
|
634
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
635
|
+
messages.push(includeMsg);
|
|
636
|
+
messageIds.add(includeMsg.id);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
const parsed = this._parseAndFormatMessages(messages, "v2");
|
|
642
|
+
let finalMessages = parsed;
|
|
643
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
644
|
+
const aValue = sortField === "createdAt" ? new Date(a.createdAt).getTime() : a[sortField];
|
|
645
|
+
const bValue = sortField === "createdAt" ? new Date(b.createdAt).getTime() : b[sortField];
|
|
646
|
+
return sortDirection === "ASC" ? aValue - bValue : bValue - aValue;
|
|
647
|
+
});
|
|
648
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
649
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
650
|
+
const hasMore = limit === false ? false : allThreadMessagesReturned ? false : offset + rows.length < total;
|
|
651
|
+
return {
|
|
652
|
+
messages: finalMessages,
|
|
653
|
+
total,
|
|
654
|
+
page,
|
|
655
|
+
perPage,
|
|
656
|
+
hasMore
|
|
657
|
+
};
|
|
658
|
+
} catch (error$1) {
|
|
659
|
+
const errorPerPage = limit === false ? Number.MAX_SAFE_INTEGER : limit === 0 ? 0 : limit || 40;
|
|
660
|
+
const mastraError = new error.MastraError(
|
|
661
|
+
{
|
|
662
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_LIST_MESSAGES_FAILED",
|
|
663
|
+
domain: error.ErrorDomain.STORAGE,
|
|
664
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
665
|
+
details: {
|
|
666
|
+
threadId,
|
|
667
|
+
resourceId: resourceId ?? ""
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
error$1
|
|
671
|
+
);
|
|
672
|
+
this.logger?.error?.(mastraError.toString());
|
|
673
|
+
this.logger?.trackException?.(mastraError);
|
|
674
|
+
return {
|
|
675
|
+
messages: [],
|
|
676
|
+
total: 0,
|
|
677
|
+
page: errorPerPage === 0 ? 0 : Math.floor(offset / errorPerPage),
|
|
678
|
+
perPage: errorPerPage,
|
|
679
|
+
hasMore: false
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
async listThreadsByResourceId(args) {
|
|
684
|
+
const { resourceId, limit, offset, orderBy, sortDirection } = args;
|
|
685
|
+
const page = Math.floor(offset / limit);
|
|
686
|
+
const perPage = limit;
|
|
687
|
+
return this.getThreadsByResourceIdPaginated({ resourceId, page, perPage, orderBy, sortDirection });
|
|
688
|
+
}
|
|
636
689
|
async getMessagesPaginated(args) {
|
|
637
690
|
const { threadId, resourceId, format, selectBy } = args;
|
|
638
691
|
const { page = 0, perPage: perPageInput, dateRange } = selectBy?.pagination || {};
|
|
@@ -644,7 +697,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
644
697
|
const orderByStatement = `ORDER BY [seq_id] DESC`;
|
|
645
698
|
let messages = [];
|
|
646
699
|
if (selectBy?.include?.length) {
|
|
647
|
-
const includeMessages = await this._getIncludedMessages({ threadId, selectBy
|
|
700
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
|
|
648
701
|
if (includeMessages) messages.push(...includeMessages);
|
|
649
702
|
}
|
|
650
703
|
const perPage = perPageInput !== void 0 ? perPageInput : storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
@@ -691,7 +744,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
691
744
|
const parsed = this._parseAndFormatMessages(messages, format);
|
|
692
745
|
return {
|
|
693
746
|
messages: parsed,
|
|
694
|
-
total
|
|
747
|
+
total,
|
|
695
748
|
page,
|
|
696
749
|
perPage,
|
|
697
750
|
hasMore: currentOffset + rows.length < total
|
|
@@ -711,7 +764,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
711
764
|
error$1
|
|
712
765
|
);
|
|
713
766
|
this.logger?.error?.(mastraError.toString());
|
|
714
|
-
this.logger?.trackException(mastraError);
|
|
767
|
+
this.logger?.trackException?.(mastraError);
|
|
715
768
|
return { messages: [], total: 0, page, perPage: perPageInput || 40, hasMore: false };
|
|
716
769
|
}
|
|
717
770
|
}
|
|
@@ -978,8 +1031,10 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
978
1031
|
return null;
|
|
979
1032
|
}
|
|
980
1033
|
return {
|
|
981
|
-
|
|
982
|
-
|
|
1034
|
+
id: result.id,
|
|
1035
|
+
createdAt: result.createdAt,
|
|
1036
|
+
updatedAt: result.updatedAt,
|
|
1037
|
+
workingMemory: result.workingMemory,
|
|
983
1038
|
metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
|
|
984
1039
|
};
|
|
985
1040
|
} catch (error$1) {
|
|
@@ -993,7 +1048,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
993
1048
|
error$1
|
|
994
1049
|
);
|
|
995
1050
|
this.logger?.error?.(mastraError.toString());
|
|
996
|
-
this.logger?.trackException(mastraError);
|
|
1051
|
+
this.logger?.trackException?.(mastraError);
|
|
997
1052
|
throw mastraError;
|
|
998
1053
|
}
|
|
999
1054
|
}
|
|
@@ -1002,7 +1057,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1002
1057
|
tableName: storage.TABLE_RESOURCES,
|
|
1003
1058
|
record: {
|
|
1004
1059
|
...resource,
|
|
1005
|
-
metadata:
|
|
1060
|
+
metadata: resource.metadata
|
|
1006
1061
|
}
|
|
1007
1062
|
});
|
|
1008
1063
|
return resource;
|
|
@@ -1060,132 +1115,457 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1060
1115
|
error$1
|
|
1061
1116
|
);
|
|
1062
1117
|
this.logger?.error?.(mastraError.toString());
|
|
1063
|
-
this.logger?.trackException(mastraError);
|
|
1118
|
+
this.logger?.trackException?.(mastraError);
|
|
1064
1119
|
throw mastraError;
|
|
1065
1120
|
}
|
|
1066
1121
|
}
|
|
1067
1122
|
};
|
|
1068
|
-
var
|
|
1123
|
+
var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
1069
1124
|
pool;
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
case "timestamp":
|
|
1078
|
-
return "DATETIME2(7)";
|
|
1079
|
-
case "uuid":
|
|
1080
|
-
return "UNIQUEIDENTIFIER";
|
|
1081
|
-
case "jsonb":
|
|
1082
|
-
return "NVARCHAR(MAX)";
|
|
1083
|
-
case "integer":
|
|
1084
|
-
return "INT";
|
|
1085
|
-
case "bigint":
|
|
1086
|
-
return "BIGINT";
|
|
1087
|
-
case "float":
|
|
1088
|
-
return "FLOAT";
|
|
1089
|
-
default:
|
|
1090
|
-
throw new error.MastraError({
|
|
1091
|
-
id: "MASTRA_STORAGE_MSSQL_STORE_TYPE_NOT_SUPPORTED",
|
|
1092
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1093
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1094
|
-
});
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
constructor({ pool, schemaName }) {
|
|
1125
|
+
operations;
|
|
1126
|
+
schema;
|
|
1127
|
+
constructor({
|
|
1128
|
+
pool,
|
|
1129
|
+
operations,
|
|
1130
|
+
schema
|
|
1131
|
+
}) {
|
|
1098
1132
|
super();
|
|
1099
1133
|
this.pool = pool;
|
|
1100
|
-
this.
|
|
1134
|
+
this.operations = operations;
|
|
1135
|
+
this.schema = schema;
|
|
1101
1136
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
request.input("column", column);
|
|
1108
|
-
request.input("columnLower", column.toLowerCase());
|
|
1109
|
-
const result = await request.query(
|
|
1110
|
-
`SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND (COLUMN_NAME = @column OR COLUMN_NAME = @columnLower)`
|
|
1111
|
-
);
|
|
1112
|
-
return result.recordset.length > 0;
|
|
1137
|
+
get aiTracingStrategy() {
|
|
1138
|
+
return {
|
|
1139
|
+
preferred: "batch-with-updates",
|
|
1140
|
+
supported: ["batch-with-updates", "insert-only"]
|
|
1141
|
+
};
|
|
1113
1142
|
}
|
|
1114
|
-
async
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1143
|
+
async createAISpan(span) {
|
|
1144
|
+
try {
|
|
1145
|
+
const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
|
|
1146
|
+
const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
|
|
1147
|
+
const record = {
|
|
1148
|
+
...span,
|
|
1149
|
+
startedAt,
|
|
1150
|
+
endedAt
|
|
1151
|
+
// Note: createdAt/updatedAt will be set by default values
|
|
1152
|
+
};
|
|
1153
|
+
return this.operations.insert({ tableName: storage.TABLE_AI_SPANS, record });
|
|
1154
|
+
} catch (error$1) {
|
|
1155
|
+
throw new error.MastraError(
|
|
1156
|
+
{
|
|
1157
|
+
id: "MSSQL_STORE_CREATE_AI_SPAN_FAILED",
|
|
1158
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1159
|
+
category: error.ErrorCategory.USER,
|
|
1160
|
+
details: {
|
|
1161
|
+
spanId: span.spanId,
|
|
1162
|
+
traceId: span.traceId,
|
|
1163
|
+
spanType: span.spanType,
|
|
1164
|
+
spanName: span.name
|
|
1137
1165
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
this.schemaSetupComplete = void 0;
|
|
1142
|
-
this.setupSchemaPromise = null;
|
|
1143
|
-
throw error;
|
|
1144
|
-
} finally {
|
|
1145
|
-
this.setupSchemaPromise = null;
|
|
1146
|
-
}
|
|
1147
|
-
})();
|
|
1166
|
+
},
|
|
1167
|
+
error$1
|
|
1168
|
+
);
|
|
1148
1169
|
}
|
|
1149
|
-
await this.setupSchemaPromise;
|
|
1150
1170
|
}
|
|
1151
|
-
async
|
|
1171
|
+
async getAITrace(traceId) {
|
|
1152
1172
|
try {
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${columns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
|
|
1157
|
-
const request = this.pool.request();
|
|
1158
|
-
values.forEach((value, i) => {
|
|
1159
|
-
if (value instanceof Date) {
|
|
1160
|
-
request.input(`param${i}`, sql2__default.default.DateTime2, value);
|
|
1161
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1162
|
-
request.input(`param${i}`, JSON.stringify(value));
|
|
1163
|
-
} else {
|
|
1164
|
-
request.input(`param${i}`, value);
|
|
1165
|
-
}
|
|
1173
|
+
const tableName = getTableName({
|
|
1174
|
+
indexName: storage.TABLE_AI_SPANS,
|
|
1175
|
+
schemaName: getSchemaName(this.schema)
|
|
1166
1176
|
});
|
|
1167
|
-
|
|
1177
|
+
const request = this.pool.request();
|
|
1178
|
+
request.input("traceId", traceId);
|
|
1179
|
+
const result = await request.query(
|
|
1180
|
+
`SELECT
|
|
1181
|
+
[traceId], [spanId], [parentSpanId], [name], [scope], [spanType],
|
|
1182
|
+
[attributes], [metadata], [links], [input], [output], [error], [isEvent],
|
|
1183
|
+
[startedAt], [endedAt], [createdAt], [updatedAt]
|
|
1184
|
+
FROM ${tableName}
|
|
1185
|
+
WHERE [traceId] = @traceId
|
|
1186
|
+
ORDER BY [startedAt] DESC`
|
|
1187
|
+
);
|
|
1188
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
return {
|
|
1192
|
+
traceId,
|
|
1193
|
+
spans: result.recordset.map(
|
|
1194
|
+
(span) => transformFromSqlRow({
|
|
1195
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
1196
|
+
sqlRow: span
|
|
1197
|
+
})
|
|
1198
|
+
)
|
|
1199
|
+
};
|
|
1168
1200
|
} catch (error$1) {
|
|
1169
1201
|
throw new error.MastraError(
|
|
1170
1202
|
{
|
|
1171
|
-
id: "
|
|
1203
|
+
id: "MSSQL_STORE_GET_AI_TRACE_FAILED",
|
|
1172
1204
|
domain: error.ErrorDomain.STORAGE,
|
|
1173
|
-
category: error.ErrorCategory.
|
|
1205
|
+
category: error.ErrorCategory.USER,
|
|
1174
1206
|
details: {
|
|
1175
|
-
|
|
1207
|
+
traceId
|
|
1176
1208
|
}
|
|
1177
1209
|
},
|
|
1178
1210
|
error$1
|
|
1179
1211
|
);
|
|
1180
1212
|
}
|
|
1181
1213
|
}
|
|
1182
|
-
async
|
|
1183
|
-
|
|
1214
|
+
async updateAISpan({
|
|
1215
|
+
spanId,
|
|
1216
|
+
traceId,
|
|
1217
|
+
updates
|
|
1218
|
+
}) {
|
|
1219
|
+
try {
|
|
1220
|
+
const data = { ...updates };
|
|
1221
|
+
if (data.endedAt instanceof Date) {
|
|
1222
|
+
data.endedAt = data.endedAt.toISOString();
|
|
1223
|
+
}
|
|
1224
|
+
if (data.startedAt instanceof Date) {
|
|
1225
|
+
data.startedAt = data.startedAt.toISOString();
|
|
1226
|
+
}
|
|
1227
|
+
await this.operations.update({
|
|
1228
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
1229
|
+
keys: { spanId, traceId },
|
|
1230
|
+
data
|
|
1231
|
+
});
|
|
1232
|
+
} catch (error$1) {
|
|
1233
|
+
throw new error.MastraError(
|
|
1234
|
+
{
|
|
1235
|
+
id: "MSSQL_STORE_UPDATE_AI_SPAN_FAILED",
|
|
1236
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1237
|
+
category: error.ErrorCategory.USER,
|
|
1238
|
+
details: {
|
|
1239
|
+
spanId,
|
|
1240
|
+
traceId
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
error$1
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
async getAITracesPaginated({
|
|
1248
|
+
filters,
|
|
1249
|
+
pagination
|
|
1250
|
+
}) {
|
|
1251
|
+
const page = pagination?.page ?? 0;
|
|
1252
|
+
const perPage = pagination?.perPage ?? 10;
|
|
1253
|
+
const { entityId, entityType, ...actualFilters } = filters || {};
|
|
1254
|
+
const filtersWithDateRange = {
|
|
1255
|
+
...actualFilters,
|
|
1256
|
+
...buildDateRangeFilter(pagination?.dateRange, "startedAt"),
|
|
1257
|
+
parentSpanId: null
|
|
1258
|
+
// Only get root spans for traces
|
|
1259
|
+
};
|
|
1260
|
+
const whereClause = prepareWhereClause(filtersWithDateRange);
|
|
1261
|
+
let actualWhereClause = whereClause.sql;
|
|
1262
|
+
const params = { ...whereClause.params };
|
|
1263
|
+
let currentParamIndex = Object.keys(params).length + 1;
|
|
1264
|
+
if (entityId && entityType) {
|
|
1265
|
+
let name = "";
|
|
1266
|
+
if (entityType === "workflow") {
|
|
1267
|
+
name = `workflow run: '${entityId}'`;
|
|
1268
|
+
} else if (entityType === "agent") {
|
|
1269
|
+
name = `agent run: '${entityId}'`;
|
|
1270
|
+
} else {
|
|
1271
|
+
const error$1 = new error.MastraError({
|
|
1272
|
+
id: "MSSQL_STORE_GET_AI_TRACES_PAGINATED_FAILED",
|
|
1273
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1274
|
+
category: error.ErrorCategory.USER,
|
|
1275
|
+
details: {
|
|
1276
|
+
entityType
|
|
1277
|
+
},
|
|
1278
|
+
text: `Cannot filter by entity type: ${entityType}`
|
|
1279
|
+
});
|
|
1280
|
+
throw error$1;
|
|
1281
|
+
}
|
|
1282
|
+
const entityParam = `p${currentParamIndex++}`;
|
|
1283
|
+
if (actualWhereClause) {
|
|
1284
|
+
actualWhereClause += ` AND [name] = @${entityParam}`;
|
|
1285
|
+
} else {
|
|
1286
|
+
actualWhereClause = ` WHERE [name] = @${entityParam}`;
|
|
1287
|
+
}
|
|
1288
|
+
params[entityParam] = name;
|
|
1289
|
+
}
|
|
1290
|
+
const tableName = getTableName({
|
|
1291
|
+
indexName: storage.TABLE_AI_SPANS,
|
|
1292
|
+
schemaName: getSchemaName(this.schema)
|
|
1293
|
+
});
|
|
1294
|
+
try {
|
|
1295
|
+
const countRequest = this.pool.request();
|
|
1296
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1297
|
+
countRequest.input(key, value);
|
|
1298
|
+
});
|
|
1299
|
+
const countResult = await countRequest.query(
|
|
1300
|
+
`SELECT COUNT(*) as count FROM ${tableName}${actualWhereClause}`
|
|
1301
|
+
);
|
|
1302
|
+
const total = countResult.recordset[0]?.count ?? 0;
|
|
1303
|
+
if (total === 0) {
|
|
1304
|
+
return {
|
|
1305
|
+
pagination: {
|
|
1306
|
+
total: 0,
|
|
1307
|
+
page,
|
|
1308
|
+
perPage,
|
|
1309
|
+
hasMore: false
|
|
1310
|
+
},
|
|
1311
|
+
spans: []
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
const dataRequest = this.pool.request();
|
|
1315
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1316
|
+
dataRequest.input(key, value);
|
|
1317
|
+
});
|
|
1318
|
+
dataRequest.input("offset", page * perPage);
|
|
1319
|
+
dataRequest.input("limit", perPage);
|
|
1320
|
+
const dataResult = await dataRequest.query(
|
|
1321
|
+
`SELECT * FROM ${tableName}${actualWhereClause} ORDER BY [startedAt] DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
|
|
1322
|
+
);
|
|
1323
|
+
const spans = dataResult.recordset.map(
|
|
1324
|
+
(row) => transformFromSqlRow({
|
|
1325
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
1326
|
+
sqlRow: row
|
|
1327
|
+
})
|
|
1328
|
+
);
|
|
1329
|
+
return {
|
|
1330
|
+
pagination: {
|
|
1331
|
+
total,
|
|
1332
|
+
page,
|
|
1333
|
+
perPage,
|
|
1334
|
+
hasMore: (page + 1) * perPage < total
|
|
1335
|
+
},
|
|
1336
|
+
spans
|
|
1337
|
+
};
|
|
1338
|
+
} catch (error$1) {
|
|
1339
|
+
throw new error.MastraError(
|
|
1340
|
+
{
|
|
1341
|
+
id: "MSSQL_STORE_GET_AI_TRACES_PAGINATED_FAILED",
|
|
1342
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1343
|
+
category: error.ErrorCategory.USER
|
|
1344
|
+
},
|
|
1345
|
+
error$1
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
async batchCreateAISpans(args) {
|
|
1350
|
+
if (!args.records || args.records.length === 0) {
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
try {
|
|
1354
|
+
await this.operations.batchInsert({
|
|
1355
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
1356
|
+
records: args.records.map((span) => ({
|
|
1357
|
+
...span,
|
|
1358
|
+
startedAt: span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt,
|
|
1359
|
+
endedAt: span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt
|
|
1360
|
+
}))
|
|
1361
|
+
});
|
|
1362
|
+
} catch (error$1) {
|
|
1363
|
+
throw new error.MastraError(
|
|
1364
|
+
{
|
|
1365
|
+
id: "MSSQL_STORE_BATCH_CREATE_AI_SPANS_FAILED",
|
|
1366
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1367
|
+
category: error.ErrorCategory.USER,
|
|
1368
|
+
details: {
|
|
1369
|
+
count: args.records.length
|
|
1370
|
+
}
|
|
1371
|
+
},
|
|
1372
|
+
error$1
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
async batchUpdateAISpans(args) {
|
|
1377
|
+
if (!args.records || args.records.length === 0) {
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
try {
|
|
1381
|
+
const updates = args.records.map(({ traceId, spanId, updates: data }) => {
|
|
1382
|
+
const processedData = { ...data };
|
|
1383
|
+
if (processedData.endedAt instanceof Date) {
|
|
1384
|
+
processedData.endedAt = processedData.endedAt.toISOString();
|
|
1385
|
+
}
|
|
1386
|
+
if (processedData.startedAt instanceof Date) {
|
|
1387
|
+
processedData.startedAt = processedData.startedAt.toISOString();
|
|
1388
|
+
}
|
|
1389
|
+
return {
|
|
1390
|
+
keys: { spanId, traceId },
|
|
1391
|
+
data: processedData
|
|
1392
|
+
};
|
|
1393
|
+
});
|
|
1394
|
+
await this.operations.batchUpdate({
|
|
1395
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
1396
|
+
updates
|
|
1397
|
+
});
|
|
1398
|
+
} catch (error$1) {
|
|
1399
|
+
throw new error.MastraError(
|
|
1400
|
+
{
|
|
1401
|
+
id: "MSSQL_STORE_BATCH_UPDATE_AI_SPANS_FAILED",
|
|
1402
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1403
|
+
category: error.ErrorCategory.USER,
|
|
1404
|
+
details: {
|
|
1405
|
+
count: args.records.length
|
|
1406
|
+
}
|
|
1407
|
+
},
|
|
1408
|
+
error$1
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
async batchDeleteAITraces(args) {
|
|
1413
|
+
if (!args.traceIds || args.traceIds.length === 0) {
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
try {
|
|
1417
|
+
const keys = args.traceIds.map((traceId) => ({ traceId }));
|
|
1418
|
+
await this.operations.batchDelete({
|
|
1419
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
1420
|
+
keys
|
|
1421
|
+
});
|
|
1422
|
+
} catch (error$1) {
|
|
1423
|
+
throw new error.MastraError(
|
|
1424
|
+
{
|
|
1425
|
+
id: "MSSQL_STORE_BATCH_DELETE_AI_TRACES_FAILED",
|
|
1426
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1427
|
+
category: error.ErrorCategory.USER,
|
|
1428
|
+
details: {
|
|
1429
|
+
count: args.traceIds.length
|
|
1430
|
+
}
|
|
1431
|
+
},
|
|
1432
|
+
error$1
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
1438
|
+
pool;
|
|
1439
|
+
schemaName;
|
|
1440
|
+
setupSchemaPromise = null;
|
|
1441
|
+
schemaSetupComplete = void 0;
|
|
1442
|
+
getSqlType(type, isPrimaryKey = false, useLargeStorage = false) {
|
|
1443
|
+
switch (type) {
|
|
1444
|
+
case "text":
|
|
1445
|
+
if (useLargeStorage) {
|
|
1446
|
+
return "NVARCHAR(MAX)";
|
|
1447
|
+
}
|
|
1448
|
+
return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(400)";
|
|
1449
|
+
case "timestamp":
|
|
1450
|
+
return "DATETIME2(7)";
|
|
1451
|
+
case "uuid":
|
|
1452
|
+
return "UNIQUEIDENTIFIER";
|
|
1453
|
+
case "jsonb":
|
|
1454
|
+
return "NVARCHAR(MAX)";
|
|
1455
|
+
case "integer":
|
|
1456
|
+
return "INT";
|
|
1457
|
+
case "bigint":
|
|
1458
|
+
return "BIGINT";
|
|
1459
|
+
case "float":
|
|
1460
|
+
return "FLOAT";
|
|
1461
|
+
case "boolean":
|
|
1462
|
+
return "BIT";
|
|
1463
|
+
default:
|
|
1464
|
+
throw new error.MastraError({
|
|
1465
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_TYPE_NOT_SUPPORTED",
|
|
1466
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1467
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
constructor({ pool, schemaName }) {
|
|
1472
|
+
super();
|
|
1473
|
+
this.pool = pool;
|
|
1474
|
+
this.schemaName = schemaName;
|
|
1475
|
+
}
|
|
1476
|
+
async hasColumn(table, column) {
|
|
1477
|
+
const schema = this.schemaName || "dbo";
|
|
1478
|
+
const request = this.pool.request();
|
|
1479
|
+
request.input("schema", schema);
|
|
1480
|
+
request.input("table", table);
|
|
1481
|
+
request.input("column", column);
|
|
1482
|
+
request.input("columnLower", column.toLowerCase());
|
|
1483
|
+
const result = await request.query(
|
|
1484
|
+
`SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND (COLUMN_NAME = @column OR COLUMN_NAME = @columnLower)`
|
|
1485
|
+
);
|
|
1486
|
+
return result.recordset.length > 0;
|
|
1487
|
+
}
|
|
1488
|
+
async setupSchema() {
|
|
1489
|
+
if (!this.schemaName || this.schemaSetupComplete) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
if (!this.setupSchemaPromise) {
|
|
1493
|
+
this.setupSchemaPromise = (async () => {
|
|
1494
|
+
try {
|
|
1495
|
+
const checkRequest = this.pool.request();
|
|
1496
|
+
checkRequest.input("schemaName", this.schemaName);
|
|
1497
|
+
const checkResult = await checkRequest.query(`
|
|
1498
|
+
SELECT 1 AS found FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = @schemaName
|
|
1499
|
+
`);
|
|
1500
|
+
const schemaExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1501
|
+
if (!schemaExists) {
|
|
1502
|
+
try {
|
|
1503
|
+
await this.pool.request().query(`CREATE SCHEMA [${this.schemaName}]`);
|
|
1504
|
+
this.logger?.info?.(`Schema "${this.schemaName}" created successfully`);
|
|
1505
|
+
} catch (error) {
|
|
1506
|
+
this.logger?.error?.(`Failed to create schema "${this.schemaName}"`, { error });
|
|
1507
|
+
throw new Error(
|
|
1508
|
+
`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.`
|
|
1509
|
+
);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
this.schemaSetupComplete = true;
|
|
1513
|
+
this.logger?.debug?.(`Schema "${this.schemaName}" is ready for use`);
|
|
1514
|
+
} catch (error) {
|
|
1515
|
+
this.schemaSetupComplete = void 0;
|
|
1516
|
+
this.setupSchemaPromise = null;
|
|
1517
|
+
throw error;
|
|
1518
|
+
} finally {
|
|
1519
|
+
this.setupSchemaPromise = null;
|
|
1520
|
+
}
|
|
1521
|
+
})();
|
|
1522
|
+
}
|
|
1523
|
+
await this.setupSchemaPromise;
|
|
1524
|
+
}
|
|
1525
|
+
async insert({
|
|
1526
|
+
tableName,
|
|
1527
|
+
record,
|
|
1528
|
+
transaction
|
|
1529
|
+
}) {
|
|
1530
|
+
try {
|
|
1531
|
+
const columns = Object.keys(record);
|
|
1532
|
+
const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
1533
|
+
const paramNames = columns.map((_, i) => `@param${i}`);
|
|
1534
|
+
const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${parsedColumns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
|
|
1535
|
+
const request = transaction ? transaction.request() : this.pool.request();
|
|
1536
|
+
columns.forEach((col, i) => {
|
|
1537
|
+
const value = record[col];
|
|
1538
|
+
const preparedValue = this.prepareValue(value, col, tableName);
|
|
1539
|
+
if (preparedValue instanceof Date) {
|
|
1540
|
+
request.input(`param${i}`, sql2__default.default.DateTime2, preparedValue);
|
|
1541
|
+
} else if (preparedValue === null || preparedValue === void 0) {
|
|
1542
|
+
request.input(`param${i}`, this.getMssqlType(tableName, col), null);
|
|
1543
|
+
} else {
|
|
1544
|
+
request.input(`param${i}`, preparedValue);
|
|
1545
|
+
}
|
|
1546
|
+
});
|
|
1547
|
+
await request.query(insertSql);
|
|
1548
|
+
} catch (error$1) {
|
|
1549
|
+
throw new error.MastraError(
|
|
1550
|
+
{
|
|
1551
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_INSERT_FAILED",
|
|
1552
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1553
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1554
|
+
details: {
|
|
1555
|
+
tableName
|
|
1556
|
+
}
|
|
1557
|
+
},
|
|
1558
|
+
error$1
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
async clearTable({ tableName }) {
|
|
1563
|
+
const fullTableName = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
|
|
1184
1564
|
try {
|
|
1185
1565
|
try {
|
|
1186
1566
|
await this.pool.request().query(`TRUNCATE TABLE ${fullTableName}`);
|
|
1187
1567
|
} catch (truncateError) {
|
|
1188
|
-
if (truncateError
|
|
1568
|
+
if (truncateError?.number === 4712) {
|
|
1189
1569
|
await this.pool.request().query(`DELETE FROM ${fullTableName}`);
|
|
1190
1570
|
} else {
|
|
1191
1571
|
throw truncateError;
|
|
@@ -1208,9 +1588,11 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1208
1588
|
getDefaultValue(type) {
|
|
1209
1589
|
switch (type) {
|
|
1210
1590
|
case "timestamp":
|
|
1211
|
-
return "DEFAULT
|
|
1591
|
+
return "DEFAULT SYSUTCDATETIME()";
|
|
1212
1592
|
case "jsonb":
|
|
1213
1593
|
return "DEFAULT N'{}'";
|
|
1594
|
+
case "boolean":
|
|
1595
|
+
return "DEFAULT 0";
|
|
1214
1596
|
default:
|
|
1215
1597
|
return super.getDefaultValue(type);
|
|
1216
1598
|
}
|
|
@@ -1221,13 +1603,29 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
|
|
|
1221
1603
|
}) {
|
|
1222
1604
|
try {
|
|
1223
1605
|
const uniqueConstraintColumns = tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? ["workflow_name", "run_id"] : [];
|
|
1606
|
+
const largeDataColumns = [
|
|
1607
|
+
"workingMemory",
|
|
1608
|
+
"snapshot",
|
|
1609
|
+
"metadata",
|
|
1610
|
+
"content",
|
|
1611
|
+
// messages.content - can be very long conversation content
|
|
1612
|
+
"input",
|
|
1613
|
+
// evals.input - test input data
|
|
1614
|
+
"output",
|
|
1615
|
+
// evals.output - test output data
|
|
1616
|
+
"instructions",
|
|
1617
|
+
// evals.instructions - evaluation instructions
|
|
1618
|
+
"other"
|
|
1619
|
+
// traces.other - additional trace data
|
|
1620
|
+
];
|
|
1224
1621
|
const columns = Object.entries(schema).map(([name, def]) => {
|
|
1225
1622
|
const parsedName = utils.parseSqlIdentifier(name, "column name");
|
|
1226
1623
|
const constraints = [];
|
|
1227
1624
|
if (def.primaryKey) constraints.push("PRIMARY KEY");
|
|
1228
1625
|
if (!def.nullable) constraints.push("NOT NULL");
|
|
1229
1626
|
const isIndexed = !!def.primaryKey || uniqueConstraintColumns.includes(name);
|
|
1230
|
-
|
|
1627
|
+
const useLargeStorage = largeDataColumns.includes(name);
|
|
1628
|
+
return `[${parsedName}] ${this.getSqlType(def.type, isIndexed, useLargeStorage)} ${constraints.join(" ")}`.trim();
|
|
1231
1629
|
}).join(",\n");
|
|
1232
1630
|
if (this.schemaName) {
|
|
1233
1631
|
await this.setupSchema();
|
|
@@ -1314,7 +1712,19 @@ ${columns}
|
|
|
1314
1712
|
const columnExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
1315
1713
|
if (!columnExists) {
|
|
1316
1714
|
const columnDef = schema[columnName];
|
|
1317
|
-
const
|
|
1715
|
+
const largeDataColumns = [
|
|
1716
|
+
"workingMemory",
|
|
1717
|
+
"snapshot",
|
|
1718
|
+
"metadata",
|
|
1719
|
+
"content",
|
|
1720
|
+
"input",
|
|
1721
|
+
"output",
|
|
1722
|
+
"instructions",
|
|
1723
|
+
"other"
|
|
1724
|
+
];
|
|
1725
|
+
const useLargeStorage = largeDataColumns.includes(columnName);
|
|
1726
|
+
const isIndexed = !!columnDef.primaryKey;
|
|
1727
|
+
const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage);
|
|
1318
1728
|
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
1319
1729
|
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
1320
1730
|
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
@@ -1342,13 +1752,17 @@ ${columns}
|
|
|
1342
1752
|
try {
|
|
1343
1753
|
const keyEntries = Object.entries(keys).map(([key, value]) => [utils.parseSqlIdentifier(key, "column name"), value]);
|
|
1344
1754
|
const conditions = keyEntries.map(([key], i) => `[${key}] = @param${i}`).join(" AND ");
|
|
1345
|
-
const
|
|
1346
|
-
const sql7 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
|
|
1755
|
+
const sql5 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
|
|
1347
1756
|
const request = this.pool.request();
|
|
1348
|
-
|
|
1349
|
-
|
|
1757
|
+
keyEntries.forEach(([key, value], i) => {
|
|
1758
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1759
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1760
|
+
request.input(`param${i}`, this.getMssqlType(tableName, key), null);
|
|
1761
|
+
} else {
|
|
1762
|
+
request.input(`param${i}`, preparedValue);
|
|
1763
|
+
}
|
|
1350
1764
|
});
|
|
1351
|
-
const resultSet = await request.query(
|
|
1765
|
+
const resultSet = await request.query(sql5);
|
|
1352
1766
|
const result = resultSet.recordset[0] || null;
|
|
1353
1767
|
if (!result) {
|
|
1354
1768
|
return null;
|
|
@@ -1380,63 +1794,599 @@ ${columns}
|
|
|
1380
1794
|
try {
|
|
1381
1795
|
await transaction.begin();
|
|
1382
1796
|
for (const record of records) {
|
|
1383
|
-
await this.insert({ tableName, record });
|
|
1797
|
+
await this.insert({ tableName, record, transaction });
|
|
1798
|
+
}
|
|
1799
|
+
await transaction.commit();
|
|
1800
|
+
} catch (error$1) {
|
|
1801
|
+
await transaction.rollback();
|
|
1802
|
+
throw new error.MastraError(
|
|
1803
|
+
{
|
|
1804
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_INSERT_FAILED",
|
|
1805
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1806
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1807
|
+
details: {
|
|
1808
|
+
tableName,
|
|
1809
|
+
numberOfRecords: records.length
|
|
1810
|
+
}
|
|
1811
|
+
},
|
|
1812
|
+
error$1
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
async dropTable({ tableName }) {
|
|
1817
|
+
try {
|
|
1818
|
+
const tableNameWithSchema = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
|
|
1819
|
+
await this.pool.request().query(`DROP TABLE IF EXISTS ${tableNameWithSchema}`);
|
|
1820
|
+
} catch (error$1) {
|
|
1821
|
+
throw new error.MastraError(
|
|
1822
|
+
{
|
|
1823
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_DROP_TABLE_FAILED",
|
|
1824
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1825
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1826
|
+
details: {
|
|
1827
|
+
tableName
|
|
1828
|
+
}
|
|
1829
|
+
},
|
|
1830
|
+
error$1
|
|
1831
|
+
);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1835
|
+
* Prepares a value for database operations, handling Date objects and JSON serialization
|
|
1836
|
+
*/
|
|
1837
|
+
prepareValue(value, columnName, tableName) {
|
|
1838
|
+
if (value === null || value === void 0) {
|
|
1839
|
+
return value;
|
|
1840
|
+
}
|
|
1841
|
+
if (value instanceof Date) {
|
|
1842
|
+
return value;
|
|
1843
|
+
}
|
|
1844
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
1845
|
+
const columnSchema = schema?.[columnName];
|
|
1846
|
+
if (columnSchema?.type === "boolean") {
|
|
1847
|
+
return value ? 1 : 0;
|
|
1848
|
+
}
|
|
1849
|
+
if (columnSchema?.type === "jsonb") {
|
|
1850
|
+
return JSON.stringify(value);
|
|
1851
|
+
}
|
|
1852
|
+
if (typeof value === "object") {
|
|
1853
|
+
return JSON.stringify(value);
|
|
1854
|
+
}
|
|
1855
|
+
return value;
|
|
1856
|
+
}
|
|
1857
|
+
/**
|
|
1858
|
+
* Maps TABLE_SCHEMAS types to mssql param types (used when value is null)
|
|
1859
|
+
*/
|
|
1860
|
+
getMssqlType(tableName, columnName) {
|
|
1861
|
+
const col = storage.TABLE_SCHEMAS[tableName]?.[columnName];
|
|
1862
|
+
switch (col?.type) {
|
|
1863
|
+
case "text":
|
|
1864
|
+
return sql2__default.default.NVarChar;
|
|
1865
|
+
case "timestamp":
|
|
1866
|
+
return sql2__default.default.DateTime2;
|
|
1867
|
+
case "uuid":
|
|
1868
|
+
return sql2__default.default.UniqueIdentifier;
|
|
1869
|
+
case "jsonb":
|
|
1870
|
+
return sql2__default.default.NVarChar;
|
|
1871
|
+
case "integer":
|
|
1872
|
+
return sql2__default.default.Int;
|
|
1873
|
+
case "bigint":
|
|
1874
|
+
return sql2__default.default.BigInt;
|
|
1875
|
+
case "float":
|
|
1876
|
+
return sql2__default.default.Float;
|
|
1877
|
+
case "boolean":
|
|
1878
|
+
return sql2__default.default.Bit;
|
|
1879
|
+
default:
|
|
1880
|
+
return sql2__default.default.NVarChar;
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* Update a single record in the database
|
|
1885
|
+
*/
|
|
1886
|
+
async update({
|
|
1887
|
+
tableName,
|
|
1888
|
+
keys,
|
|
1889
|
+
data,
|
|
1890
|
+
transaction
|
|
1891
|
+
}) {
|
|
1892
|
+
try {
|
|
1893
|
+
if (!data || Object.keys(data).length === 0) {
|
|
1894
|
+
throw new error.MastraError({
|
|
1895
|
+
id: "MASTRA_STORAGE_MSSQL_UPDATE_EMPTY_DATA",
|
|
1896
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1897
|
+
category: error.ErrorCategory.USER,
|
|
1898
|
+
text: "Cannot update with empty data payload"
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
1902
|
+
throw new error.MastraError({
|
|
1903
|
+
id: "MASTRA_STORAGE_MSSQL_UPDATE_EMPTY_KEYS",
|
|
1904
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1905
|
+
category: error.ErrorCategory.USER,
|
|
1906
|
+
text: "Cannot update without keys to identify records"
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
const setClauses = [];
|
|
1910
|
+
const request = transaction ? transaction.request() : this.pool.request();
|
|
1911
|
+
let paramIndex = 0;
|
|
1912
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
1913
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1914
|
+
const paramName = `set${paramIndex++}`;
|
|
1915
|
+
setClauses.push(`[${parsedKey}] = @${paramName}`);
|
|
1916
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1917
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1918
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1919
|
+
} else {
|
|
1920
|
+
request.input(paramName, preparedValue);
|
|
1921
|
+
}
|
|
1922
|
+
});
|
|
1923
|
+
const whereConditions = [];
|
|
1924
|
+
Object.entries(keys).forEach(([key, value]) => {
|
|
1925
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
1926
|
+
const paramName = `where${paramIndex++}`;
|
|
1927
|
+
whereConditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1928
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
1929
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
1930
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
1931
|
+
} else {
|
|
1932
|
+
request.input(paramName, preparedValue);
|
|
1933
|
+
}
|
|
1934
|
+
});
|
|
1935
|
+
const tableName_ = getTableName({
|
|
1936
|
+
indexName: tableName,
|
|
1937
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1938
|
+
});
|
|
1939
|
+
const updateSql = `UPDATE ${tableName_} SET ${setClauses.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
|
|
1940
|
+
await request.query(updateSql);
|
|
1941
|
+
} catch (error$1) {
|
|
1942
|
+
throw new error.MastraError(
|
|
1943
|
+
{
|
|
1944
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_FAILED",
|
|
1945
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1946
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1947
|
+
details: {
|
|
1948
|
+
tableName
|
|
1949
|
+
}
|
|
1950
|
+
},
|
|
1951
|
+
error$1
|
|
1952
|
+
);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
/**
|
|
1956
|
+
* Update multiple records in a single batch transaction
|
|
1957
|
+
*/
|
|
1958
|
+
async batchUpdate({
|
|
1959
|
+
tableName,
|
|
1960
|
+
updates
|
|
1961
|
+
}) {
|
|
1962
|
+
const transaction = this.pool.transaction();
|
|
1963
|
+
try {
|
|
1964
|
+
await transaction.begin();
|
|
1965
|
+
for (const { keys, data } of updates) {
|
|
1966
|
+
await this.update({ tableName, keys, data, transaction });
|
|
1967
|
+
}
|
|
1968
|
+
await transaction.commit();
|
|
1969
|
+
} catch (error$1) {
|
|
1970
|
+
await transaction.rollback();
|
|
1971
|
+
throw new error.MastraError(
|
|
1972
|
+
{
|
|
1973
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_UPDATE_FAILED",
|
|
1974
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1975
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1976
|
+
details: {
|
|
1977
|
+
tableName,
|
|
1978
|
+
numberOfRecords: updates.length
|
|
1979
|
+
}
|
|
1980
|
+
},
|
|
1981
|
+
error$1
|
|
1982
|
+
);
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Delete multiple records by keys
|
|
1987
|
+
*/
|
|
1988
|
+
async batchDelete({ tableName, keys }) {
|
|
1989
|
+
if (keys.length === 0) {
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
const tableName_ = getTableName({
|
|
1993
|
+
indexName: tableName,
|
|
1994
|
+
schemaName: getSchemaName(this.schemaName)
|
|
1995
|
+
});
|
|
1996
|
+
const transaction = this.pool.transaction();
|
|
1997
|
+
try {
|
|
1998
|
+
await transaction.begin();
|
|
1999
|
+
for (const keySet of keys) {
|
|
2000
|
+
const conditions = [];
|
|
2001
|
+
const request = transaction.request();
|
|
2002
|
+
let paramIndex = 0;
|
|
2003
|
+
Object.entries(keySet).forEach(([key, value]) => {
|
|
2004
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
2005
|
+
const paramName = `p${paramIndex++}`;
|
|
2006
|
+
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
2007
|
+
const preparedValue = this.prepareValue(value, key, tableName);
|
|
2008
|
+
if (preparedValue === null || preparedValue === void 0) {
|
|
2009
|
+
request.input(paramName, this.getMssqlType(tableName, key), null);
|
|
2010
|
+
} else {
|
|
2011
|
+
request.input(paramName, preparedValue);
|
|
2012
|
+
}
|
|
2013
|
+
});
|
|
2014
|
+
const deleteSql = `DELETE FROM ${tableName_} WHERE ${conditions.join(" AND ")}`;
|
|
2015
|
+
await request.query(deleteSql);
|
|
2016
|
+
}
|
|
2017
|
+
await transaction.commit();
|
|
2018
|
+
} catch (error$1) {
|
|
2019
|
+
await transaction.rollback();
|
|
2020
|
+
throw new error.MastraError(
|
|
2021
|
+
{
|
|
2022
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_DELETE_FAILED",
|
|
2023
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2024
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2025
|
+
details: {
|
|
2026
|
+
tableName,
|
|
2027
|
+
numberOfRecords: keys.length
|
|
2028
|
+
}
|
|
2029
|
+
},
|
|
2030
|
+
error$1
|
|
2031
|
+
);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
/**
|
|
2035
|
+
* Create a new index on a table
|
|
2036
|
+
*/
|
|
2037
|
+
async createIndex(options) {
|
|
2038
|
+
try {
|
|
2039
|
+
const { name, table, columns, unique = false, where } = options;
|
|
2040
|
+
const schemaName = this.schemaName || "dbo";
|
|
2041
|
+
const fullTableName = getTableName({
|
|
2042
|
+
indexName: table,
|
|
2043
|
+
schemaName: getSchemaName(this.schemaName)
|
|
2044
|
+
});
|
|
2045
|
+
const indexNameSafe = utils.parseSqlIdentifier(name, "index name");
|
|
2046
|
+
const checkRequest = this.pool.request();
|
|
2047
|
+
checkRequest.input("indexName", indexNameSafe);
|
|
2048
|
+
checkRequest.input("schemaName", schemaName);
|
|
2049
|
+
checkRequest.input("tableName", table);
|
|
2050
|
+
const indexExists = await checkRequest.query(`
|
|
2051
|
+
SELECT 1 as found
|
|
2052
|
+
FROM sys.indexes i
|
|
2053
|
+
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
2054
|
+
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
2055
|
+
WHERE i.name = @indexName
|
|
2056
|
+
AND s.name = @schemaName
|
|
2057
|
+
AND t.name = @tableName
|
|
2058
|
+
`);
|
|
2059
|
+
if (indexExists.recordset && indexExists.recordset.length > 0) {
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
const uniqueStr = unique ? "UNIQUE " : "";
|
|
2063
|
+
const columnsStr = columns.map((col) => {
|
|
2064
|
+
if (col.includes(" DESC") || col.includes(" ASC")) {
|
|
2065
|
+
const [colName, ...modifiers] = col.split(" ");
|
|
2066
|
+
if (!colName) {
|
|
2067
|
+
throw new Error(`Invalid column specification: ${col}`);
|
|
2068
|
+
}
|
|
2069
|
+
return `[${utils.parseSqlIdentifier(colName, "column name")}] ${modifiers.join(" ")}`;
|
|
2070
|
+
}
|
|
2071
|
+
return `[${utils.parseSqlIdentifier(col, "column name")}]`;
|
|
2072
|
+
}).join(", ");
|
|
2073
|
+
const whereStr = where ? ` WHERE ${where}` : "";
|
|
2074
|
+
const createIndexSql = `CREATE ${uniqueStr}INDEX [${indexNameSafe}] ON ${fullTableName} (${columnsStr})${whereStr}`;
|
|
2075
|
+
await this.pool.request().query(createIndexSql);
|
|
2076
|
+
} catch (error$1) {
|
|
2077
|
+
throw new error.MastraError(
|
|
2078
|
+
{
|
|
2079
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_CREATE_FAILED",
|
|
2080
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2081
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2082
|
+
details: {
|
|
2083
|
+
indexName: options.name,
|
|
2084
|
+
tableName: options.table
|
|
2085
|
+
}
|
|
2086
|
+
},
|
|
2087
|
+
error$1
|
|
2088
|
+
);
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Drop an existing index
|
|
2093
|
+
*/
|
|
2094
|
+
async dropIndex(indexName) {
|
|
2095
|
+
try {
|
|
2096
|
+
const schemaName = this.schemaName || "dbo";
|
|
2097
|
+
const indexNameSafe = utils.parseSqlIdentifier(indexName, "index name");
|
|
2098
|
+
const checkRequest = this.pool.request();
|
|
2099
|
+
checkRequest.input("indexName", indexNameSafe);
|
|
2100
|
+
checkRequest.input("schemaName", schemaName);
|
|
2101
|
+
const result = await checkRequest.query(`
|
|
2102
|
+
SELECT t.name as table_name
|
|
2103
|
+
FROM sys.indexes i
|
|
2104
|
+
INNER JOIN sys.tables t ON i.object_id = t.object_id
|
|
2105
|
+
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
2106
|
+
WHERE i.name = @indexName
|
|
2107
|
+
AND s.name = @schemaName
|
|
2108
|
+
`);
|
|
2109
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2110
|
+
return;
|
|
2111
|
+
}
|
|
2112
|
+
if (result.recordset.length > 1) {
|
|
2113
|
+
const tables = result.recordset.map((r) => r.table_name).join(", ");
|
|
2114
|
+
throw new error.MastraError({
|
|
2115
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_AMBIGUOUS",
|
|
2116
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2117
|
+
category: error.ErrorCategory.USER,
|
|
2118
|
+
text: `Index "${indexNameSafe}" exists on multiple tables (${tables}) in schema "${schemaName}". Please drop indexes manually or ensure unique index names.`
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
const tableName = result.recordset[0].table_name;
|
|
2122
|
+
const fullTableName = getTableName({
|
|
2123
|
+
indexName: tableName,
|
|
2124
|
+
schemaName: getSchemaName(this.schemaName)
|
|
2125
|
+
});
|
|
2126
|
+
const dropSql = `DROP INDEX [${indexNameSafe}] ON ${fullTableName}`;
|
|
2127
|
+
await this.pool.request().query(dropSql);
|
|
2128
|
+
} catch (error$1) {
|
|
2129
|
+
throw new error.MastraError(
|
|
2130
|
+
{
|
|
2131
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_DROP_FAILED",
|
|
2132
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2133
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2134
|
+
details: {
|
|
2135
|
+
indexName
|
|
2136
|
+
}
|
|
2137
|
+
},
|
|
2138
|
+
error$1
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
/**
|
|
2143
|
+
* List indexes for a specific table or all tables
|
|
2144
|
+
*/
|
|
2145
|
+
async listIndexes(tableName) {
|
|
2146
|
+
try {
|
|
2147
|
+
const schemaName = this.schemaName || "dbo";
|
|
2148
|
+
let query;
|
|
2149
|
+
const request = this.pool.request();
|
|
2150
|
+
request.input("schemaName", schemaName);
|
|
2151
|
+
if (tableName) {
|
|
2152
|
+
query = `
|
|
2153
|
+
SELECT
|
|
2154
|
+
i.name as name,
|
|
2155
|
+
o.name as [table],
|
|
2156
|
+
i.is_unique as is_unique,
|
|
2157
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
|
|
2158
|
+
FROM sys.indexes i
|
|
2159
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2160
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2161
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2162
|
+
WHERE sch.name = @schemaName
|
|
2163
|
+
AND o.name = @tableName
|
|
2164
|
+
AND i.name IS NOT NULL
|
|
2165
|
+
GROUP BY i.name, o.name, i.is_unique
|
|
2166
|
+
`;
|
|
2167
|
+
request.input("tableName", tableName);
|
|
2168
|
+
} else {
|
|
2169
|
+
query = `
|
|
2170
|
+
SELECT
|
|
2171
|
+
i.name as name,
|
|
2172
|
+
o.name as [table],
|
|
2173
|
+
i.is_unique as is_unique,
|
|
2174
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
|
|
2175
|
+
FROM sys.indexes i
|
|
2176
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2177
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2178
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2179
|
+
WHERE sch.name = @schemaName
|
|
2180
|
+
AND i.name IS NOT NULL
|
|
2181
|
+
GROUP BY i.name, o.name, i.is_unique
|
|
2182
|
+
`;
|
|
2183
|
+
}
|
|
2184
|
+
const result = await request.query(query);
|
|
2185
|
+
const indexes = [];
|
|
2186
|
+
for (const row of result.recordset) {
|
|
2187
|
+
const colRequest = this.pool.request();
|
|
2188
|
+
colRequest.input("indexName", row.name);
|
|
2189
|
+
colRequest.input("schemaName", schemaName);
|
|
2190
|
+
const colResult = await colRequest.query(`
|
|
2191
|
+
SELECT c.name as column_name
|
|
2192
|
+
FROM sys.indexes i
|
|
2193
|
+
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
2194
|
+
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
2195
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2196
|
+
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
2197
|
+
WHERE i.name = @indexName
|
|
2198
|
+
AND s.name = @schemaName
|
|
2199
|
+
ORDER BY ic.key_ordinal
|
|
2200
|
+
`);
|
|
2201
|
+
indexes.push({
|
|
2202
|
+
name: row.name,
|
|
2203
|
+
table: row.table,
|
|
2204
|
+
columns: colResult.recordset.map((c) => c.column_name),
|
|
2205
|
+
unique: row.is_unique || false,
|
|
2206
|
+
size: row.size || "0 MB",
|
|
2207
|
+
definition: ""
|
|
2208
|
+
// MSSQL doesn't store definition like PG
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
return indexes;
|
|
2212
|
+
} catch (error$1) {
|
|
2213
|
+
throw new error.MastraError(
|
|
2214
|
+
{
|
|
2215
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_LIST_FAILED",
|
|
2216
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2217
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2218
|
+
details: tableName ? {
|
|
2219
|
+
tableName
|
|
2220
|
+
} : {}
|
|
2221
|
+
},
|
|
2222
|
+
error$1
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
/**
|
|
2227
|
+
* Get detailed statistics for a specific index
|
|
2228
|
+
*/
|
|
2229
|
+
async describeIndex(indexName) {
|
|
2230
|
+
try {
|
|
2231
|
+
const schemaName = this.schemaName || "dbo";
|
|
2232
|
+
const request = this.pool.request();
|
|
2233
|
+
request.input("indexName", indexName);
|
|
2234
|
+
request.input("schemaName", schemaName);
|
|
2235
|
+
const query = `
|
|
2236
|
+
SELECT
|
|
2237
|
+
i.name as name,
|
|
2238
|
+
o.name as [table],
|
|
2239
|
+
i.is_unique as is_unique,
|
|
2240
|
+
CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size,
|
|
2241
|
+
i.type_desc as method,
|
|
2242
|
+
ISNULL(us.user_scans, 0) as scans,
|
|
2243
|
+
ISNULL(us.user_seeks + us.user_scans, 0) as tuples_read,
|
|
2244
|
+
ISNULL(us.user_lookups, 0) as tuples_fetched
|
|
2245
|
+
FROM sys.indexes i
|
|
2246
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2247
|
+
INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
|
|
2248
|
+
LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
|
|
2249
|
+
LEFT JOIN sys.dm_db_index_usage_stats us ON i.object_id = us.object_id AND i.index_id = us.index_id
|
|
2250
|
+
WHERE i.name = @indexName
|
|
2251
|
+
AND sch.name = @schemaName
|
|
2252
|
+
GROUP BY i.name, o.name, i.is_unique, i.type_desc, us.user_seeks, us.user_scans, us.user_lookups
|
|
2253
|
+
`;
|
|
2254
|
+
const result = await request.query(query);
|
|
2255
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2256
|
+
throw new Error(`Index "${indexName}" not found in schema "${schemaName}"`);
|
|
1384
2257
|
}
|
|
1385
|
-
|
|
2258
|
+
const row = result.recordset[0];
|
|
2259
|
+
const colRequest = this.pool.request();
|
|
2260
|
+
colRequest.input("indexName", indexName);
|
|
2261
|
+
colRequest.input("schemaName", schemaName);
|
|
2262
|
+
const colResult = await colRequest.query(`
|
|
2263
|
+
SELECT c.name as column_name
|
|
2264
|
+
FROM sys.indexes i
|
|
2265
|
+
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
2266
|
+
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
2267
|
+
INNER JOIN sys.objects o ON i.object_id = o.object_id
|
|
2268
|
+
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
2269
|
+
WHERE i.name = @indexName
|
|
2270
|
+
AND s.name = @schemaName
|
|
2271
|
+
ORDER BY ic.key_ordinal
|
|
2272
|
+
`);
|
|
2273
|
+
return {
|
|
2274
|
+
name: row.name,
|
|
2275
|
+
table: row.table,
|
|
2276
|
+
columns: colResult.recordset.map((c) => c.column_name),
|
|
2277
|
+
unique: row.is_unique || false,
|
|
2278
|
+
size: row.size || "0 MB",
|
|
2279
|
+
definition: "",
|
|
2280
|
+
method: row.method?.toLowerCase() || "nonclustered",
|
|
2281
|
+
scans: Number(row.scans) || 0,
|
|
2282
|
+
tuples_read: Number(row.tuples_read) || 0,
|
|
2283
|
+
tuples_fetched: Number(row.tuples_fetched) || 0
|
|
2284
|
+
};
|
|
1386
2285
|
} catch (error$1) {
|
|
1387
|
-
await transaction.rollback();
|
|
1388
2286
|
throw new error.MastraError(
|
|
1389
2287
|
{
|
|
1390
|
-
id: "
|
|
2288
|
+
id: "MASTRA_STORAGE_MSSQL_INDEX_DESCRIBE_FAILED",
|
|
1391
2289
|
domain: error.ErrorDomain.STORAGE,
|
|
1392
2290
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1393
2291
|
details: {
|
|
1394
|
-
|
|
1395
|
-
numberOfRecords: records.length
|
|
2292
|
+
indexName
|
|
1396
2293
|
}
|
|
1397
2294
|
},
|
|
1398
2295
|
error$1
|
|
1399
2296
|
);
|
|
1400
2297
|
}
|
|
1401
2298
|
}
|
|
1402
|
-
|
|
2299
|
+
/**
|
|
2300
|
+
* Returns definitions for automatic performance indexes
|
|
2301
|
+
* IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
|
|
2302
|
+
* NOTE: Using NVARCHAR(400) for text columns (800 bytes) leaves room for composite indexes
|
|
2303
|
+
*/
|
|
2304
|
+
getAutomaticIndexDefinitions() {
|
|
2305
|
+
const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
|
|
2306
|
+
return [
|
|
2307
|
+
// Composite indexes for optimal filtering + sorting performance
|
|
2308
|
+
// NVARCHAR(400) = 800 bytes, plus BIGINT (8 bytes) = 808 bytes total (under 900-byte limit)
|
|
2309
|
+
{
|
|
2310
|
+
name: `${schemaPrefix}mastra_threads_resourceid_seqid_idx`,
|
|
2311
|
+
table: storage.TABLE_THREADS,
|
|
2312
|
+
columns: ["resourceId", "seq_id DESC"]
|
|
2313
|
+
},
|
|
2314
|
+
{
|
|
2315
|
+
name: `${schemaPrefix}mastra_messages_thread_id_seqid_idx`,
|
|
2316
|
+
table: storage.TABLE_MESSAGES,
|
|
2317
|
+
columns: ["thread_id", "seq_id DESC"]
|
|
2318
|
+
},
|
|
2319
|
+
{
|
|
2320
|
+
name: `${schemaPrefix}mastra_traces_name_seqid_idx`,
|
|
2321
|
+
table: storage.TABLE_TRACES,
|
|
2322
|
+
columns: ["name", "seq_id DESC"]
|
|
2323
|
+
},
|
|
2324
|
+
{
|
|
2325
|
+
name: `${schemaPrefix}mastra_scores_trace_id_span_id_seqid_idx`,
|
|
2326
|
+
table: storage.TABLE_SCORERS,
|
|
2327
|
+
columns: ["traceId", "spanId", "seq_id DESC"]
|
|
2328
|
+
},
|
|
2329
|
+
// AI Spans indexes for optimal trace querying
|
|
2330
|
+
{
|
|
2331
|
+
name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
|
|
2332
|
+
table: storage.TABLE_AI_SPANS,
|
|
2333
|
+
columns: ["traceId", "startedAt DESC"]
|
|
2334
|
+
},
|
|
2335
|
+
{
|
|
2336
|
+
name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
|
|
2337
|
+
table: storage.TABLE_AI_SPANS,
|
|
2338
|
+
columns: ["parentSpanId", "startedAt DESC"]
|
|
2339
|
+
},
|
|
2340
|
+
{
|
|
2341
|
+
name: `${schemaPrefix}mastra_ai_spans_name_idx`,
|
|
2342
|
+
table: storage.TABLE_AI_SPANS,
|
|
2343
|
+
columns: ["name"]
|
|
2344
|
+
},
|
|
2345
|
+
{
|
|
2346
|
+
name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
|
|
2347
|
+
table: storage.TABLE_AI_SPANS,
|
|
2348
|
+
columns: ["spanType", "startedAt DESC"]
|
|
2349
|
+
}
|
|
2350
|
+
];
|
|
2351
|
+
}
|
|
2352
|
+
/**
|
|
2353
|
+
* Creates automatic indexes for optimal query performance
|
|
2354
|
+
* Uses getAutomaticIndexDefinitions() to determine which indexes to create
|
|
2355
|
+
*/
|
|
2356
|
+
async createAutomaticIndexes() {
|
|
1403
2357
|
try {
|
|
1404
|
-
const
|
|
1405
|
-
|
|
2358
|
+
const indexes = this.getAutomaticIndexDefinitions();
|
|
2359
|
+
for (const indexOptions of indexes) {
|
|
2360
|
+
try {
|
|
2361
|
+
await this.createIndex(indexOptions);
|
|
2362
|
+
} catch (error) {
|
|
2363
|
+
this.logger?.warn?.(`Failed to create index ${indexOptions.name}:`, error);
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
1406
2366
|
} catch (error$1) {
|
|
1407
2367
|
throw new error.MastraError(
|
|
1408
2368
|
{
|
|
1409
|
-
id: "
|
|
2369
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_CREATE_PERFORMANCE_INDEXES_FAILED",
|
|
1410
2370
|
domain: error.ErrorDomain.STORAGE,
|
|
1411
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1412
|
-
details: {
|
|
1413
|
-
tableName
|
|
1414
|
-
}
|
|
2371
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1415
2372
|
},
|
|
1416
2373
|
error$1
|
|
1417
2374
|
);
|
|
1418
2375
|
}
|
|
1419
2376
|
}
|
|
1420
2377
|
};
|
|
1421
|
-
function parseJSON(jsonString) {
|
|
1422
|
-
try {
|
|
1423
|
-
return JSON.parse(jsonString);
|
|
1424
|
-
} catch {
|
|
1425
|
-
return jsonString;
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
2378
|
function transformScoreRow(row) {
|
|
1429
2379
|
return {
|
|
1430
2380
|
...row,
|
|
1431
|
-
input:
|
|
1432
|
-
scorer:
|
|
1433
|
-
preprocessStepResult:
|
|
1434
|
-
analyzeStepResult:
|
|
1435
|
-
metadata:
|
|
1436
|
-
output:
|
|
1437
|
-
additionalContext:
|
|
1438
|
-
|
|
1439
|
-
entity:
|
|
2381
|
+
input: storage.safelyParseJSON(row.input),
|
|
2382
|
+
scorer: storage.safelyParseJSON(row.scorer),
|
|
2383
|
+
preprocessStepResult: storage.safelyParseJSON(row.preprocessStepResult),
|
|
2384
|
+
analyzeStepResult: storage.safelyParseJSON(row.analyzeStepResult),
|
|
2385
|
+
metadata: storage.safelyParseJSON(row.metadata),
|
|
2386
|
+
output: storage.safelyParseJSON(row.output),
|
|
2387
|
+
additionalContext: storage.safelyParseJSON(row.additionalContext),
|
|
2388
|
+
requestContext: storage.safelyParseJSON(row.requestContext),
|
|
2389
|
+
entity: storage.safelyParseJSON(row.entity),
|
|
1440
2390
|
createdAt: row.createdAt,
|
|
1441
2391
|
updatedAt: row.updatedAt
|
|
1442
2392
|
};
|
|
@@ -1479,6 +2429,19 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1479
2429
|
}
|
|
1480
2430
|
}
|
|
1481
2431
|
async saveScore(score) {
|
|
2432
|
+
let validatedScore;
|
|
2433
|
+
try {
|
|
2434
|
+
validatedScore = scores.saveScorePayloadSchema.parse(score);
|
|
2435
|
+
} catch (error$1) {
|
|
2436
|
+
throw new error.MastraError(
|
|
2437
|
+
{
|
|
2438
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_SAVE_SCORE_VALIDATION_FAILED",
|
|
2439
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2440
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
2441
|
+
},
|
|
2442
|
+
error$1
|
|
2443
|
+
);
|
|
2444
|
+
}
|
|
1482
2445
|
try {
|
|
1483
2446
|
const scoreId = crypto.randomUUID();
|
|
1484
2447
|
const {
|
|
@@ -1489,24 +2452,24 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1489
2452
|
input,
|
|
1490
2453
|
output,
|
|
1491
2454
|
additionalContext,
|
|
1492
|
-
|
|
2455
|
+
requestContext,
|
|
1493
2456
|
entity,
|
|
1494
2457
|
...rest
|
|
1495
|
-
} =
|
|
2458
|
+
} = validatedScore;
|
|
1496
2459
|
await this.operations.insert({
|
|
1497
2460
|
tableName: storage.TABLE_SCORERS,
|
|
1498
2461
|
record: {
|
|
1499
2462
|
id: scoreId,
|
|
1500
2463
|
...rest,
|
|
1501
|
-
input:
|
|
1502
|
-
output:
|
|
1503
|
-
preprocessStepResult: preprocessStepResult
|
|
1504
|
-
analyzeStepResult: analyzeStepResult
|
|
1505
|
-
metadata: metadata
|
|
1506
|
-
additionalContext: additionalContext
|
|
1507
|
-
|
|
1508
|
-
entity: entity
|
|
1509
|
-
scorer: scorer
|
|
2464
|
+
input: input || "",
|
|
2465
|
+
output: output || "",
|
|
2466
|
+
preprocessStepResult: preprocessStepResult || null,
|
|
2467
|
+
analyzeStepResult: analyzeStepResult || null,
|
|
2468
|
+
metadata: metadata || null,
|
|
2469
|
+
additionalContext: additionalContext || null,
|
|
2470
|
+
requestContext: requestContext || null,
|
|
2471
|
+
entity: entity || null,
|
|
2472
|
+
scorer: scorer || null,
|
|
1510
2473
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1511
2474
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1512
2475
|
}
|
|
@@ -1526,14 +2489,37 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1526
2489
|
}
|
|
1527
2490
|
async getScoresByScorerId({
|
|
1528
2491
|
scorerId,
|
|
1529
|
-
pagination
|
|
2492
|
+
pagination,
|
|
2493
|
+
entityId,
|
|
2494
|
+
entityType,
|
|
2495
|
+
source
|
|
1530
2496
|
}) {
|
|
1531
2497
|
try {
|
|
1532
|
-
const
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
2498
|
+
const conditions = ["[scorerId] = @p1"];
|
|
2499
|
+
const params = { p1: scorerId };
|
|
2500
|
+
let paramIndex = 2;
|
|
2501
|
+
if (entityId) {
|
|
2502
|
+
conditions.push(`[entityId] = @p${paramIndex}`);
|
|
2503
|
+
params[`p${paramIndex}`] = entityId;
|
|
2504
|
+
paramIndex++;
|
|
2505
|
+
}
|
|
2506
|
+
if (entityType) {
|
|
2507
|
+
conditions.push(`[entityType] = @p${paramIndex}`);
|
|
2508
|
+
params[`p${paramIndex}`] = entityType;
|
|
2509
|
+
paramIndex++;
|
|
2510
|
+
}
|
|
2511
|
+
if (source) {
|
|
2512
|
+
conditions.push(`[source] = @p${paramIndex}`);
|
|
2513
|
+
params[`p${paramIndex}`] = source;
|
|
2514
|
+
paramIndex++;
|
|
2515
|
+
}
|
|
2516
|
+
const whereClause = conditions.join(" AND ");
|
|
2517
|
+
const tableName = getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) });
|
|
2518
|
+
const countRequest = this.pool.request();
|
|
2519
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
2520
|
+
countRequest.input(key, value);
|
|
2521
|
+
});
|
|
2522
|
+
const totalResult = await countRequest.query(`SELECT COUNT(*) as count FROM ${tableName} WHERE ${whereClause}`);
|
|
1537
2523
|
const total = totalResult.recordset[0]?.count || 0;
|
|
1538
2524
|
if (total === 0) {
|
|
1539
2525
|
return {
|
|
@@ -1547,12 +2533,13 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1547
2533
|
};
|
|
1548
2534
|
}
|
|
1549
2535
|
const dataRequest = this.pool.request();
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
2536
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
2537
|
+
dataRequest.input(key, value);
|
|
2538
|
+
});
|
|
2539
|
+
dataRequest.input("perPage", pagination.perPage);
|
|
2540
|
+
dataRequest.input("offset", pagination.page * pagination.perPage);
|
|
2541
|
+
const dataQuery = `SELECT * FROM ${tableName} WHERE ${whereClause} ORDER BY [createdAt] DESC OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
|
|
2542
|
+
const result = await dataRequest.query(dataQuery);
|
|
1556
2543
|
return {
|
|
1557
2544
|
pagination: {
|
|
1558
2545
|
total: Number(total),
|
|
@@ -1677,8 +2664,62 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
1677
2664
|
);
|
|
1678
2665
|
}
|
|
1679
2666
|
}
|
|
2667
|
+
async getScoresBySpan({
|
|
2668
|
+
traceId,
|
|
2669
|
+
spanId,
|
|
2670
|
+
pagination
|
|
2671
|
+
}) {
|
|
2672
|
+
try {
|
|
2673
|
+
const request = this.pool.request();
|
|
2674
|
+
request.input("p1", traceId);
|
|
2675
|
+
request.input("p2", spanId);
|
|
2676
|
+
const totalResult = await request.query(
|
|
2677
|
+
`SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [traceId] = @p1 AND [spanId] = @p2`
|
|
2678
|
+
);
|
|
2679
|
+
const total = totalResult.recordset[0]?.count || 0;
|
|
2680
|
+
if (total === 0) {
|
|
2681
|
+
return {
|
|
2682
|
+
pagination: {
|
|
2683
|
+
total: 0,
|
|
2684
|
+
page: pagination.page,
|
|
2685
|
+
perPage: pagination.perPage,
|
|
2686
|
+
hasMore: false
|
|
2687
|
+
},
|
|
2688
|
+
scores: []
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
const limit = pagination.perPage + 1;
|
|
2692
|
+
const dataRequest = this.pool.request();
|
|
2693
|
+
dataRequest.input("p1", traceId);
|
|
2694
|
+
dataRequest.input("p2", spanId);
|
|
2695
|
+
dataRequest.input("p3", limit);
|
|
2696
|
+
dataRequest.input("p4", pagination.page * pagination.perPage);
|
|
2697
|
+
const result = await dataRequest.query(
|
|
2698
|
+
`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`
|
|
2699
|
+
);
|
|
2700
|
+
return {
|
|
2701
|
+
pagination: {
|
|
2702
|
+
total: Number(total),
|
|
2703
|
+
page: pagination.page,
|
|
2704
|
+
perPage: pagination.perPage,
|
|
2705
|
+
hasMore: result.recordset.length > pagination.perPage
|
|
2706
|
+
},
|
|
2707
|
+
scores: result.recordset.slice(0, pagination.perPage).map((row) => transformScoreRow(row))
|
|
2708
|
+
};
|
|
2709
|
+
} catch (error$1) {
|
|
2710
|
+
throw new error.MastraError(
|
|
2711
|
+
{
|
|
2712
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_GET_SCORES_BY_SPAN_FAILED",
|
|
2713
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2714
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2715
|
+
details: { traceId, spanId }
|
|
2716
|
+
},
|
|
2717
|
+
error$1
|
|
2718
|
+
);
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
1680
2721
|
};
|
|
1681
|
-
var
|
|
2722
|
+
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
1682
2723
|
pool;
|
|
1683
2724
|
operations;
|
|
1684
2725
|
schema;
|
|
@@ -1692,210 +2733,168 @@ var TracesMSSQL = class extends storage.TracesStorage {
|
|
|
1692
2733
|
this.operations = operations;
|
|
1693
2734
|
this.schema = schema;
|
|
1694
2735
|
}
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
if (
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
const result = await this.getTracesPaginated(args);
|
|
1704
|
-
return result.traces;
|
|
1705
|
-
}
|
|
1706
|
-
async getTracesPaginated(args) {
|
|
1707
|
-
const { name, scope, page = 0, perPage: perPageInput, attributes, filters, dateRange } = args;
|
|
1708
|
-
const fromDate = dateRange?.start;
|
|
1709
|
-
const toDate = dateRange?.end;
|
|
1710
|
-
const perPage = perPageInput !== void 0 ? perPageInput : 100;
|
|
1711
|
-
const currentOffset = page * perPage;
|
|
1712
|
-
const paramMap = {};
|
|
1713
|
-
const conditions = [];
|
|
1714
|
-
let paramIndex = 1;
|
|
1715
|
-
if (name) {
|
|
1716
|
-
const paramName = `p${paramIndex++}`;
|
|
1717
|
-
conditions.push(`[name] LIKE @${paramName}`);
|
|
1718
|
-
paramMap[paramName] = `${name}%`;
|
|
1719
|
-
}
|
|
1720
|
-
if (scope) {
|
|
1721
|
-
const paramName = `p${paramIndex++}`;
|
|
1722
|
-
conditions.push(`[scope] = @${paramName}`);
|
|
1723
|
-
paramMap[paramName] = scope;
|
|
1724
|
-
}
|
|
1725
|
-
if (attributes) {
|
|
1726
|
-
Object.entries(attributes).forEach(([key, value]) => {
|
|
1727
|
-
const parsedKey = utils.parseFieldKey(key);
|
|
1728
|
-
const paramName = `p${paramIndex++}`;
|
|
1729
|
-
conditions.push(`JSON_VALUE([attributes], '$.${parsedKey}') = @${paramName}`);
|
|
1730
|
-
paramMap[paramName] = value;
|
|
1731
|
-
});
|
|
1732
|
-
}
|
|
1733
|
-
if (filters) {
|
|
1734
|
-
Object.entries(filters).forEach(([key, value]) => {
|
|
1735
|
-
const parsedKey = utils.parseFieldKey(key);
|
|
1736
|
-
const paramName = `p${paramIndex++}`;
|
|
1737
|
-
conditions.push(`[${parsedKey}] = @${paramName}`);
|
|
1738
|
-
paramMap[paramName] = value;
|
|
1739
|
-
});
|
|
1740
|
-
}
|
|
1741
|
-
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
1742
|
-
const paramName = `p${paramIndex++}`;
|
|
1743
|
-
conditions.push(`[createdAt] >= @${paramName}`);
|
|
1744
|
-
paramMap[paramName] = fromDate.toISOString();
|
|
1745
|
-
}
|
|
1746
|
-
if (toDate instanceof Date && !isNaN(toDate.getTime())) {
|
|
1747
|
-
const paramName = `p${paramIndex++}`;
|
|
1748
|
-
conditions.push(`[createdAt] <= @${paramName}`);
|
|
1749
|
-
paramMap[paramName] = toDate.toISOString();
|
|
2736
|
+
parseWorkflowRun(row) {
|
|
2737
|
+
let parsedSnapshot = row.snapshot;
|
|
2738
|
+
if (typeof parsedSnapshot === "string") {
|
|
2739
|
+
try {
|
|
2740
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
2741
|
+
} catch (e) {
|
|
2742
|
+
this.logger?.warn?.(`Failed to parse snapshot for workflow ${row.workflow_name}:`, e);
|
|
2743
|
+
}
|
|
1750
2744
|
}
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
2745
|
+
return {
|
|
2746
|
+
workflowName: row.workflow_name,
|
|
2747
|
+
runId: row.run_id,
|
|
2748
|
+
snapshot: parsedSnapshot,
|
|
2749
|
+
createdAt: row.createdAt,
|
|
2750
|
+
updatedAt: row.updatedAt,
|
|
2751
|
+
resourceId: row.resourceId
|
|
2752
|
+
};
|
|
2753
|
+
}
|
|
2754
|
+
async updateWorkflowResults({
|
|
2755
|
+
workflowName,
|
|
2756
|
+
runId,
|
|
2757
|
+
stepId,
|
|
2758
|
+
result,
|
|
2759
|
+
requestContext
|
|
2760
|
+
}) {
|
|
2761
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2762
|
+
const transaction = this.pool.transaction();
|
|
1754
2763
|
try {
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
2764
|
+
await transaction.begin();
|
|
2765
|
+
const selectRequest = new sql2__default.default.Request(transaction);
|
|
2766
|
+
selectRequest.input("workflow_name", workflowName);
|
|
2767
|
+
selectRequest.input("run_id", runId);
|
|
2768
|
+
const existingSnapshotResult = await selectRequest.query(
|
|
2769
|
+
`SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2770
|
+
);
|
|
2771
|
+
let snapshot;
|
|
2772
|
+
if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
|
|
2773
|
+
snapshot = {
|
|
2774
|
+
context: {},
|
|
2775
|
+
activePaths: [],
|
|
2776
|
+
timestamp: Date.now(),
|
|
2777
|
+
suspendedPaths: {},
|
|
2778
|
+
resumeLabels: {},
|
|
2779
|
+
serializedStepGraph: [],
|
|
2780
|
+
value: {},
|
|
2781
|
+
waitingPaths: {},
|
|
2782
|
+
status: "pending",
|
|
2783
|
+
runId,
|
|
2784
|
+
requestContext: {}
|
|
2785
|
+
};
|
|
2786
|
+
} else {
|
|
2787
|
+
const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
|
|
2788
|
+
snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
2789
|
+
}
|
|
2790
|
+
snapshot.context[stepId] = result;
|
|
2791
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
2792
|
+
const upsertReq = new sql2__default.default.Request(transaction);
|
|
2793
|
+
upsertReq.input("workflow_name", workflowName);
|
|
2794
|
+
upsertReq.input("run_id", runId);
|
|
2795
|
+
upsertReq.input("snapshot", JSON.stringify(snapshot));
|
|
2796
|
+
upsertReq.input("createdAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2797
|
+
upsertReq.input("updatedAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2798
|
+
await upsertReq.query(
|
|
2799
|
+
`MERGE ${table} AS target
|
|
2800
|
+
USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
|
|
2801
|
+
ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
|
|
2802
|
+
WHEN MATCHED THEN UPDATE SET snapshot = @snapshot, [updatedAt] = @updatedAt
|
|
2803
|
+
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
|
|
2804
|
+
VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`
|
|
2805
|
+
);
|
|
2806
|
+
await transaction.commit();
|
|
2807
|
+
return snapshot.context;
|
|
1765
2808
|
} catch (error$1) {
|
|
2809
|
+
try {
|
|
2810
|
+
await transaction.rollback();
|
|
2811
|
+
} catch {
|
|
2812
|
+
}
|
|
1766
2813
|
throw new error.MastraError(
|
|
1767
2814
|
{
|
|
1768
|
-
id: "
|
|
2815
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_RESULTS_FAILED",
|
|
1769
2816
|
domain: error.ErrorDomain.STORAGE,
|
|
1770
2817
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1771
2818
|
details: {
|
|
1772
|
-
|
|
1773
|
-
|
|
2819
|
+
workflowName,
|
|
2820
|
+
runId,
|
|
2821
|
+
stepId
|
|
1774
2822
|
}
|
|
1775
2823
|
},
|
|
1776
2824
|
error$1
|
|
1777
2825
|
);
|
|
1778
2826
|
}
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
}
|
|
1788
|
-
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`;
|
|
1789
|
-
const dataRequest = this.pool.request();
|
|
1790
|
-
Object.entries(paramMap).forEach(([key, value]) => {
|
|
1791
|
-
if (value instanceof Date) {
|
|
1792
|
-
dataRequest.input(key, sql2__default.default.DateTime, value);
|
|
1793
|
-
} else {
|
|
1794
|
-
dataRequest.input(key, value);
|
|
1795
|
-
}
|
|
1796
|
-
});
|
|
1797
|
-
dataRequest.input("offset", currentOffset);
|
|
1798
|
-
dataRequest.input("limit", perPage);
|
|
2827
|
+
}
|
|
2828
|
+
async updateWorkflowState({
|
|
2829
|
+
workflowName,
|
|
2830
|
+
runId,
|
|
2831
|
+
opts
|
|
2832
|
+
}) {
|
|
2833
|
+
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
2834
|
+
const transaction = this.pool.transaction();
|
|
1799
2835
|
try {
|
|
1800
|
-
|
|
1801
|
-
const
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
2836
|
+
await transaction.begin();
|
|
2837
|
+
const selectRequest = new sql2__default.default.Request(transaction);
|
|
2838
|
+
selectRequest.input("workflow_name", workflowName);
|
|
2839
|
+
selectRequest.input("run_id", runId);
|
|
2840
|
+
const existingSnapshotResult = await selectRequest.query(
|
|
2841
|
+
`SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2842
|
+
);
|
|
2843
|
+
if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
|
|
2844
|
+
await transaction.rollback();
|
|
2845
|
+
return void 0;
|
|
2846
|
+
}
|
|
2847
|
+
const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
|
|
2848
|
+
const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
2849
|
+
if (!snapshot || !snapshot?.context) {
|
|
2850
|
+
await transaction.rollback();
|
|
2851
|
+
throw new error.MastraError(
|
|
2852
|
+
{
|
|
2853
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_SNAPSHOT_NOT_FOUND",
|
|
2854
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2855
|
+
category: error.ErrorCategory.SYSTEM,
|
|
2856
|
+
details: {
|
|
2857
|
+
workflowName,
|
|
2858
|
+
runId
|
|
2859
|
+
}
|
|
2860
|
+
},
|
|
2861
|
+
new Error(`Snapshot not found for runId ${runId}`)
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
2865
|
+
const updateRequest = new sql2__default.default.Request(transaction);
|
|
2866
|
+
updateRequest.input("snapshot", JSON.stringify(updatedSnapshot));
|
|
2867
|
+
updateRequest.input("workflow_name", workflowName);
|
|
2868
|
+
updateRequest.input("run_id", runId);
|
|
2869
|
+
updateRequest.input("updatedAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
|
|
2870
|
+
await updateRequest.query(
|
|
2871
|
+
`UPDATE ${table} SET snapshot = @snapshot, [updatedAt] = @updatedAt WHERE workflow_name = @workflow_name AND run_id = @run_id`
|
|
2872
|
+
);
|
|
2873
|
+
await transaction.commit();
|
|
2874
|
+
return updatedSnapshot;
|
|
1825
2875
|
} catch (error$1) {
|
|
2876
|
+
try {
|
|
2877
|
+
await transaction.rollback();
|
|
2878
|
+
} catch {
|
|
2879
|
+
}
|
|
1826
2880
|
throw new error.MastraError(
|
|
1827
2881
|
{
|
|
1828
|
-
id: "
|
|
2882
|
+
id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_FAILED",
|
|
1829
2883
|
domain: error.ErrorDomain.STORAGE,
|
|
1830
2884
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1831
2885
|
details: {
|
|
1832
|
-
|
|
1833
|
-
|
|
2886
|
+
workflowName,
|
|
2887
|
+
runId
|
|
1834
2888
|
}
|
|
1835
2889
|
},
|
|
1836
2890
|
error$1
|
|
1837
2891
|
);
|
|
1838
2892
|
}
|
|
1839
2893
|
}
|
|
1840
|
-
async batchTraceInsert({ records }) {
|
|
1841
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1842
|
-
await this.operations.batchInsert({
|
|
1843
|
-
tableName: storage.TABLE_TRACES,
|
|
1844
|
-
records
|
|
1845
|
-
});
|
|
1846
|
-
}
|
|
1847
|
-
};
|
|
1848
|
-
function parseWorkflowRun(row) {
|
|
1849
|
-
let parsedSnapshot = row.snapshot;
|
|
1850
|
-
if (typeof parsedSnapshot === "string") {
|
|
1851
|
-
try {
|
|
1852
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1853
|
-
} catch (e) {
|
|
1854
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
return {
|
|
1858
|
-
workflowName: row.workflow_name,
|
|
1859
|
-
runId: row.run_id,
|
|
1860
|
-
snapshot: parsedSnapshot,
|
|
1861
|
-
createdAt: row.createdAt,
|
|
1862
|
-
updatedAt: row.updatedAt,
|
|
1863
|
-
resourceId: row.resourceId
|
|
1864
|
-
};
|
|
1865
|
-
}
|
|
1866
|
-
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
1867
|
-
pool;
|
|
1868
|
-
operations;
|
|
1869
|
-
schema;
|
|
1870
|
-
constructor({
|
|
1871
|
-
pool,
|
|
1872
|
-
operations,
|
|
1873
|
-
schema
|
|
1874
|
-
}) {
|
|
1875
|
-
super();
|
|
1876
|
-
this.pool = pool;
|
|
1877
|
-
this.operations = operations;
|
|
1878
|
-
this.schema = schema;
|
|
1879
|
-
}
|
|
1880
|
-
updateWorkflowResults({
|
|
1881
|
-
// workflowName,
|
|
1882
|
-
// runId,
|
|
1883
|
-
// stepId,
|
|
1884
|
-
// result,
|
|
1885
|
-
// runtimeContext,
|
|
1886
|
-
}) {
|
|
1887
|
-
throw new Error("Method not implemented.");
|
|
1888
|
-
}
|
|
1889
|
-
updateWorkflowState({
|
|
1890
|
-
// workflowName,
|
|
1891
|
-
// runId,
|
|
1892
|
-
// opts,
|
|
1893
|
-
}) {
|
|
1894
|
-
throw new Error("Method not implemented.");
|
|
1895
|
-
}
|
|
1896
2894
|
async persistWorkflowSnapshot({
|
|
1897
2895
|
workflowName,
|
|
1898
2896
|
runId,
|
|
2897
|
+
resourceId,
|
|
1899
2898
|
snapshot
|
|
1900
2899
|
}) {
|
|
1901
2900
|
const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
|
|
@@ -1904,6 +2903,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1904
2903
|
const request = this.pool.request();
|
|
1905
2904
|
request.input("workflow_name", workflowName);
|
|
1906
2905
|
request.input("run_id", runId);
|
|
2906
|
+
request.input("resourceId", resourceId);
|
|
1907
2907
|
request.input("snapshot", JSON.stringify(snapshot));
|
|
1908
2908
|
request.input("createdAt", sql2__default.default.DateTime2, new Date(now));
|
|
1909
2909
|
request.input("updatedAt", sql2__default.default.DateTime2, new Date(now));
|
|
@@ -1911,10 +2911,11 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1911
2911
|
USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
|
|
1912
2912
|
ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
|
|
1913
2913
|
WHEN MATCHED THEN UPDATE SET
|
|
2914
|
+
resourceId = @resourceId,
|
|
1914
2915
|
snapshot = @snapshot,
|
|
1915
2916
|
[updatedAt] = @updatedAt
|
|
1916
|
-
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
|
|
1917
|
-
VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`;
|
|
2917
|
+
WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, resourceId, snapshot, [createdAt], [updatedAt])
|
|
2918
|
+
VALUES (@workflow_name, @run_id, @resourceId, @snapshot, @createdAt, @updatedAt);`;
|
|
1918
2919
|
await request.query(mergeSql);
|
|
1919
2920
|
} catch (error$1) {
|
|
1920
2921
|
throw new error.MastraError(
|
|
@@ -1986,7 +2987,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
1986
2987
|
if (!result.recordset || result.recordset.length === 0) {
|
|
1987
2988
|
return null;
|
|
1988
2989
|
}
|
|
1989
|
-
return parseWorkflowRun(result.recordset[0]);
|
|
2990
|
+
return this.parseWorkflowRun(result.recordset[0]);
|
|
1990
2991
|
} catch (error$1) {
|
|
1991
2992
|
throw new error.MastraError(
|
|
1992
2993
|
{
|
|
@@ -2002,7 +3003,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
2002
3003
|
);
|
|
2003
3004
|
}
|
|
2004
3005
|
}
|
|
2005
|
-
async
|
|
3006
|
+
async listWorkflowRuns({
|
|
2006
3007
|
workflowName,
|
|
2007
3008
|
fromDate,
|
|
2008
3009
|
toDate,
|
|
@@ -2023,7 +3024,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
2023
3024
|
conditions.push(`[resourceId] = @resourceId`);
|
|
2024
3025
|
paramMap["resourceId"] = resourceId;
|
|
2025
3026
|
} else {
|
|
2026
|
-
|
|
3027
|
+
this.logger?.warn?.(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
2027
3028
|
}
|
|
2028
3029
|
}
|
|
2029
3030
|
if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
|
|
@@ -2057,7 +3058,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
2057
3058
|
request.input("offset", offset);
|
|
2058
3059
|
}
|
|
2059
3060
|
const result = await request.query(query);
|
|
2060
|
-
const runs = (result.recordset || []).map((row) => parseWorkflowRun(row));
|
|
3061
|
+
const runs = (result.recordset || []).map((row) => this.parseWorkflowRun(row));
|
|
2061
3062
|
return { runs, total: total || runs.length };
|
|
2062
3063
|
} catch (error$1) {
|
|
2063
3064
|
throw new error.MastraError(
|
|
@@ -2105,19 +3106,17 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2105
3106
|
port: config.port,
|
|
2106
3107
|
options: config.options || { encrypt: true, trustServerCertificate: true }
|
|
2107
3108
|
});
|
|
2108
|
-
const legacyEvals = new LegacyEvalsMSSQL({ pool: this.pool, schema: this.schema });
|
|
2109
3109
|
const operations = new StoreOperationsMSSQL({ pool: this.pool, schemaName: this.schema });
|
|
2110
3110
|
const scores = new ScoresMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2111
|
-
const traces = new TracesMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2112
3111
|
const workflows = new WorkflowsMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2113
3112
|
const memory = new MemoryMSSQL({ pool: this.pool, schema: this.schema, operations });
|
|
3113
|
+
const observability = new ObservabilityMSSQL({ pool: this.pool, operations, schema: this.schema });
|
|
2114
3114
|
this.stores = {
|
|
2115
3115
|
operations,
|
|
2116
3116
|
scores,
|
|
2117
|
-
traces,
|
|
2118
3117
|
workflows,
|
|
2119
|
-
|
|
2120
|
-
|
|
3118
|
+
memory,
|
|
3119
|
+
observability
|
|
2121
3120
|
};
|
|
2122
3121
|
} catch (e) {
|
|
2123
3122
|
throw new error.MastraError(
|
|
@@ -2137,6 +3136,11 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2137
3136
|
try {
|
|
2138
3137
|
await this.isConnected;
|
|
2139
3138
|
await super.init();
|
|
3139
|
+
try {
|
|
3140
|
+
await this.stores.operations.createAutomaticIndexes();
|
|
3141
|
+
} catch (indexError) {
|
|
3142
|
+
this.logger?.warn?.("Failed to create indexes:", indexError);
|
|
3143
|
+
}
|
|
2140
3144
|
} catch (error$1) {
|
|
2141
3145
|
this.isConnected = null;
|
|
2142
3146
|
throw new error.MastraError(
|
|
@@ -2163,28 +3167,12 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2163
3167
|
resourceWorkingMemory: true,
|
|
2164
3168
|
hasColumn: true,
|
|
2165
3169
|
createTable: true,
|
|
2166
|
-
deleteMessages: true
|
|
3170
|
+
deleteMessages: true,
|
|
3171
|
+
getScoresBySpan: true,
|
|
3172
|
+
aiTracing: true,
|
|
3173
|
+
indexManagement: true
|
|
2167
3174
|
};
|
|
2168
3175
|
}
|
|
2169
|
-
/** @deprecated use getEvals instead */
|
|
2170
|
-
async getEvalsByAgentName(agentName, type) {
|
|
2171
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2172
|
-
}
|
|
2173
|
-
async getEvals(options = {}) {
|
|
2174
|
-
return this.stores.legacyEvals.getEvals(options);
|
|
2175
|
-
}
|
|
2176
|
-
/**
|
|
2177
|
-
* @deprecated use getTracesPaginated instead
|
|
2178
|
-
*/
|
|
2179
|
-
async getTraces(args) {
|
|
2180
|
-
return this.stores.traces.getTraces(args);
|
|
2181
|
-
}
|
|
2182
|
-
async getTracesPaginated(args) {
|
|
2183
|
-
return this.stores.traces.getTracesPaginated(args);
|
|
2184
|
-
}
|
|
2185
|
-
async batchTraceInsert({ records }) {
|
|
2186
|
-
return this.stores.traces.batchTraceInsert({ records });
|
|
2187
|
-
}
|
|
2188
3176
|
async createTable({
|
|
2189
3177
|
tableName,
|
|
2190
3178
|
schema
|
|
@@ -2244,12 +3232,6 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2244
3232
|
async getMessages(args) {
|
|
2245
3233
|
return this.stores.memory.getMessages(args);
|
|
2246
3234
|
}
|
|
2247
|
-
async getMessagesById({
|
|
2248
|
-
messageIds,
|
|
2249
|
-
format
|
|
2250
|
-
}) {
|
|
2251
|
-
return this.stores.memory.getMessagesById({ messageIds, format });
|
|
2252
|
-
}
|
|
2253
3235
|
async getMessagesPaginated(args) {
|
|
2254
3236
|
return this.stores.memory.getMessagesPaginated(args);
|
|
2255
3237
|
}
|
|
@@ -2285,9 +3267,9 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2285
3267
|
runId,
|
|
2286
3268
|
stepId,
|
|
2287
3269
|
result,
|
|
2288
|
-
|
|
3270
|
+
requestContext
|
|
2289
3271
|
}) {
|
|
2290
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result,
|
|
3272
|
+
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
2291
3273
|
}
|
|
2292
3274
|
async updateWorkflowState({
|
|
2293
3275
|
workflowName,
|
|
@@ -2299,9 +3281,10 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2299
3281
|
async persistWorkflowSnapshot({
|
|
2300
3282
|
workflowName,
|
|
2301
3283
|
runId,
|
|
3284
|
+
resourceId,
|
|
2302
3285
|
snapshot
|
|
2303
3286
|
}) {
|
|
2304
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
3287
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
2305
3288
|
}
|
|
2306
3289
|
async loadWorkflowSnapshot({
|
|
2307
3290
|
workflowName,
|
|
@@ -2309,7 +3292,7 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2309
3292
|
}) {
|
|
2310
3293
|
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
2311
3294
|
}
|
|
2312
|
-
async
|
|
3295
|
+
async listWorkflowRuns({
|
|
2313
3296
|
workflowName,
|
|
2314
3297
|
fromDate,
|
|
2315
3298
|
toDate,
|
|
@@ -2317,7 +3300,7 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2317
3300
|
offset,
|
|
2318
3301
|
resourceId
|
|
2319
3302
|
} = {}) {
|
|
2320
|
-
return this.stores.workflows.
|
|
3303
|
+
return this.stores.workflows.listWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
|
|
2321
3304
|
}
|
|
2322
3305
|
async getWorkflowRunById({
|
|
2323
3306
|
runId,
|
|
@@ -2328,6 +3311,60 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2328
3311
|
async close() {
|
|
2329
3312
|
await this.pool.close();
|
|
2330
3313
|
}
|
|
3314
|
+
/**
|
|
3315
|
+
* Index Management
|
|
3316
|
+
*/
|
|
3317
|
+
async createIndex(options) {
|
|
3318
|
+
return this.stores.operations.createIndex(options);
|
|
3319
|
+
}
|
|
3320
|
+
async listIndexes(tableName) {
|
|
3321
|
+
return this.stores.operations.listIndexes(tableName);
|
|
3322
|
+
}
|
|
3323
|
+
async describeIndex(indexName) {
|
|
3324
|
+
return this.stores.operations.describeIndex(indexName);
|
|
3325
|
+
}
|
|
3326
|
+
async dropIndex(indexName) {
|
|
3327
|
+
return this.stores.operations.dropIndex(indexName);
|
|
3328
|
+
}
|
|
3329
|
+
/**
|
|
3330
|
+
* AI Tracing / Observability
|
|
3331
|
+
*/
|
|
3332
|
+
getObservabilityStore() {
|
|
3333
|
+
if (!this.stores.observability) {
|
|
3334
|
+
throw new error.MastraError({
|
|
3335
|
+
id: "MSSQL_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
3336
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3337
|
+
category: error.ErrorCategory.SYSTEM,
|
|
3338
|
+
text: "Observability storage is not initialized"
|
|
3339
|
+
});
|
|
3340
|
+
}
|
|
3341
|
+
return this.stores.observability;
|
|
3342
|
+
}
|
|
3343
|
+
async createAISpan(span) {
|
|
3344
|
+
return this.getObservabilityStore().createAISpan(span);
|
|
3345
|
+
}
|
|
3346
|
+
async updateAISpan({
|
|
3347
|
+
spanId,
|
|
3348
|
+
traceId,
|
|
3349
|
+
updates
|
|
3350
|
+
}) {
|
|
3351
|
+
return this.getObservabilityStore().updateAISpan({ spanId, traceId, updates });
|
|
3352
|
+
}
|
|
3353
|
+
async getAITrace(traceId) {
|
|
3354
|
+
return this.getObservabilityStore().getAITrace(traceId);
|
|
3355
|
+
}
|
|
3356
|
+
async getAITracesPaginated(args) {
|
|
3357
|
+
return this.getObservabilityStore().getAITracesPaginated(args);
|
|
3358
|
+
}
|
|
3359
|
+
async batchCreateAISpans(args) {
|
|
3360
|
+
return this.getObservabilityStore().batchCreateAISpans(args);
|
|
3361
|
+
}
|
|
3362
|
+
async batchUpdateAISpans(args) {
|
|
3363
|
+
return this.getObservabilityStore().batchUpdateAISpans(args);
|
|
3364
|
+
}
|
|
3365
|
+
async batchDeleteAITraces(args) {
|
|
3366
|
+
return this.getObservabilityStore().batchDeleteAITraces(args);
|
|
3367
|
+
}
|
|
2331
3368
|
/**
|
|
2332
3369
|
* Scorers
|
|
2333
3370
|
*/
|
|
@@ -2336,9 +3373,18 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2336
3373
|
}
|
|
2337
3374
|
async getScoresByScorerId({
|
|
2338
3375
|
scorerId: _scorerId,
|
|
2339
|
-
pagination: _pagination
|
|
3376
|
+
pagination: _pagination,
|
|
3377
|
+
entityId: _entityId,
|
|
3378
|
+
entityType: _entityType,
|
|
3379
|
+
source: _source
|
|
2340
3380
|
}) {
|
|
2341
|
-
return this.stores.scores.getScoresByScorerId({
|
|
3381
|
+
return this.stores.scores.getScoresByScorerId({
|
|
3382
|
+
scorerId: _scorerId,
|
|
3383
|
+
pagination: _pagination,
|
|
3384
|
+
entityId: _entityId,
|
|
3385
|
+
entityType: _entityType,
|
|
3386
|
+
source: _source
|
|
3387
|
+
});
|
|
2342
3388
|
}
|
|
2343
3389
|
async saveScore(_score) {
|
|
2344
3390
|
return this.stores.scores.saveScore(_score);
|
|
@@ -2360,6 +3406,13 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
2360
3406
|
pagination: _pagination
|
|
2361
3407
|
});
|
|
2362
3408
|
}
|
|
3409
|
+
async getScoresBySpan({
|
|
3410
|
+
traceId,
|
|
3411
|
+
spanId,
|
|
3412
|
+
pagination: _pagination
|
|
3413
|
+
}) {
|
|
3414
|
+
return this.stores.scores.getScoresBySpan({ traceId, spanId, pagination: _pagination });
|
|
3415
|
+
}
|
|
2363
3416
|
};
|
|
2364
3417
|
|
|
2365
3418
|
exports.MSSQLStore = MSSQLStore;
|