@mastra/mssql 0.0.0-roamin-openaivoice-speak-options-passing-20250926163614 → 0.0.0-safe-stringify-telemetry-20251205024938

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,13 +2,15 @@
2
2
 
3
3
  var error = require('@mastra/core/error');
4
4
  var storage = require('@mastra/core/storage');
5
- var sql2 = require('mssql');
5
+ var sql3 = require('mssql');
6
6
  var utils = require('@mastra/core/utils');
7
7
  var agent = require('@mastra/core/agent');
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
 
11
- var sql2__default = /*#__PURE__*/_interopDefault(sql2);
13
+ var sql3__default = /*#__PURE__*/_interopDefault(sql3);
12
14
 
13
15
  // src/storage/index.ts
14
16
  function getSchemaName(schema) {
@@ -20,6 +22,69 @@ function getTableName({ indexName, schemaName }) {
20
22
  const quotedSchemaName = schemaName;
21
23
  return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
22
24
  }
25
+ function buildDateRangeFilter(dateRange, fieldName) {
26
+ const filters = {};
27
+ if (dateRange?.start) {
28
+ filters[`${fieldName}_gte`] = dateRange.start;
29
+ }
30
+ if (dateRange?.end) {
31
+ filters[`${fieldName}_lte`] = dateRange.end;
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
+ });
57
+ return {
58
+ sql: conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "",
59
+ params
60
+ };
61
+ }
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;
75
+ }
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;
84
+ }
85
+ });
86
+ return result;
87
+ }
23
88
 
24
89
  // src/storage/domains/legacy-evals/index.ts
25
90
  function transformEvalRow(row) {
@@ -30,7 +95,7 @@ function transformEvalRow(row) {
30
95
  } catch {
31
96
  }
32
97
  }
33
- if (row.test_info) {
98
+ if (row.result) {
34
99
  try {
35
100
  resultValue = typeof row.result === "string" ? JSON.parse(row.result) : row.result;
36
101
  } catch {
@@ -76,7 +141,7 @@ var LegacyEvalsMSSQL = class extends storage.LegacyEvalsStorage {
76
141
  if (error && error.number === 208 && error.message && error.message.includes("Invalid object name")) {
77
142
  return [];
78
143
  }
79
- console.error("Failed to get evals for the specified agent: " + error?.message);
144
+ this.logger?.error?.("Failed to get evals for the specified agent:", error);
80
145
  throw error;
81
146
  }
82
147
  }
@@ -112,7 +177,7 @@ var LegacyEvalsMSSQL = class extends storage.LegacyEvalsStorage {
112
177
  const countReq = this.pool.request();
113
178
  Object.entries(params).forEach(([key, value]) => {
114
179
  if (value instanceof Date) {
115
- countReq.input(key, sql2__default.default.DateTime, value);
180
+ countReq.input(key, sql3__default.default.DateTime, value);
116
181
  } else {
117
182
  countReq.input(key, value);
118
183
  }
@@ -131,7 +196,7 @@ var LegacyEvalsMSSQL = class extends storage.LegacyEvalsStorage {
131
196
  const req = this.pool.request();
132
197
  Object.entries(params).forEach(([key, value]) => {
133
198
  if (value instanceof Date) {
134
- req.input(key, sql2__default.default.DateTime, value);
199
+ req.input(key, sql3__default.default.DateTime, value);
135
200
  } else {
136
201
  req.input(key, value);
137
202
  }
@@ -163,7 +228,7 @@ var LegacyEvalsMSSQL = class extends storage.LegacyEvalsStorage {
163
228
  error$1
164
229
  );
165
230
  this.logger?.error?.(mastraError.toString());
166
- this.logger?.trackException(mastraError);
231
+ this.logger?.trackException?.(mastraError);
167
232
  throw mastraError;
168
233
  }
169
234
  }
@@ -256,7 +321,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
256
321
  };
257
322
  }
258
323
  const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
259
- const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${sortDirection} OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
324
+ const dir = (sortDirection || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
325
+ const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir} OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
260
326
  const dataRequest = this.pool.request();
261
327
  dataRequest.input("resourceId", resourceId);
262
328
  dataRequest.input("perPage", perPage);
@@ -313,9 +379,14 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
313
379
  req.input("id", thread.id);
314
380
  req.input("resourceId", thread.resourceId);
315
381
  req.input("title", thread.title);
316
- req.input("metadata", thread.metadata ? JSON.stringify(thread.metadata) : null);
317
- req.input("createdAt", sql2__default.default.DateTime2, thread.createdAt);
318
- req.input("updatedAt", sql2__default.default.DateTime2, thread.updatedAt);
382
+ const metadata = thread.metadata ? JSON.stringify(thread.metadata) : null;
383
+ if (metadata === null) {
384
+ req.input("metadata", sql3__default.default.NVarChar, null);
385
+ } else {
386
+ req.input("metadata", metadata);
387
+ }
388
+ req.input("createdAt", sql3__default.default.DateTime2, thread.createdAt);
389
+ req.input("updatedAt", sql3__default.default.DateTime2, thread.updatedAt);
319
390
  await req.query(mergeSql);
320
391
  return thread;
321
392
  } catch (error$1) {
@@ -340,7 +411,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
340
411
  try {
341
412
  const baseQuery = `FROM ${getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) })} WHERE [resourceId] = @resourceId`;
342
413
  const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
343
- const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${sortDirection}`;
414
+ const dir = (sortDirection || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
415
+ const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir}`;
344
416
  const request = this.pool.request();
345
417
  request.input("resourceId", resourceId);
346
418
  const resultSet = await request.query(dataQuery);
@@ -589,7 +661,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
589
661
  error$1
590
662
  );
591
663
  this.logger?.error?.(mastraError.toString());
592
- this.logger?.trackException(mastraError);
664
+ this.logger?.trackException?.(mastraError);
593
665
  return [];
594
666
  }
595
667
  }
@@ -629,7 +701,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
629
701
  error$1
630
702
  );
631
703
  this.logger?.error?.(mastraError.toString());
632
- this.logger?.trackException(mastraError);
704
+ this.logger?.trackException?.(mastraError);
633
705
  return [];
634
706
  }
635
707
  }
@@ -688,10 +760,11 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
688
760
  const rows = rowsResult.recordset || [];
689
761
  rows.sort((a, b) => a.seq_id - b.seq_id);
690
762
  messages.push(...rows);
691
- const parsed = this._parseAndFormatMessages(messages, format);
763
+ let parsed = this._parseAndFormatMessages(messages, format);
764
+ parsed = parsed.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
692
765
  return {
693
766
  messages: parsed,
694
- total: total + excludeIds.length,
767
+ total,
695
768
  page,
696
769
  perPage,
697
770
  hasMore: currentOffset + rows.length < total
@@ -711,7 +784,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
711
784
  error$1
712
785
  );
713
786
  this.logger?.error?.(mastraError.toString());
714
- this.logger?.trackException(mastraError);
787
+ this.logger?.trackException?.(mastraError);
715
788
  return { messages: [], total: 0, page, perPage: perPageInput || 40, hasMore: false };
716
789
  }
717
790
  }
@@ -763,7 +836,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
763
836
  "content",
764
837
  typeof message.content === "string" ? message.content : JSON.stringify(message.content)
765
838
  );
766
- request.input("createdAt", sql2__default.default.DateTime2, message.createdAt);
839
+ request.input("createdAt", sql3__default.default.DateTime2, message.createdAt);
767
840
  request.input("role", message.role);
768
841
  request.input("type", message.type || "v2");
769
842
  request.input("resourceId", message.resourceId);
@@ -782,7 +855,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
782
855
  await request.query(mergeSql);
783
856
  }
784
857
  const threadReq = transaction.request();
785
- threadReq.input("updatedAt", sql2__default.default.DateTime2, /* @__PURE__ */ new Date());
858
+ threadReq.input("updatedAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
786
859
  threadReq.input("id", threadId);
787
860
  await threadReq.query(`UPDATE ${tableThreads} SET [updatedAt] = @updatedAt WHERE id = @id`);
788
861
  await transaction.commit();
@@ -978,8 +1051,10 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
978
1051
  return null;
979
1052
  }
980
1053
  return {
981
- ...result,
982
- workingMemory: typeof result.workingMemory === "object" ? JSON.stringify(result.workingMemory) : result.workingMemory,
1054
+ id: result.id,
1055
+ createdAt: result.createdAt,
1056
+ updatedAt: result.updatedAt,
1057
+ workingMemory: result.workingMemory,
983
1058
  metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
984
1059
  };
985
1060
  } catch (error$1) {
@@ -993,7 +1068,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
993
1068
  error$1
994
1069
  );
995
1070
  this.logger?.error?.(mastraError.toString());
996
- this.logger?.trackException(mastraError);
1071
+ this.logger?.trackException?.(mastraError);
997
1072
  throw mastraError;
998
1073
  }
999
1074
  }
@@ -1002,7 +1077,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
1002
1077
  tableName: storage.TABLE_RESOURCES,
1003
1078
  record: {
1004
1079
  ...resource,
1005
- metadata: JSON.stringify(resource.metadata)
1080
+ metadata: resource.metadata
1006
1081
  }
1007
1082
  });
1008
1083
  return resource;
@@ -1060,20 +1135,337 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
1060
1135
  error$1
1061
1136
  );
1062
1137
  this.logger?.error?.(mastraError.toString());
1063
- this.logger?.trackException(mastraError);
1138
+ this.logger?.trackException?.(mastraError);
1064
1139
  throw mastraError;
1065
1140
  }
1066
1141
  }
1067
1142
  };
1143
+ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
1144
+ pool;
1145
+ operations;
1146
+ schema;
1147
+ constructor({
1148
+ pool,
1149
+ operations,
1150
+ schema
1151
+ }) {
1152
+ super();
1153
+ this.pool = pool;
1154
+ this.operations = operations;
1155
+ this.schema = schema;
1156
+ }
1157
+ get aiTracingStrategy() {
1158
+ return {
1159
+ preferred: "batch-with-updates",
1160
+ supported: ["batch-with-updates", "insert-only"]
1161
+ };
1162
+ }
1163
+ async createAISpan(span) {
1164
+ try {
1165
+ const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
1166
+ const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
1167
+ const record = {
1168
+ ...span,
1169
+ startedAt,
1170
+ endedAt
1171
+ // Note: createdAt/updatedAt will be set by default values
1172
+ };
1173
+ return this.operations.insert({ tableName: storage.TABLE_AI_SPANS, record });
1174
+ } catch (error$1) {
1175
+ throw new error.MastraError(
1176
+ {
1177
+ id: "MSSQL_STORE_CREATE_AI_SPAN_FAILED",
1178
+ domain: error.ErrorDomain.STORAGE,
1179
+ category: error.ErrorCategory.USER,
1180
+ details: {
1181
+ spanId: span.spanId,
1182
+ traceId: span.traceId,
1183
+ spanType: span.spanType,
1184
+ spanName: span.name
1185
+ }
1186
+ },
1187
+ error$1
1188
+ );
1189
+ }
1190
+ }
1191
+ async getAITrace(traceId) {
1192
+ try {
1193
+ const tableName = getTableName({
1194
+ indexName: storage.TABLE_AI_SPANS,
1195
+ schemaName: getSchemaName(this.schema)
1196
+ });
1197
+ const request = this.pool.request();
1198
+ request.input("traceId", traceId);
1199
+ const result = await request.query(
1200
+ `SELECT
1201
+ [traceId], [spanId], [parentSpanId], [name], [scope], [spanType],
1202
+ [attributes], [metadata], [links], [input], [output], [error], [isEvent],
1203
+ [startedAt], [endedAt], [createdAt], [updatedAt]
1204
+ FROM ${tableName}
1205
+ WHERE [traceId] = @traceId
1206
+ ORDER BY [startedAt] DESC`
1207
+ );
1208
+ if (!result.recordset || result.recordset.length === 0) {
1209
+ return null;
1210
+ }
1211
+ return {
1212
+ traceId,
1213
+ spans: result.recordset.map(
1214
+ (span) => transformFromSqlRow({
1215
+ tableName: storage.TABLE_AI_SPANS,
1216
+ sqlRow: span
1217
+ })
1218
+ )
1219
+ };
1220
+ } catch (error$1) {
1221
+ throw new error.MastraError(
1222
+ {
1223
+ id: "MSSQL_STORE_GET_AI_TRACE_FAILED",
1224
+ domain: error.ErrorDomain.STORAGE,
1225
+ category: error.ErrorCategory.USER,
1226
+ details: {
1227
+ traceId
1228
+ }
1229
+ },
1230
+ error$1
1231
+ );
1232
+ }
1233
+ }
1234
+ async updateAISpan({
1235
+ spanId,
1236
+ traceId,
1237
+ updates
1238
+ }) {
1239
+ try {
1240
+ const data = { ...updates };
1241
+ if (data.endedAt instanceof Date) {
1242
+ data.endedAt = data.endedAt.toISOString();
1243
+ }
1244
+ if (data.startedAt instanceof Date) {
1245
+ data.startedAt = data.startedAt.toISOString();
1246
+ }
1247
+ await this.operations.update({
1248
+ tableName: storage.TABLE_AI_SPANS,
1249
+ keys: { spanId, traceId },
1250
+ data
1251
+ });
1252
+ } catch (error$1) {
1253
+ throw new error.MastraError(
1254
+ {
1255
+ id: "MSSQL_STORE_UPDATE_AI_SPAN_FAILED",
1256
+ domain: error.ErrorDomain.STORAGE,
1257
+ category: error.ErrorCategory.USER,
1258
+ details: {
1259
+ spanId,
1260
+ traceId
1261
+ }
1262
+ },
1263
+ error$1
1264
+ );
1265
+ }
1266
+ }
1267
+ async getAITracesPaginated({
1268
+ filters,
1269
+ pagination
1270
+ }) {
1271
+ const page = pagination?.page ?? 0;
1272
+ const perPage = pagination?.perPage ?? 10;
1273
+ const { entityId, entityType, ...actualFilters } = filters || {};
1274
+ const filtersWithDateRange = {
1275
+ ...actualFilters,
1276
+ ...buildDateRangeFilter(pagination?.dateRange, "startedAt"),
1277
+ parentSpanId: null
1278
+ // Only get root spans for traces
1279
+ };
1280
+ const whereClause = prepareWhereClause(filtersWithDateRange);
1281
+ let actualWhereClause = whereClause.sql;
1282
+ const params = { ...whereClause.params };
1283
+ let currentParamIndex = Object.keys(params).length + 1;
1284
+ if (entityId && entityType) {
1285
+ let name = "";
1286
+ if (entityType === "workflow") {
1287
+ name = `workflow run: '${entityId}'`;
1288
+ } else if (entityType === "agent") {
1289
+ name = `agent run: '${entityId}'`;
1290
+ } else {
1291
+ const error$1 = new error.MastraError({
1292
+ id: "MSSQL_STORE_GET_AI_TRACES_PAGINATED_FAILED",
1293
+ domain: error.ErrorDomain.STORAGE,
1294
+ category: error.ErrorCategory.USER,
1295
+ details: {
1296
+ entityType
1297
+ },
1298
+ text: `Cannot filter by entity type: ${entityType}`
1299
+ });
1300
+ throw error$1;
1301
+ }
1302
+ const entityParam = `p${currentParamIndex++}`;
1303
+ if (actualWhereClause) {
1304
+ actualWhereClause += ` AND [name] = @${entityParam}`;
1305
+ } else {
1306
+ actualWhereClause = ` WHERE [name] = @${entityParam}`;
1307
+ }
1308
+ params[entityParam] = name;
1309
+ }
1310
+ const tableName = getTableName({
1311
+ indexName: storage.TABLE_AI_SPANS,
1312
+ schemaName: getSchemaName(this.schema)
1313
+ });
1314
+ try {
1315
+ const countRequest = this.pool.request();
1316
+ Object.entries(params).forEach(([key, value]) => {
1317
+ countRequest.input(key, value);
1318
+ });
1319
+ const countResult = await countRequest.query(
1320
+ `SELECT COUNT(*) as count FROM ${tableName}${actualWhereClause}`
1321
+ );
1322
+ const total = countResult.recordset[0]?.count ?? 0;
1323
+ if (total === 0) {
1324
+ return {
1325
+ pagination: {
1326
+ total: 0,
1327
+ page,
1328
+ perPage,
1329
+ hasMore: false
1330
+ },
1331
+ spans: []
1332
+ };
1333
+ }
1334
+ const dataRequest = this.pool.request();
1335
+ Object.entries(params).forEach(([key, value]) => {
1336
+ dataRequest.input(key, value);
1337
+ });
1338
+ dataRequest.input("offset", page * perPage);
1339
+ dataRequest.input("limit", perPage);
1340
+ const dataResult = await dataRequest.query(
1341
+ `SELECT * FROM ${tableName}${actualWhereClause} ORDER BY [startedAt] DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
1342
+ );
1343
+ const spans = dataResult.recordset.map(
1344
+ (row) => transformFromSqlRow({
1345
+ tableName: storage.TABLE_AI_SPANS,
1346
+ sqlRow: row
1347
+ })
1348
+ );
1349
+ return {
1350
+ pagination: {
1351
+ total,
1352
+ page,
1353
+ perPage,
1354
+ hasMore: (page + 1) * perPage < total
1355
+ },
1356
+ spans
1357
+ };
1358
+ } catch (error$1) {
1359
+ throw new error.MastraError(
1360
+ {
1361
+ id: "MSSQL_STORE_GET_AI_TRACES_PAGINATED_FAILED",
1362
+ domain: error.ErrorDomain.STORAGE,
1363
+ category: error.ErrorCategory.USER
1364
+ },
1365
+ error$1
1366
+ );
1367
+ }
1368
+ }
1369
+ async batchCreateAISpans(args) {
1370
+ if (!args.records || args.records.length === 0) {
1371
+ return;
1372
+ }
1373
+ try {
1374
+ await this.operations.batchInsert({
1375
+ tableName: storage.TABLE_AI_SPANS,
1376
+ records: args.records.map((span) => ({
1377
+ ...span,
1378
+ startedAt: span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt,
1379
+ endedAt: span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt
1380
+ }))
1381
+ });
1382
+ } catch (error$1) {
1383
+ throw new error.MastraError(
1384
+ {
1385
+ id: "MSSQL_STORE_BATCH_CREATE_AI_SPANS_FAILED",
1386
+ domain: error.ErrorDomain.STORAGE,
1387
+ category: error.ErrorCategory.USER,
1388
+ details: {
1389
+ count: args.records.length
1390
+ }
1391
+ },
1392
+ error$1
1393
+ );
1394
+ }
1395
+ }
1396
+ async batchUpdateAISpans(args) {
1397
+ if (!args.records || args.records.length === 0) {
1398
+ return;
1399
+ }
1400
+ try {
1401
+ const updates = args.records.map(({ traceId, spanId, updates: data }) => {
1402
+ const processedData = { ...data };
1403
+ if (processedData.endedAt instanceof Date) {
1404
+ processedData.endedAt = processedData.endedAt.toISOString();
1405
+ }
1406
+ if (processedData.startedAt instanceof Date) {
1407
+ processedData.startedAt = processedData.startedAt.toISOString();
1408
+ }
1409
+ return {
1410
+ keys: { spanId, traceId },
1411
+ data: processedData
1412
+ };
1413
+ });
1414
+ await this.operations.batchUpdate({
1415
+ tableName: storage.TABLE_AI_SPANS,
1416
+ updates
1417
+ });
1418
+ } catch (error$1) {
1419
+ throw new error.MastraError(
1420
+ {
1421
+ id: "MSSQL_STORE_BATCH_UPDATE_AI_SPANS_FAILED",
1422
+ domain: error.ErrorDomain.STORAGE,
1423
+ category: error.ErrorCategory.USER,
1424
+ details: {
1425
+ count: args.records.length
1426
+ }
1427
+ },
1428
+ error$1
1429
+ );
1430
+ }
1431
+ }
1432
+ async batchDeleteAITraces(args) {
1433
+ if (!args.traceIds || args.traceIds.length === 0) {
1434
+ return;
1435
+ }
1436
+ try {
1437
+ const keys = args.traceIds.map((traceId) => ({ traceId }));
1438
+ await this.operations.batchDelete({
1439
+ tableName: storage.TABLE_AI_SPANS,
1440
+ keys
1441
+ });
1442
+ } catch (error$1) {
1443
+ throw new error.MastraError(
1444
+ {
1445
+ id: "MSSQL_STORE_BATCH_DELETE_AI_TRACES_FAILED",
1446
+ domain: error.ErrorDomain.STORAGE,
1447
+ category: error.ErrorCategory.USER,
1448
+ details: {
1449
+ count: args.traceIds.length
1450
+ }
1451
+ },
1452
+ error$1
1453
+ );
1454
+ }
1455
+ }
1456
+ };
1068
1457
  var StoreOperationsMSSQL = class extends storage.StoreOperations {
1069
1458
  pool;
1070
1459
  schemaName;
1071
1460
  setupSchemaPromise = null;
1072
1461
  schemaSetupComplete = void 0;
1073
- getSqlType(type, isPrimaryKey = false) {
1462
+ getSqlType(type, isPrimaryKey = false, useLargeStorage = false) {
1074
1463
  switch (type) {
1075
1464
  case "text":
1076
- return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(MAX)";
1465
+ if (useLargeStorage) {
1466
+ return "NVARCHAR(MAX)";
1467
+ }
1468
+ return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(400)";
1077
1469
  case "timestamp":
1078
1470
  return "DATETIME2(7)";
1079
1471
  case "uuid":
@@ -1086,6 +1478,8 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1086
1478
  return "BIGINT";
1087
1479
  case "float":
1088
1480
  return "FLOAT";
1481
+ case "boolean":
1482
+ return "BIT";
1089
1483
  default:
1090
1484
  throw new error.MastraError({
1091
1485
  id: "MASTRA_STORAGE_MSSQL_STORE_TYPE_NOT_SUPPORTED",
@@ -1148,20 +1542,26 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1148
1542
  }
1149
1543
  await this.setupSchemaPromise;
1150
1544
  }
1151
- async insert({ tableName, record }) {
1545
+ async insert({
1546
+ tableName,
1547
+ record,
1548
+ transaction
1549
+ }) {
1152
1550
  try {
1153
- const columns = Object.keys(record).map((col) => utils.parseSqlIdentifier(col, "column name"));
1154
- const values = Object.values(record);
1155
- const paramNames = values.map((_, i) => `@param${i}`);
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));
1551
+ const columns = Object.keys(record);
1552
+ const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
1553
+ const paramNames = columns.map((_, i) => `@param${i}`);
1554
+ const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${parsedColumns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
1555
+ const request = transaction ? transaction.request() : this.pool.request();
1556
+ columns.forEach((col, i) => {
1557
+ const value = record[col];
1558
+ const preparedValue = this.prepareValue(value, col, tableName);
1559
+ if (preparedValue instanceof Date) {
1560
+ request.input(`param${i}`, sql3__default.default.DateTime2, preparedValue);
1561
+ } else if (preparedValue === null || preparedValue === void 0) {
1562
+ request.input(`param${i}`, this.getMssqlType(tableName, col), null);
1163
1563
  } else {
1164
- request.input(`param${i}`, value);
1564
+ request.input(`param${i}`, preparedValue);
1165
1565
  }
1166
1566
  });
1167
1567
  await request.query(insertSql);
@@ -1185,7 +1585,7 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1185
1585
  try {
1186
1586
  await this.pool.request().query(`TRUNCATE TABLE ${fullTableName}`);
1187
1587
  } catch (truncateError) {
1188
- if (truncateError.message && truncateError.message.includes("foreign key")) {
1588
+ if (truncateError?.number === 4712) {
1189
1589
  await this.pool.request().query(`DELETE FROM ${fullTableName}`);
1190
1590
  } else {
1191
1591
  throw truncateError;
@@ -1208,9 +1608,11 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1208
1608
  getDefaultValue(type) {
1209
1609
  switch (type) {
1210
1610
  case "timestamp":
1211
- return "DEFAULT SYSDATETIMEOFFSET()";
1611
+ return "DEFAULT SYSUTCDATETIME()";
1212
1612
  case "jsonb":
1213
1613
  return "DEFAULT N'{}'";
1614
+ case "boolean":
1615
+ return "DEFAULT 0";
1214
1616
  default:
1215
1617
  return super.getDefaultValue(type);
1216
1618
  }
@@ -1221,13 +1623,29 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1221
1623
  }) {
1222
1624
  try {
1223
1625
  const uniqueConstraintColumns = tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? ["workflow_name", "run_id"] : [];
1626
+ const largeDataColumns = [
1627
+ "workingMemory",
1628
+ "snapshot",
1629
+ "metadata",
1630
+ "content",
1631
+ // messages.content - can be very long conversation content
1632
+ "input",
1633
+ // evals.input - test input data
1634
+ "output",
1635
+ // evals.output - test output data
1636
+ "instructions",
1637
+ // evals.instructions - evaluation instructions
1638
+ "other"
1639
+ // traces.other - additional trace data
1640
+ ];
1224
1641
  const columns = Object.entries(schema).map(([name, def]) => {
1225
1642
  const parsedName = utils.parseSqlIdentifier(name, "column name");
1226
1643
  const constraints = [];
1227
1644
  if (def.primaryKey) constraints.push("PRIMARY KEY");
1228
1645
  if (!def.nullable) constraints.push("NOT NULL");
1229
1646
  const isIndexed = !!def.primaryKey || uniqueConstraintColumns.includes(name);
1230
- return `[${parsedName}] ${this.getSqlType(def.type, isIndexed)} ${constraints.join(" ")}`.trim();
1647
+ const useLargeStorage = largeDataColumns.includes(name);
1648
+ return `[${parsedName}] ${this.getSqlType(def.type, isIndexed, useLargeStorage)} ${constraints.join(" ")}`.trim();
1231
1649
  }).join(",\n");
1232
1650
  if (this.schemaName) {
1233
1651
  await this.setupSchema();
@@ -1314,7 +1732,19 @@ ${columns}
1314
1732
  const columnExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
1315
1733
  if (!columnExists) {
1316
1734
  const columnDef = schema[columnName];
1317
- const sqlType = this.getSqlType(columnDef.type);
1735
+ const largeDataColumns = [
1736
+ "workingMemory",
1737
+ "snapshot",
1738
+ "metadata",
1739
+ "content",
1740
+ "input",
1741
+ "output",
1742
+ "instructions",
1743
+ "other"
1744
+ ];
1745
+ const useLargeStorage = largeDataColumns.includes(columnName);
1746
+ const isIndexed = !!columnDef.primaryKey;
1747
+ const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage);
1318
1748
  const nullable = columnDef.nullable === false ? "NOT NULL" : "";
1319
1749
  const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
1320
1750
  const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
@@ -1342,11 +1772,15 @@ ${columns}
1342
1772
  try {
1343
1773
  const keyEntries = Object.entries(keys).map(([key, value]) => [utils.parseSqlIdentifier(key, "column name"), value]);
1344
1774
  const conditions = keyEntries.map(([key], i) => `[${key}] = @param${i}`).join(" AND ");
1345
- const values = keyEntries.map(([_, value]) => value);
1346
1775
  const sql7 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
1347
1776
  const request = this.pool.request();
1348
- values.forEach((value, i) => {
1349
- request.input(`param${i}`, value);
1777
+ keyEntries.forEach(([key, value], i) => {
1778
+ const preparedValue = this.prepareValue(value, key, tableName);
1779
+ if (preparedValue === null || preparedValue === void 0) {
1780
+ request.input(`param${i}`, this.getMssqlType(tableName, key), null);
1781
+ } else {
1782
+ request.input(`param${i}`, preparedValue);
1783
+ }
1350
1784
  });
1351
1785
  const resultSet = await request.query(sql7);
1352
1786
  const result = resultSet.recordset[0] || null;
@@ -1380,7 +1814,7 @@ ${columns}
1380
1814
  try {
1381
1815
  await transaction.begin();
1382
1816
  for (const record of records) {
1383
- await this.insert({ tableName, record });
1817
+ await this.insert({ tableName, record, transaction });
1384
1818
  }
1385
1819
  await transaction.commit();
1386
1820
  } catch (error$1) {
@@ -1417,69 +1851,637 @@ ${columns}
1417
1851
  );
1418
1852
  }
1419
1853
  }
1420
- };
1421
- function parseJSON(jsonString) {
1422
- try {
1423
- return JSON.parse(jsonString);
1424
- } catch {
1425
- return jsonString;
1426
- }
1427
- }
1428
- function transformScoreRow(row) {
1429
- return {
1430
- ...row,
1431
- input: parseJSON(row.input),
1432
- scorer: parseJSON(row.scorer),
1433
- preprocessStepResult: parseJSON(row.preprocessStepResult),
1434
- analyzeStepResult: parseJSON(row.analyzeStepResult),
1435
- metadata: parseJSON(row.metadata),
1436
- output: parseJSON(row.output),
1437
- additionalContext: parseJSON(row.additionalContext),
1438
- runtimeContext: parseJSON(row.runtimeContext),
1439
- entity: parseJSON(row.entity),
1440
- createdAt: row.createdAt,
1441
- updatedAt: row.updatedAt
1442
- };
1443
- }
1444
- var ScoresMSSQL = class extends storage.ScoresStorage {
1445
- pool;
1446
- operations;
1447
- schema;
1448
- constructor({
1449
- pool,
1450
- operations,
1451
- schema
1452
- }) {
1453
- super();
1454
- this.pool = pool;
1455
- this.operations = operations;
1456
- this.schema = schema;
1457
- }
1458
- async getScoreById({ id }) {
1459
- try {
1460
- const request = this.pool.request();
1461
- request.input("p1", id);
1462
- const result = await request.query(
1463
- `SELECT * FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE id = @p1`
1464
- );
1465
- if (result.recordset.length === 0) {
1466
- return null;
1854
+ /**
1855
+ * Prepares a value for database operations, handling Date objects and JSON serialization
1856
+ */
1857
+ prepareValue(value, columnName, tableName) {
1858
+ if (value === null || value === void 0) {
1859
+ return value;
1860
+ }
1861
+ if (value instanceof Date) {
1862
+ return value;
1863
+ }
1864
+ const schema = storage.TABLE_SCHEMAS[tableName];
1865
+ const columnSchema = schema?.[columnName];
1866
+ if (columnSchema?.type === "boolean") {
1867
+ return value ? 1 : 0;
1868
+ }
1869
+ if (columnSchema?.type === "jsonb") {
1870
+ if (typeof value === "string") {
1871
+ const trimmed = value.trim();
1872
+ if (trimmed.length > 0) {
1873
+ try {
1874
+ JSON.parse(trimmed);
1875
+ return trimmed;
1876
+ } catch {
1877
+ }
1878
+ }
1879
+ return JSON.stringify(value);
1467
1880
  }
1468
- return transformScoreRow(result.recordset[0]);
1469
- } catch (error$1) {
1470
- throw new error.MastraError(
1471
- {
1472
- id: "MASTRA_STORAGE_MSSQL_STORE_GET_SCORE_BY_ID_FAILED",
1473
- domain: error.ErrorDomain.STORAGE,
1474
- category: error.ErrorCategory.THIRD_PARTY,
1475
- details: { id }
1476
- },
1477
- error$1
1478
- );
1881
+ if (typeof value === "bigint") {
1882
+ return value.toString();
1883
+ }
1884
+ return JSON.stringify(value);
1885
+ }
1886
+ if (typeof value === "object") {
1887
+ return JSON.stringify(value);
1479
1888
  }
1889
+ return value;
1480
1890
  }
1481
- async saveScore(score) {
1482
- try {
1891
+ /**
1892
+ * Maps TABLE_SCHEMAS types to mssql param types (used when value is null)
1893
+ */
1894
+ getMssqlType(tableName, columnName) {
1895
+ const col = storage.TABLE_SCHEMAS[tableName]?.[columnName];
1896
+ switch (col?.type) {
1897
+ case "text":
1898
+ return sql3__default.default.NVarChar;
1899
+ case "timestamp":
1900
+ return sql3__default.default.DateTime2;
1901
+ case "uuid":
1902
+ return sql3__default.default.UniqueIdentifier;
1903
+ case "jsonb":
1904
+ return sql3__default.default.NVarChar;
1905
+ case "integer":
1906
+ return sql3__default.default.Int;
1907
+ case "bigint":
1908
+ return sql3__default.default.BigInt;
1909
+ case "float":
1910
+ return sql3__default.default.Float;
1911
+ case "boolean":
1912
+ return sql3__default.default.Bit;
1913
+ default:
1914
+ return sql3__default.default.NVarChar;
1915
+ }
1916
+ }
1917
+ /**
1918
+ * Update a single record in the database
1919
+ */
1920
+ async update({
1921
+ tableName,
1922
+ keys,
1923
+ data,
1924
+ transaction
1925
+ }) {
1926
+ try {
1927
+ if (!data || Object.keys(data).length === 0) {
1928
+ throw new error.MastraError({
1929
+ id: "MASTRA_STORAGE_MSSQL_UPDATE_EMPTY_DATA",
1930
+ domain: error.ErrorDomain.STORAGE,
1931
+ category: error.ErrorCategory.USER,
1932
+ text: "Cannot update with empty data payload"
1933
+ });
1934
+ }
1935
+ if (!keys || Object.keys(keys).length === 0) {
1936
+ throw new error.MastraError({
1937
+ id: "MASTRA_STORAGE_MSSQL_UPDATE_EMPTY_KEYS",
1938
+ domain: error.ErrorDomain.STORAGE,
1939
+ category: error.ErrorCategory.USER,
1940
+ text: "Cannot update without keys to identify records"
1941
+ });
1942
+ }
1943
+ const setClauses = [];
1944
+ const request = transaction ? transaction.request() : this.pool.request();
1945
+ let paramIndex = 0;
1946
+ Object.entries(data).forEach(([key, value]) => {
1947
+ const parsedKey = utils.parseSqlIdentifier(key, "column name");
1948
+ const paramName = `set${paramIndex++}`;
1949
+ setClauses.push(`[${parsedKey}] = @${paramName}`);
1950
+ const preparedValue = this.prepareValue(value, key, tableName);
1951
+ if (preparedValue === null || preparedValue === void 0) {
1952
+ request.input(paramName, this.getMssqlType(tableName, key), null);
1953
+ } else {
1954
+ request.input(paramName, preparedValue);
1955
+ }
1956
+ });
1957
+ const whereConditions = [];
1958
+ Object.entries(keys).forEach(([key, value]) => {
1959
+ const parsedKey = utils.parseSqlIdentifier(key, "column name");
1960
+ const paramName = `where${paramIndex++}`;
1961
+ whereConditions.push(`[${parsedKey}] = @${paramName}`);
1962
+ const preparedValue = this.prepareValue(value, key, tableName);
1963
+ if (preparedValue === null || preparedValue === void 0) {
1964
+ request.input(paramName, this.getMssqlType(tableName, key), null);
1965
+ } else {
1966
+ request.input(paramName, preparedValue);
1967
+ }
1968
+ });
1969
+ const tableName_ = getTableName({
1970
+ indexName: tableName,
1971
+ schemaName: getSchemaName(this.schemaName)
1972
+ });
1973
+ const updateSql = `UPDATE ${tableName_} SET ${setClauses.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
1974
+ await request.query(updateSql);
1975
+ } catch (error$1) {
1976
+ throw new error.MastraError(
1977
+ {
1978
+ id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_FAILED",
1979
+ domain: error.ErrorDomain.STORAGE,
1980
+ category: error.ErrorCategory.THIRD_PARTY,
1981
+ details: {
1982
+ tableName
1983
+ }
1984
+ },
1985
+ error$1
1986
+ );
1987
+ }
1988
+ }
1989
+ /**
1990
+ * Update multiple records in a single batch transaction
1991
+ */
1992
+ async batchUpdate({
1993
+ tableName,
1994
+ updates
1995
+ }) {
1996
+ const transaction = this.pool.transaction();
1997
+ try {
1998
+ await transaction.begin();
1999
+ for (const { keys, data } of updates) {
2000
+ await this.update({ tableName, keys, data, transaction });
2001
+ }
2002
+ await transaction.commit();
2003
+ } catch (error$1) {
2004
+ await transaction.rollback();
2005
+ throw new error.MastraError(
2006
+ {
2007
+ id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_UPDATE_FAILED",
2008
+ domain: error.ErrorDomain.STORAGE,
2009
+ category: error.ErrorCategory.THIRD_PARTY,
2010
+ details: {
2011
+ tableName,
2012
+ numberOfRecords: updates.length
2013
+ }
2014
+ },
2015
+ error$1
2016
+ );
2017
+ }
2018
+ }
2019
+ /**
2020
+ * Delete multiple records by keys
2021
+ */
2022
+ async batchDelete({ tableName, keys }) {
2023
+ if (keys.length === 0) {
2024
+ return;
2025
+ }
2026
+ const tableName_ = getTableName({
2027
+ indexName: tableName,
2028
+ schemaName: getSchemaName(this.schemaName)
2029
+ });
2030
+ const transaction = this.pool.transaction();
2031
+ try {
2032
+ await transaction.begin();
2033
+ for (const keySet of keys) {
2034
+ const conditions = [];
2035
+ const request = transaction.request();
2036
+ let paramIndex = 0;
2037
+ Object.entries(keySet).forEach(([key, value]) => {
2038
+ const parsedKey = utils.parseSqlIdentifier(key, "column name");
2039
+ const paramName = `p${paramIndex++}`;
2040
+ conditions.push(`[${parsedKey}] = @${paramName}`);
2041
+ const preparedValue = this.prepareValue(value, key, tableName);
2042
+ if (preparedValue === null || preparedValue === void 0) {
2043
+ request.input(paramName, this.getMssqlType(tableName, key), null);
2044
+ } else {
2045
+ request.input(paramName, preparedValue);
2046
+ }
2047
+ });
2048
+ const deleteSql = `DELETE FROM ${tableName_} WHERE ${conditions.join(" AND ")}`;
2049
+ await request.query(deleteSql);
2050
+ }
2051
+ await transaction.commit();
2052
+ } catch (error$1) {
2053
+ await transaction.rollback();
2054
+ throw new error.MastraError(
2055
+ {
2056
+ id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_DELETE_FAILED",
2057
+ domain: error.ErrorDomain.STORAGE,
2058
+ category: error.ErrorCategory.THIRD_PARTY,
2059
+ details: {
2060
+ tableName,
2061
+ numberOfRecords: keys.length
2062
+ }
2063
+ },
2064
+ error$1
2065
+ );
2066
+ }
2067
+ }
2068
+ /**
2069
+ * Create a new index on a table
2070
+ */
2071
+ async createIndex(options) {
2072
+ try {
2073
+ const { name, table, columns, unique = false, where } = options;
2074
+ const schemaName = this.schemaName || "dbo";
2075
+ const fullTableName = getTableName({
2076
+ indexName: table,
2077
+ schemaName: getSchemaName(this.schemaName)
2078
+ });
2079
+ const indexNameSafe = utils.parseSqlIdentifier(name, "index name");
2080
+ const checkRequest = this.pool.request();
2081
+ checkRequest.input("indexName", indexNameSafe);
2082
+ checkRequest.input("schemaName", schemaName);
2083
+ checkRequest.input("tableName", table);
2084
+ const indexExists = await checkRequest.query(`
2085
+ SELECT 1 as found
2086
+ FROM sys.indexes i
2087
+ INNER JOIN sys.tables t ON i.object_id = t.object_id
2088
+ INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
2089
+ WHERE i.name = @indexName
2090
+ AND s.name = @schemaName
2091
+ AND t.name = @tableName
2092
+ `);
2093
+ if (indexExists.recordset && indexExists.recordset.length > 0) {
2094
+ return;
2095
+ }
2096
+ const uniqueStr = unique ? "UNIQUE " : "";
2097
+ const columnsStr = columns.map((col) => {
2098
+ if (col.includes(" DESC") || col.includes(" ASC")) {
2099
+ const [colName, ...modifiers] = col.split(" ");
2100
+ if (!colName) {
2101
+ throw new Error(`Invalid column specification: ${col}`);
2102
+ }
2103
+ return `[${utils.parseSqlIdentifier(colName, "column name")}] ${modifiers.join(" ")}`;
2104
+ }
2105
+ return `[${utils.parseSqlIdentifier(col, "column name")}]`;
2106
+ }).join(", ");
2107
+ const whereStr = where ? ` WHERE ${where}` : "";
2108
+ const createIndexSql = `CREATE ${uniqueStr}INDEX [${indexNameSafe}] ON ${fullTableName} (${columnsStr})${whereStr}`;
2109
+ await this.pool.request().query(createIndexSql);
2110
+ } catch (error$1) {
2111
+ throw new error.MastraError(
2112
+ {
2113
+ id: "MASTRA_STORAGE_MSSQL_INDEX_CREATE_FAILED",
2114
+ domain: error.ErrorDomain.STORAGE,
2115
+ category: error.ErrorCategory.THIRD_PARTY,
2116
+ details: {
2117
+ indexName: options.name,
2118
+ tableName: options.table
2119
+ }
2120
+ },
2121
+ error$1
2122
+ );
2123
+ }
2124
+ }
2125
+ /**
2126
+ * Drop an existing index
2127
+ */
2128
+ async dropIndex(indexName) {
2129
+ try {
2130
+ const schemaName = this.schemaName || "dbo";
2131
+ const indexNameSafe = utils.parseSqlIdentifier(indexName, "index name");
2132
+ const checkRequest = this.pool.request();
2133
+ checkRequest.input("indexName", indexNameSafe);
2134
+ checkRequest.input("schemaName", schemaName);
2135
+ const result = await checkRequest.query(`
2136
+ SELECT t.name as table_name
2137
+ FROM sys.indexes i
2138
+ INNER JOIN sys.tables t ON i.object_id = t.object_id
2139
+ INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
2140
+ WHERE i.name = @indexName
2141
+ AND s.name = @schemaName
2142
+ `);
2143
+ if (!result.recordset || result.recordset.length === 0) {
2144
+ return;
2145
+ }
2146
+ if (result.recordset.length > 1) {
2147
+ const tables = result.recordset.map((r) => r.table_name).join(", ");
2148
+ throw new error.MastraError({
2149
+ id: "MASTRA_STORAGE_MSSQL_INDEX_AMBIGUOUS",
2150
+ domain: error.ErrorDomain.STORAGE,
2151
+ category: error.ErrorCategory.USER,
2152
+ text: `Index "${indexNameSafe}" exists on multiple tables (${tables}) in schema "${schemaName}". Please drop indexes manually or ensure unique index names.`
2153
+ });
2154
+ }
2155
+ const tableName = result.recordset[0].table_name;
2156
+ const fullTableName = getTableName({
2157
+ indexName: tableName,
2158
+ schemaName: getSchemaName(this.schemaName)
2159
+ });
2160
+ const dropSql = `DROP INDEX [${indexNameSafe}] ON ${fullTableName}`;
2161
+ await this.pool.request().query(dropSql);
2162
+ } catch (error$1) {
2163
+ throw new error.MastraError(
2164
+ {
2165
+ id: "MASTRA_STORAGE_MSSQL_INDEX_DROP_FAILED",
2166
+ domain: error.ErrorDomain.STORAGE,
2167
+ category: error.ErrorCategory.THIRD_PARTY,
2168
+ details: {
2169
+ indexName
2170
+ }
2171
+ },
2172
+ error$1
2173
+ );
2174
+ }
2175
+ }
2176
+ /**
2177
+ * List indexes for a specific table or all tables
2178
+ */
2179
+ async listIndexes(tableName) {
2180
+ try {
2181
+ const schemaName = this.schemaName || "dbo";
2182
+ let query;
2183
+ const request = this.pool.request();
2184
+ request.input("schemaName", schemaName);
2185
+ if (tableName) {
2186
+ query = `
2187
+ SELECT
2188
+ i.name as name,
2189
+ o.name as [table],
2190
+ i.is_unique as is_unique,
2191
+ CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
2192
+ FROM sys.indexes i
2193
+ INNER JOIN sys.objects o ON i.object_id = o.object_id
2194
+ INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
2195
+ LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
2196
+ WHERE sch.name = @schemaName
2197
+ AND o.name = @tableName
2198
+ AND i.name IS NOT NULL
2199
+ GROUP BY i.name, o.name, i.is_unique
2200
+ `;
2201
+ request.input("tableName", tableName);
2202
+ } else {
2203
+ query = `
2204
+ SELECT
2205
+ i.name as name,
2206
+ o.name as [table],
2207
+ i.is_unique as is_unique,
2208
+ CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size
2209
+ FROM sys.indexes i
2210
+ INNER JOIN sys.objects o ON i.object_id = o.object_id
2211
+ INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
2212
+ LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
2213
+ WHERE sch.name = @schemaName
2214
+ AND i.name IS NOT NULL
2215
+ GROUP BY i.name, o.name, i.is_unique
2216
+ `;
2217
+ }
2218
+ const result = await request.query(query);
2219
+ const indexes = [];
2220
+ for (const row of result.recordset) {
2221
+ const colRequest = this.pool.request();
2222
+ colRequest.input("indexName", row.name);
2223
+ colRequest.input("schemaName", schemaName);
2224
+ const colResult = await colRequest.query(`
2225
+ SELECT c.name as column_name
2226
+ FROM sys.indexes i
2227
+ INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
2228
+ INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
2229
+ INNER JOIN sys.objects o ON i.object_id = o.object_id
2230
+ INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
2231
+ WHERE i.name = @indexName
2232
+ AND s.name = @schemaName
2233
+ ORDER BY ic.key_ordinal
2234
+ `);
2235
+ indexes.push({
2236
+ name: row.name,
2237
+ table: row.table,
2238
+ columns: colResult.recordset.map((c) => c.column_name),
2239
+ unique: row.is_unique || false,
2240
+ size: row.size || "0 MB",
2241
+ definition: ""
2242
+ // MSSQL doesn't store definition like PG
2243
+ });
2244
+ }
2245
+ return indexes;
2246
+ } catch (error$1) {
2247
+ throw new error.MastraError(
2248
+ {
2249
+ id: "MASTRA_STORAGE_MSSQL_INDEX_LIST_FAILED",
2250
+ domain: error.ErrorDomain.STORAGE,
2251
+ category: error.ErrorCategory.THIRD_PARTY,
2252
+ details: tableName ? {
2253
+ tableName
2254
+ } : {}
2255
+ },
2256
+ error$1
2257
+ );
2258
+ }
2259
+ }
2260
+ /**
2261
+ * Get detailed statistics for a specific index
2262
+ */
2263
+ async describeIndex(indexName) {
2264
+ try {
2265
+ const schemaName = this.schemaName || "dbo";
2266
+ const request = this.pool.request();
2267
+ request.input("indexName", indexName);
2268
+ request.input("schemaName", schemaName);
2269
+ const query = `
2270
+ SELECT
2271
+ i.name as name,
2272
+ o.name as [table],
2273
+ i.is_unique as is_unique,
2274
+ CAST(SUM(s.used_page_count) * 8 / 1024.0 AS VARCHAR(50)) + ' MB' as size,
2275
+ i.type_desc as method,
2276
+ ISNULL(us.user_scans, 0) as scans,
2277
+ ISNULL(us.user_seeks + us.user_scans, 0) as tuples_read,
2278
+ ISNULL(us.user_lookups, 0) as tuples_fetched
2279
+ FROM sys.indexes i
2280
+ INNER JOIN sys.objects o ON i.object_id = o.object_id
2281
+ INNER JOIN sys.schemas sch ON o.schema_id = sch.schema_id
2282
+ LEFT JOIN sys.dm_db_partition_stats s ON i.object_id = s.object_id AND i.index_id = s.index_id
2283
+ LEFT JOIN sys.dm_db_index_usage_stats us ON i.object_id = us.object_id AND i.index_id = us.index_id
2284
+ WHERE i.name = @indexName
2285
+ AND sch.name = @schemaName
2286
+ GROUP BY i.name, o.name, i.is_unique, i.type_desc, us.user_seeks, us.user_scans, us.user_lookups
2287
+ `;
2288
+ const result = await request.query(query);
2289
+ if (!result.recordset || result.recordset.length === 0) {
2290
+ throw new Error(`Index "${indexName}" not found in schema "${schemaName}"`);
2291
+ }
2292
+ const row = result.recordset[0];
2293
+ const colRequest = this.pool.request();
2294
+ colRequest.input("indexName", indexName);
2295
+ colRequest.input("schemaName", schemaName);
2296
+ const colResult = await colRequest.query(`
2297
+ SELECT c.name as column_name
2298
+ FROM sys.indexes i
2299
+ INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
2300
+ INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
2301
+ INNER JOIN sys.objects o ON i.object_id = o.object_id
2302
+ INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
2303
+ WHERE i.name = @indexName
2304
+ AND s.name = @schemaName
2305
+ ORDER BY ic.key_ordinal
2306
+ `);
2307
+ return {
2308
+ name: row.name,
2309
+ table: row.table,
2310
+ columns: colResult.recordset.map((c) => c.column_name),
2311
+ unique: row.is_unique || false,
2312
+ size: row.size || "0 MB",
2313
+ definition: "",
2314
+ method: row.method?.toLowerCase() || "nonclustered",
2315
+ scans: Number(row.scans) || 0,
2316
+ tuples_read: Number(row.tuples_read) || 0,
2317
+ tuples_fetched: Number(row.tuples_fetched) || 0
2318
+ };
2319
+ } catch (error$1) {
2320
+ throw new error.MastraError(
2321
+ {
2322
+ id: "MASTRA_STORAGE_MSSQL_INDEX_DESCRIBE_FAILED",
2323
+ domain: error.ErrorDomain.STORAGE,
2324
+ category: error.ErrorCategory.THIRD_PARTY,
2325
+ details: {
2326
+ indexName
2327
+ }
2328
+ },
2329
+ error$1
2330
+ );
2331
+ }
2332
+ }
2333
+ /**
2334
+ * Returns definitions for automatic performance indexes
2335
+ * IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
2336
+ * NOTE: Using NVARCHAR(400) for text columns (800 bytes) leaves room for composite indexes
2337
+ */
2338
+ getAutomaticIndexDefinitions() {
2339
+ const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
2340
+ return [
2341
+ // Composite indexes for optimal filtering + sorting performance
2342
+ // NVARCHAR(400) = 800 bytes, plus BIGINT (8 bytes) = 808 bytes total (under 900-byte limit)
2343
+ {
2344
+ name: `${schemaPrefix}mastra_threads_resourceid_seqid_idx`,
2345
+ table: storage.TABLE_THREADS,
2346
+ columns: ["resourceId", "seq_id DESC"]
2347
+ },
2348
+ {
2349
+ name: `${schemaPrefix}mastra_messages_thread_id_seqid_idx`,
2350
+ table: storage.TABLE_MESSAGES,
2351
+ columns: ["thread_id", "seq_id DESC"]
2352
+ },
2353
+ {
2354
+ name: `${schemaPrefix}mastra_traces_name_seqid_idx`,
2355
+ table: storage.TABLE_TRACES,
2356
+ columns: ["name", "seq_id DESC"]
2357
+ },
2358
+ {
2359
+ name: `${schemaPrefix}mastra_evals_agent_name_seqid_idx`,
2360
+ table: storage.TABLE_EVALS,
2361
+ columns: ["agent_name", "seq_id DESC"]
2362
+ },
2363
+ {
2364
+ name: `${schemaPrefix}mastra_scores_trace_id_span_id_seqid_idx`,
2365
+ table: storage.TABLE_SCORERS,
2366
+ columns: ["traceId", "spanId", "seq_id DESC"]
2367
+ },
2368
+ // AI Spans indexes for optimal trace querying
2369
+ {
2370
+ name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
2371
+ table: storage.TABLE_AI_SPANS,
2372
+ columns: ["traceId", "startedAt DESC"]
2373
+ },
2374
+ {
2375
+ name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
2376
+ table: storage.TABLE_AI_SPANS,
2377
+ columns: ["parentSpanId", "startedAt DESC"]
2378
+ },
2379
+ {
2380
+ name: `${schemaPrefix}mastra_ai_spans_name_idx`,
2381
+ table: storage.TABLE_AI_SPANS,
2382
+ columns: ["name"]
2383
+ },
2384
+ {
2385
+ name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
2386
+ table: storage.TABLE_AI_SPANS,
2387
+ columns: ["spanType", "startedAt DESC"]
2388
+ }
2389
+ ];
2390
+ }
2391
+ /**
2392
+ * Creates automatic indexes for optimal query performance
2393
+ * Uses getAutomaticIndexDefinitions() to determine which indexes to create
2394
+ */
2395
+ async createAutomaticIndexes() {
2396
+ try {
2397
+ const indexes = this.getAutomaticIndexDefinitions();
2398
+ for (const indexOptions of indexes) {
2399
+ try {
2400
+ await this.createIndex(indexOptions);
2401
+ } catch (error) {
2402
+ this.logger?.warn?.(`Failed to create index ${indexOptions.name}:`, error);
2403
+ }
2404
+ }
2405
+ } catch (error$1) {
2406
+ throw new error.MastraError(
2407
+ {
2408
+ id: "MASTRA_STORAGE_MSSQL_STORE_CREATE_PERFORMANCE_INDEXES_FAILED",
2409
+ domain: error.ErrorDomain.STORAGE,
2410
+ category: error.ErrorCategory.THIRD_PARTY
2411
+ },
2412
+ error$1
2413
+ );
2414
+ }
2415
+ }
2416
+ };
2417
+ function transformScoreRow(row) {
2418
+ return {
2419
+ ...row,
2420
+ input: storage.safelyParseJSON(row.input),
2421
+ scorer: storage.safelyParseJSON(row.scorer),
2422
+ preprocessStepResult: storage.safelyParseJSON(row.preprocessStepResult),
2423
+ analyzeStepResult: storage.safelyParseJSON(row.analyzeStepResult),
2424
+ metadata: storage.safelyParseJSON(row.metadata),
2425
+ output: storage.safelyParseJSON(row.output),
2426
+ additionalContext: storage.safelyParseJSON(row.additionalContext),
2427
+ runtimeContext: storage.safelyParseJSON(row.runtimeContext),
2428
+ entity: storage.safelyParseJSON(row.entity),
2429
+ createdAt: new Date(row.createdAt),
2430
+ updatedAt: new Date(row.updatedAt)
2431
+ };
2432
+ }
2433
+ var ScoresMSSQL = class extends storage.ScoresStorage {
2434
+ pool;
2435
+ operations;
2436
+ schema;
2437
+ constructor({
2438
+ pool,
2439
+ operations,
2440
+ schema
2441
+ }) {
2442
+ super();
2443
+ this.pool = pool;
2444
+ this.operations = operations;
2445
+ this.schema = schema;
2446
+ }
2447
+ async getScoreById({ id }) {
2448
+ try {
2449
+ const request = this.pool.request();
2450
+ request.input("p1", id);
2451
+ const result = await request.query(
2452
+ `SELECT * FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE id = @p1`
2453
+ );
2454
+ if (result.recordset.length === 0) {
2455
+ return null;
2456
+ }
2457
+ return transformScoreRow(result.recordset[0]);
2458
+ } catch (error$1) {
2459
+ throw new error.MastraError(
2460
+ {
2461
+ id: "MASTRA_STORAGE_MSSQL_STORE_GET_SCORE_BY_ID_FAILED",
2462
+ domain: error.ErrorDomain.STORAGE,
2463
+ category: error.ErrorCategory.THIRD_PARTY,
2464
+ details: { id }
2465
+ },
2466
+ error$1
2467
+ );
2468
+ }
2469
+ }
2470
+ async saveScore(score) {
2471
+ let validatedScore;
2472
+ try {
2473
+ validatedScore = scores.saveScorePayloadSchema.parse(score);
2474
+ } catch (error$1) {
2475
+ throw new error.MastraError(
2476
+ {
2477
+ id: "MASTRA_STORAGE_MSSQL_STORE_SAVE_SCORE_VALIDATION_FAILED",
2478
+ domain: error.ErrorDomain.STORAGE,
2479
+ category: error.ErrorCategory.THIRD_PARTY
2480
+ },
2481
+ error$1
2482
+ );
2483
+ }
2484
+ try {
1483
2485
  const scoreId = crypto.randomUUID();
1484
2486
  const {
1485
2487
  scorer,
@@ -1492,21 +2494,21 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1492
2494
  runtimeContext,
1493
2495
  entity,
1494
2496
  ...rest
1495
- } = score;
2497
+ } = validatedScore;
1496
2498
  await this.operations.insert({
1497
2499
  tableName: storage.TABLE_SCORERS,
1498
2500
  record: {
1499
2501
  id: scoreId,
1500
2502
  ...rest,
1501
- input: JSON.stringify(input) || "",
1502
- output: JSON.stringify(output) || "",
1503
- preprocessStepResult: preprocessStepResult ? JSON.stringify(preprocessStepResult) : null,
1504
- analyzeStepResult: analyzeStepResult ? JSON.stringify(analyzeStepResult) : null,
1505
- metadata: metadata ? JSON.stringify(metadata) : null,
1506
- additionalContext: additionalContext ? JSON.stringify(additionalContext) : null,
1507
- runtimeContext: runtimeContext ? JSON.stringify(runtimeContext) : null,
1508
- entity: entity ? JSON.stringify(entity) : null,
1509
- scorer: scorer ? JSON.stringify(scorer) : null,
2503
+ input: input || "",
2504
+ output: output || "",
2505
+ preprocessStepResult: preprocessStepResult || null,
2506
+ analyzeStepResult: analyzeStepResult || null,
2507
+ metadata: metadata || null,
2508
+ additionalContext: additionalContext || null,
2509
+ runtimeContext: runtimeContext || null,
2510
+ entity: entity || null,
2511
+ scorer: scorer || null,
1510
2512
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1511
2513
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1512
2514
  }
@@ -1526,14 +2528,37 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1526
2528
  }
1527
2529
  async getScoresByScorerId({
1528
2530
  scorerId,
1529
- pagination
2531
+ pagination,
2532
+ entityId,
2533
+ entityType,
2534
+ source
1530
2535
  }) {
1531
2536
  try {
1532
- const request = this.pool.request();
1533
- request.input("p1", scorerId);
1534
- const totalResult = await request.query(
1535
- `SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [scorerId] = @p1`
1536
- );
2537
+ const conditions = ["[scorerId] = @p1"];
2538
+ const params = { p1: scorerId };
2539
+ let paramIndex = 2;
2540
+ if (entityId) {
2541
+ conditions.push(`[entityId] = @p${paramIndex}`);
2542
+ params[`p${paramIndex}`] = entityId;
2543
+ paramIndex++;
2544
+ }
2545
+ if (entityType) {
2546
+ conditions.push(`[entityType] = @p${paramIndex}`);
2547
+ params[`p${paramIndex}`] = entityType;
2548
+ paramIndex++;
2549
+ }
2550
+ if (source) {
2551
+ conditions.push(`[source] = @p${paramIndex}`);
2552
+ params[`p${paramIndex}`] = source;
2553
+ paramIndex++;
2554
+ }
2555
+ const whereClause = conditions.join(" AND ");
2556
+ const tableName = getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) });
2557
+ const countRequest = this.pool.request();
2558
+ Object.entries(params).forEach(([key, value]) => {
2559
+ countRequest.input(key, value);
2560
+ });
2561
+ const totalResult = await countRequest.query(`SELECT COUNT(*) as count FROM ${tableName} WHERE ${whereClause}`);
1537
2562
  const total = totalResult.recordset[0]?.count || 0;
1538
2563
  if (total === 0) {
1539
2564
  return {
@@ -1547,12 +2572,13 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1547
2572
  };
1548
2573
  }
1549
2574
  const dataRequest = this.pool.request();
1550
- dataRequest.input("p1", scorerId);
1551
- dataRequest.input("p2", pagination.perPage);
1552
- dataRequest.input("p3", pagination.page * pagination.perPage);
1553
- const result = await dataRequest.query(
1554
- `SELECT * FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [scorerId] = @p1 ORDER BY [createdAt] DESC OFFSET @p3 ROWS FETCH NEXT @p2 ROWS ONLY`
1555
- );
2575
+ Object.entries(params).forEach(([key, value]) => {
2576
+ dataRequest.input(key, value);
2577
+ });
2578
+ dataRequest.input("perPage", pagination.perPage);
2579
+ dataRequest.input("offset", pagination.page * pagination.perPage);
2580
+ const dataQuery = `SELECT * FROM ${tableName} WHERE ${whereClause} ORDER BY [createdAt] DESC OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
2581
+ const result = await dataRequest.query(dataQuery);
1556
2582
  return {
1557
2583
  pagination: {
1558
2584
  total: Number(total),
@@ -1677,6 +2703,60 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1677
2703
  );
1678
2704
  }
1679
2705
  }
2706
+ async getScoresBySpan({
2707
+ traceId,
2708
+ spanId,
2709
+ pagination
2710
+ }) {
2711
+ try {
2712
+ const request = this.pool.request();
2713
+ request.input("p1", traceId);
2714
+ request.input("p2", spanId);
2715
+ const totalResult = await request.query(
2716
+ `SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [traceId] = @p1 AND [spanId] = @p2`
2717
+ );
2718
+ const total = totalResult.recordset[0]?.count || 0;
2719
+ if (total === 0) {
2720
+ return {
2721
+ pagination: {
2722
+ total: 0,
2723
+ page: pagination.page,
2724
+ perPage: pagination.perPage,
2725
+ hasMore: false
2726
+ },
2727
+ scores: []
2728
+ };
2729
+ }
2730
+ const limit = pagination.perPage + 1;
2731
+ const dataRequest = this.pool.request();
2732
+ dataRequest.input("p1", traceId);
2733
+ dataRequest.input("p2", spanId);
2734
+ dataRequest.input("p3", limit);
2735
+ dataRequest.input("p4", pagination.page * pagination.perPage);
2736
+ const result = await dataRequest.query(
2737
+ `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`
2738
+ );
2739
+ return {
2740
+ pagination: {
2741
+ total: Number(total),
2742
+ page: pagination.page,
2743
+ perPage: pagination.perPage,
2744
+ hasMore: result.recordset.length > pagination.perPage
2745
+ },
2746
+ scores: result.recordset.slice(0, pagination.perPage).map((row) => transformScoreRow(row))
2747
+ };
2748
+ } catch (error$1) {
2749
+ throw new error.MastraError(
2750
+ {
2751
+ id: "MASTRA_STORAGE_MSSQL_STORE_GET_SCORES_BY_SPAN_FAILED",
2752
+ domain: error.ErrorDomain.STORAGE,
2753
+ category: error.ErrorCategory.THIRD_PARTY,
2754
+ details: { traceId, spanId }
2755
+ },
2756
+ error$1
2757
+ );
2758
+ }
2759
+ }
1680
2760
  };
1681
2761
  var TracesMSSQL = class extends storage.TracesStorage {
1682
2762
  pool;
@@ -1755,7 +2835,7 @@ var TracesMSSQL = class extends storage.TracesStorage {
1755
2835
  const countRequest = this.pool.request();
1756
2836
  Object.entries(paramMap).forEach(([key, value]) => {
1757
2837
  if (value instanceof Date) {
1758
- countRequest.input(key, sql2__default.default.DateTime, value);
2838
+ countRequest.input(key, sql3__default.default.DateTime, value);
1759
2839
  } else {
1760
2840
  countRequest.input(key, value);
1761
2841
  }
@@ -1789,7 +2869,7 @@ var TracesMSSQL = class extends storage.TracesStorage {
1789
2869
  const dataRequest = this.pool.request();
1790
2870
  Object.entries(paramMap).forEach(([key, value]) => {
1791
2871
  if (value instanceof Date) {
1792
- dataRequest.input(key, sql2__default.default.DateTime, value);
2872
+ dataRequest.input(key, sql3__default.default.DateTime, value);
1793
2873
  } else {
1794
2874
  dataRequest.input(key, value);
1795
2875
  }
@@ -1845,24 +2925,6 @@ var TracesMSSQL = class extends storage.TracesStorage {
1845
2925
  });
1846
2926
  }
1847
2927
  };
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
2928
  var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
1867
2929
  pool;
1868
2930
  operations;
@@ -1877,21 +2939,164 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
1877
2939
  this.operations = operations;
1878
2940
  this.schema = schema;
1879
2941
  }
1880
- updateWorkflowResults({
1881
- // workflowName,
1882
- // runId,
1883
- // stepId,
1884
- // result,
1885
- // runtimeContext,
2942
+ parseWorkflowRun(row) {
2943
+ let parsedSnapshot = row.snapshot;
2944
+ if (typeof parsedSnapshot === "string") {
2945
+ try {
2946
+ parsedSnapshot = JSON.parse(row.snapshot);
2947
+ } catch (e) {
2948
+ this.logger?.warn?.(`Failed to parse snapshot for workflow ${row.workflow_name}:`, e);
2949
+ }
2950
+ }
2951
+ return {
2952
+ workflowName: row.workflow_name,
2953
+ runId: row.run_id,
2954
+ snapshot: parsedSnapshot,
2955
+ createdAt: row.createdAt,
2956
+ updatedAt: row.updatedAt,
2957
+ resourceId: row.resourceId
2958
+ };
2959
+ }
2960
+ async updateWorkflowResults({
2961
+ workflowName,
2962
+ runId,
2963
+ stepId,
2964
+ result,
2965
+ runtimeContext
1886
2966
  }) {
1887
- throw new Error("Method not implemented.");
2967
+ const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
2968
+ const transaction = this.pool.transaction();
2969
+ try {
2970
+ await transaction.begin();
2971
+ const selectRequest = new sql3__default.default.Request(transaction);
2972
+ selectRequest.input("workflow_name", workflowName);
2973
+ selectRequest.input("run_id", runId);
2974
+ const existingSnapshotResult = await selectRequest.query(
2975
+ `SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
2976
+ );
2977
+ let snapshot;
2978
+ if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
2979
+ snapshot = {
2980
+ context: {},
2981
+ activePaths: [],
2982
+ activeStepsPath: {},
2983
+ timestamp: Date.now(),
2984
+ suspendedPaths: {},
2985
+ resumeLabels: {},
2986
+ serializedStepGraph: [],
2987
+ status: "pending",
2988
+ value: {},
2989
+ waitingPaths: {},
2990
+ runId,
2991
+ runtimeContext: {}
2992
+ };
2993
+ } else {
2994
+ const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
2995
+ snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
2996
+ }
2997
+ snapshot.context[stepId] = result;
2998
+ snapshot.runtimeContext = { ...snapshot.runtimeContext, ...runtimeContext };
2999
+ const upsertReq = new sql3__default.default.Request(transaction);
3000
+ upsertReq.input("workflow_name", workflowName);
3001
+ upsertReq.input("run_id", runId);
3002
+ upsertReq.input("snapshot", JSON.stringify(snapshot));
3003
+ upsertReq.input("createdAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
3004
+ upsertReq.input("updatedAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
3005
+ await upsertReq.query(
3006
+ `MERGE ${table} AS target
3007
+ USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
3008
+ ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
3009
+ WHEN MATCHED THEN UPDATE SET snapshot = @snapshot, [updatedAt] = @updatedAt
3010
+ WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, snapshot, [createdAt], [updatedAt])
3011
+ VALUES (@workflow_name, @run_id, @snapshot, @createdAt, @updatedAt);`
3012
+ );
3013
+ await transaction.commit();
3014
+ return snapshot.context;
3015
+ } catch (error$1) {
3016
+ try {
3017
+ await transaction.rollback();
3018
+ } catch {
3019
+ }
3020
+ throw new error.MastraError(
3021
+ {
3022
+ id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_RESULTS_FAILED",
3023
+ domain: error.ErrorDomain.STORAGE,
3024
+ category: error.ErrorCategory.THIRD_PARTY,
3025
+ details: {
3026
+ workflowName,
3027
+ runId,
3028
+ stepId
3029
+ }
3030
+ },
3031
+ error$1
3032
+ );
3033
+ }
1888
3034
  }
1889
- updateWorkflowState({
1890
- // workflowName,
1891
- // runId,
1892
- // opts,
3035
+ async updateWorkflowState({
3036
+ workflowName,
3037
+ runId,
3038
+ opts
1893
3039
  }) {
1894
- throw new Error("Method not implemented.");
3040
+ const table = getTableName({ indexName: storage.TABLE_WORKFLOW_SNAPSHOT, schemaName: getSchemaName(this.schema) });
3041
+ const transaction = this.pool.transaction();
3042
+ try {
3043
+ await transaction.begin();
3044
+ const selectRequest = new sql3__default.default.Request(transaction);
3045
+ selectRequest.input("workflow_name", workflowName);
3046
+ selectRequest.input("run_id", runId);
3047
+ const existingSnapshotResult = await selectRequest.query(
3048
+ `SELECT snapshot FROM ${table} WITH (UPDLOCK, HOLDLOCK) WHERE workflow_name = @workflow_name AND run_id = @run_id`
3049
+ );
3050
+ if (!existingSnapshotResult.recordset || existingSnapshotResult.recordset.length === 0) {
3051
+ await transaction.rollback();
3052
+ return void 0;
3053
+ }
3054
+ const existingSnapshot = existingSnapshotResult.recordset[0].snapshot;
3055
+ const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
3056
+ if (!snapshot || !snapshot?.context) {
3057
+ await transaction.rollback();
3058
+ throw new error.MastraError(
3059
+ {
3060
+ id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_SNAPSHOT_NOT_FOUND",
3061
+ domain: error.ErrorDomain.STORAGE,
3062
+ category: error.ErrorCategory.SYSTEM,
3063
+ details: {
3064
+ workflowName,
3065
+ runId
3066
+ }
3067
+ },
3068
+ new Error(`Snapshot not found for runId ${runId}`)
3069
+ );
3070
+ }
3071
+ const updatedSnapshot = { ...snapshot, ...opts };
3072
+ const updateRequest = new sql3__default.default.Request(transaction);
3073
+ updateRequest.input("snapshot", JSON.stringify(updatedSnapshot));
3074
+ updateRequest.input("workflow_name", workflowName);
3075
+ updateRequest.input("run_id", runId);
3076
+ updateRequest.input("updatedAt", sql3__default.default.DateTime2, /* @__PURE__ */ new Date());
3077
+ await updateRequest.query(
3078
+ `UPDATE ${table} SET snapshot = @snapshot, [updatedAt] = @updatedAt WHERE workflow_name = @workflow_name AND run_id = @run_id`
3079
+ );
3080
+ await transaction.commit();
3081
+ return updatedSnapshot;
3082
+ } catch (error$1) {
3083
+ try {
3084
+ await transaction.rollback();
3085
+ } catch {
3086
+ }
3087
+ throw new error.MastraError(
3088
+ {
3089
+ id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_FAILED",
3090
+ domain: error.ErrorDomain.STORAGE,
3091
+ category: error.ErrorCategory.THIRD_PARTY,
3092
+ details: {
3093
+ workflowName,
3094
+ runId
3095
+ }
3096
+ },
3097
+ error$1
3098
+ );
3099
+ }
1895
3100
  }
1896
3101
  async persistWorkflowSnapshot({
1897
3102
  workflowName,
@@ -1907,8 +3112,8 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
1907
3112
  request.input("run_id", runId);
1908
3113
  request.input("resourceId", resourceId);
1909
3114
  request.input("snapshot", JSON.stringify(snapshot));
1910
- request.input("createdAt", sql2__default.default.DateTime2, new Date(now));
1911
- request.input("updatedAt", sql2__default.default.DateTime2, new Date(now));
3115
+ request.input("createdAt", sql3__default.default.DateTime2, new Date(now));
3116
+ request.input("updatedAt", sql3__default.default.DateTime2, new Date(now));
1912
3117
  const mergeSql = `MERGE INTO ${table} AS target
1913
3118
  USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
1914
3119
  ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
@@ -1989,7 +3194,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
1989
3194
  if (!result.recordset || result.recordset.length === 0) {
1990
3195
  return null;
1991
3196
  }
1992
- return parseWorkflowRun(result.recordset[0]);
3197
+ return this.parseWorkflowRun(result.recordset[0]);
1993
3198
  } catch (error$1) {
1994
3199
  throw new error.MastraError(
1995
3200
  {
@@ -2011,7 +3216,8 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2011
3216
  toDate,
2012
3217
  limit,
2013
3218
  offset,
2014
- resourceId
3219
+ resourceId,
3220
+ status
2015
3221
  } = {}) {
2016
3222
  try {
2017
3223
  const conditions = [];
@@ -2020,13 +3226,17 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2020
3226
  conditions.push(`[workflow_name] = @workflowName`);
2021
3227
  paramMap["workflowName"] = workflowName;
2022
3228
  }
3229
+ if (status) {
3230
+ conditions.push(`JSON_VALUE([snapshot], '$.status') = @status`);
3231
+ paramMap["status"] = status;
3232
+ }
2023
3233
  if (resourceId) {
2024
3234
  const hasResourceId = await this.operations.hasColumn(storage.TABLE_WORKFLOW_SNAPSHOT, "resourceId");
2025
3235
  if (hasResourceId) {
2026
3236
  conditions.push(`[resourceId] = @resourceId`);
2027
3237
  paramMap["resourceId"] = resourceId;
2028
3238
  } else {
2029
- console.warn(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
3239
+ this.logger?.warn?.(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
2030
3240
  }
2031
3241
  }
2032
3242
  if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
@@ -2043,7 +3253,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2043
3253
  const request = this.pool.request();
2044
3254
  Object.entries(paramMap).forEach(([key, value]) => {
2045
3255
  if (value instanceof Date) {
2046
- request.input(key, sql2__default.default.DateTime, value);
3256
+ request.input(key, sql3__default.default.DateTime, value);
2047
3257
  } else {
2048
3258
  request.input(key, value);
2049
3259
  }
@@ -2060,7 +3270,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2060
3270
  request.input("offset", offset);
2061
3271
  }
2062
3272
  const result = await request.query(query);
2063
- const runs = (result.recordset || []).map((row) => parseWorkflowRun(row));
3273
+ const runs = (result.recordset || []).map((row) => this.parseWorkflowRun(row));
2064
3274
  return { runs, total: total || runs.length };
2065
3275
  } catch (error$1) {
2066
3276
  throw new error.MastraError(
@@ -2100,7 +3310,7 @@ var MSSQLStore = class extends storage.MastraStorage {
2100
3310
  }
2101
3311
  }
2102
3312
  this.schema = config.schemaName || "dbo";
2103
- this.pool = "connectionString" in config ? new sql2__default.default.ConnectionPool(config.connectionString) : new sql2__default.default.ConnectionPool({
3313
+ this.pool = "connectionString" in config ? new sql3__default.default.ConnectionPool(config.connectionString) : new sql3__default.default.ConnectionPool({
2104
3314
  server: config.server,
2105
3315
  database: config.database,
2106
3316
  user: config.user,
@@ -2114,13 +3324,15 @@ var MSSQLStore = class extends storage.MastraStorage {
2114
3324
  const traces = new TracesMSSQL({ pool: this.pool, operations, schema: this.schema });
2115
3325
  const workflows = new WorkflowsMSSQL({ pool: this.pool, operations, schema: this.schema });
2116
3326
  const memory = new MemoryMSSQL({ pool: this.pool, schema: this.schema, operations });
3327
+ const observability = new ObservabilityMSSQL({ pool: this.pool, operations, schema: this.schema });
2117
3328
  this.stores = {
2118
3329
  operations,
2119
3330
  scores,
2120
3331
  traces,
2121
3332
  workflows,
2122
3333
  legacyEvals,
2123
- memory
3334
+ memory,
3335
+ observability
2124
3336
  };
2125
3337
  } catch (e) {
2126
3338
  throw new error.MastraError(
@@ -2140,6 +3352,11 @@ var MSSQLStore = class extends storage.MastraStorage {
2140
3352
  try {
2141
3353
  await this.isConnected;
2142
3354
  await super.init();
3355
+ try {
3356
+ await this.stores.operations.createAutomaticIndexes();
3357
+ } catch (indexError) {
3358
+ this.logger?.warn?.("Failed to create indexes:", indexError);
3359
+ }
2143
3360
  } catch (error$1) {
2144
3361
  this.isConnected = null;
2145
3362
  throw new error.MastraError(
@@ -2166,7 +3383,10 @@ var MSSQLStore = class extends storage.MastraStorage {
2166
3383
  resourceWorkingMemory: true,
2167
3384
  hasColumn: true,
2168
3385
  createTable: true,
2169
- deleteMessages: true
3386
+ deleteMessages: true,
3387
+ getScoresBySpan: true,
3388
+ aiTracing: true,
3389
+ indexManagement: true
2170
3390
  };
2171
3391
  }
2172
3392
  /** @deprecated use getEvals instead */
@@ -2313,15 +3533,8 @@ var MSSQLStore = class extends storage.MastraStorage {
2313
3533
  }) {
2314
3534
  return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
2315
3535
  }
2316
- async getWorkflowRuns({
2317
- workflowName,
2318
- fromDate,
2319
- toDate,
2320
- limit,
2321
- offset,
2322
- resourceId
2323
- } = {}) {
2324
- return this.stores.workflows.getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
3536
+ async getWorkflowRuns(args = {}) {
3537
+ return this.stores.workflows.getWorkflowRuns(args);
2325
3538
  }
2326
3539
  async getWorkflowRunById({
2327
3540
  runId,
@@ -2332,6 +3545,60 @@ var MSSQLStore = class extends storage.MastraStorage {
2332
3545
  async close() {
2333
3546
  await this.pool.close();
2334
3547
  }
3548
+ /**
3549
+ * Index Management
3550
+ */
3551
+ async createIndex(options) {
3552
+ return this.stores.operations.createIndex(options);
3553
+ }
3554
+ async listIndexes(tableName) {
3555
+ return this.stores.operations.listIndexes(tableName);
3556
+ }
3557
+ async describeIndex(indexName) {
3558
+ return this.stores.operations.describeIndex(indexName);
3559
+ }
3560
+ async dropIndex(indexName) {
3561
+ return this.stores.operations.dropIndex(indexName);
3562
+ }
3563
+ /**
3564
+ * AI Tracing / Observability
3565
+ */
3566
+ getObservabilityStore() {
3567
+ if (!this.stores.observability) {
3568
+ throw new error.MastraError({
3569
+ id: "MSSQL_STORE_OBSERVABILITY_NOT_INITIALIZED",
3570
+ domain: error.ErrorDomain.STORAGE,
3571
+ category: error.ErrorCategory.SYSTEM,
3572
+ text: "Observability storage is not initialized"
3573
+ });
3574
+ }
3575
+ return this.stores.observability;
3576
+ }
3577
+ async createAISpan(span) {
3578
+ return this.getObservabilityStore().createAISpan(span);
3579
+ }
3580
+ async updateAISpan({
3581
+ spanId,
3582
+ traceId,
3583
+ updates
3584
+ }) {
3585
+ return this.getObservabilityStore().updateAISpan({ spanId, traceId, updates });
3586
+ }
3587
+ async getAITrace(traceId) {
3588
+ return this.getObservabilityStore().getAITrace(traceId);
3589
+ }
3590
+ async getAITracesPaginated(args) {
3591
+ return this.getObservabilityStore().getAITracesPaginated(args);
3592
+ }
3593
+ async batchCreateAISpans(args) {
3594
+ return this.getObservabilityStore().batchCreateAISpans(args);
3595
+ }
3596
+ async batchUpdateAISpans(args) {
3597
+ return this.getObservabilityStore().batchUpdateAISpans(args);
3598
+ }
3599
+ async batchDeleteAITraces(args) {
3600
+ return this.getObservabilityStore().batchDeleteAITraces(args);
3601
+ }
2335
3602
  /**
2336
3603
  * Scorers
2337
3604
  */
@@ -2340,9 +3607,18 @@ var MSSQLStore = class extends storage.MastraStorage {
2340
3607
  }
2341
3608
  async getScoresByScorerId({
2342
3609
  scorerId: _scorerId,
2343
- pagination: _pagination
3610
+ pagination: _pagination,
3611
+ entityId: _entityId,
3612
+ entityType: _entityType,
3613
+ source: _source
2344
3614
  }) {
2345
- return this.stores.scores.getScoresByScorerId({ scorerId: _scorerId, pagination: _pagination });
3615
+ return this.stores.scores.getScoresByScorerId({
3616
+ scorerId: _scorerId,
3617
+ pagination: _pagination,
3618
+ entityId: _entityId,
3619
+ entityType: _entityType,
3620
+ source: _source
3621
+ });
2346
3622
  }
2347
3623
  async saveScore(_score) {
2348
3624
  return this.stores.scores.saveScore(_score);
@@ -2364,6 +3640,13 @@ var MSSQLStore = class extends storage.MastraStorage {
2364
3640
  pagination: _pagination
2365
3641
  });
2366
3642
  }
3643
+ async getScoresBySpan({
3644
+ traceId,
3645
+ spanId,
3646
+ pagination: _pagination
3647
+ }) {
3648
+ return this.stores.scores.getScoresBySpan({ traceId, spanId, pagination: _pagination });
3649
+ }
2367
3650
  };
2368
3651
 
2369
3652
  exports.MSSQLStore = MSSQLStore;