@mastra/mssql 0.0.0-rag-chunk-extract-llm-option-20250926183645 → 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/dist/index.cjs CHANGED
@@ -3,8 +3,9 @@
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');
8
9
  var scores = require('@mastra/core/scores');
9
10
 
10
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -21,154 +22,71 @@ function getTableName({ indexName, schemaName }) {
21
22
  const quotedSchemaName = schemaName;
22
23
  return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
23
24
  }
24
-
25
- // src/storage/domains/legacy-evals/index.ts
26
- function transformEvalRow(row) {
27
- let testInfoValue = null, resultValue = null;
28
- if (row.test_info) {
29
- try {
30
- testInfoValue = typeof row.test_info === "string" ? JSON.parse(row.test_info) : row.test_info;
31
- } catch {
32
- }
25
+ function buildDateRangeFilter(dateRange, fieldName) {
26
+ const filters = {};
27
+ if (dateRange?.start) {
28
+ filters[`${fieldName}_gte`] = dateRange.start;
33
29
  }
34
- if (row.test_info) {
35
- try {
36
- resultValue = typeof row.result === "string" ? JSON.parse(row.result) : row.result;
37
- } catch {
38
- }
30
+ if (dateRange?.end) {
31
+ filters[`${fieldName}_lte`] = dateRange.end;
39
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
+ });
40
57
  return {
41
- agentName: row.agent_name,
42
- input: row.input,
43
- output: row.output,
44
- result: resultValue,
45
- metricName: row.metric_name,
46
- instructions: row.instructions,
47
- testInfo: testInfoValue,
48
- globalRunId: row.global_run_id,
49
- runId: row.run_id,
50
- createdAt: row.created_at
58
+ sql: conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "",
59
+ params
51
60
  };
52
61
  }
53
- var LegacyEvalsMSSQL = class extends storage.LegacyEvalsStorage {
54
- pool;
55
- schema;
56
- constructor({ pool, schema }) {
57
- super();
58
- this.pool = pool;
59
- this.schema = schema;
60
- }
61
- /** @deprecated use getEvals instead */
62
- async getEvalsByAgentName(agentName, type) {
63
- try {
64
- let query = `SELECT * FROM ${getTableName({ indexName: storage.TABLE_EVALS, schemaName: getSchemaName(this.schema) })} WHERE agent_name = @p1`;
65
- if (type === "test") {
66
- query += " AND test_info IS NOT NULL AND JSON_VALUE(test_info, '$.testPath') IS NOT NULL";
67
- } else if (type === "live") {
68
- query += " AND (test_info IS NULL OR JSON_VALUE(test_info, '$.testPath') IS NULL)";
69
- }
70
- query += " ORDER BY created_at DESC";
71
- const request = this.pool.request();
72
- request.input("p1", agentName);
73
- const result = await request.query(query);
74
- const rows = result.recordset;
75
- return typeof transformEvalRow === "function" ? rows?.map((row) => transformEvalRow(row)) ?? [] : rows ?? [];
76
- } catch (error) {
77
- if (error && error.number === 208 && error.message && error.message.includes("Invalid object name")) {
78
- return [];
79
- }
80
- console.error("Failed to get evals for the specified agent: " + error?.message);
81
- throw error;
82
- }
83
- }
84
- async getEvals(options = {}) {
85
- const { agentName, type, page = 0, perPage = 100, dateRange } = options;
86
- const fromDate = dateRange?.start;
87
- const toDate = dateRange?.end;
88
- const where = [];
89
- const params = {};
90
- if (agentName) {
91
- where.push("agent_name = @agentName");
92
- params["agentName"] = agentName;
93
- }
94
- if (type === "test") {
95
- where.push("test_info IS NOT NULL AND JSON_VALUE(test_info, '$.testPath') IS NOT NULL");
96
- } else if (type === "live") {
97
- where.push("(test_info IS NULL OR JSON_VALUE(test_info, '$.testPath') IS NULL)");
98
- }
99
- if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
100
- where.push(`[created_at] >= @fromDate`);
101
- params[`fromDate`] = fromDate.toISOString();
102
- }
103
- if (toDate instanceof Date && !isNaN(toDate.getTime())) {
104
- where.push(`[created_at] <= @toDate`);
105
- params[`toDate`] = toDate.toISOString();
106
- }
107
- const whereClause = where.length > 0 ? `WHERE ${where.join(" AND ")}` : "";
108
- const tableName = getTableName({ indexName: storage.TABLE_EVALS, schemaName: getSchemaName(this.schema) });
109
- const offset = page * perPage;
110
- const countQuery = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause}`;
111
- const dataQuery = `SELECT * FROM ${tableName} ${whereClause} ORDER BY seq_id DESC OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
112
- try {
113
- const countReq = this.pool.request();
114
- Object.entries(params).forEach(([key, value]) => {
115
- if (value instanceof Date) {
116
- countReq.input(key, sql2__default.default.DateTime, value);
117
- } else {
118
- countReq.input(key, value);
119
- }
120
- });
121
- const countResult = await countReq.query(countQuery);
122
- const total = countResult.recordset[0]?.total || 0;
123
- if (total === 0) {
124
- return {
125
- evals: [],
126
- total: 0,
127
- page,
128
- perPage,
129
- hasMore: false
130
- };
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;
131
75
  }
132
- const req = this.pool.request();
133
- Object.entries(params).forEach(([key, value]) => {
134
- if (value instanceof Date) {
135
- req.input(key, sql2__default.default.DateTime, value);
136
- } else {
137
- req.input(key, value);
138
- }
139
- });
140
- req.input("offset", offset);
141
- req.input("perPage", perPage);
142
- const result = await req.query(dataQuery);
143
- const rows = result.recordset;
144
- return {
145
- evals: rows?.map((row) => transformEvalRow(row)) ?? [],
146
- total,
147
- page,
148
- perPage,
149
- hasMore: offset + (rows?.length ?? 0) < total
150
- };
151
- } catch (error$1) {
152
- const mastraError = new error.MastraError(
153
- {
154
- id: "MASTRA_STORAGE_MSSQL_STORE_GET_EVALS_FAILED",
155
- domain: error.ErrorDomain.STORAGE,
156
- category: error.ErrorCategory.THIRD_PARTY,
157
- details: {
158
- agentName: agentName || "all",
159
- type: type || "all",
160
- page,
161
- perPage
162
- }
163
- },
164
- error$1
165
- );
166
- this.logger?.error?.(mastraError.toString());
167
- this.logger?.trackException(mastraError);
168
- 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;
169
84
  }
170
- }
171
- };
85
+ });
86
+ return result;
87
+ }
88
+
89
+ // src/storage/domains/memory/index.ts
172
90
  var MemoryMSSQL = class extends storage.MemoryStorage {
173
91
  pool;
174
92
  schema;
@@ -200,7 +118,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
200
118
  }
201
119
  async getThreadById({ threadId }) {
202
120
  try {
203
- const sql7 = `SELECT
121
+ const sql5 = `SELECT
204
122
  id,
205
123
  [resourceId],
206
124
  title,
@@ -211,7 +129,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
211
129
  WHERE id = @threadId`;
212
130
  const request = this.pool.request();
213
131
  request.input("threadId", threadId);
214
- const resultSet = await request.query(sql7);
132
+ const resultSet = await request.query(sql5);
215
133
  const thread = resultSet.recordset[0] || null;
216
134
  if (!thread) {
217
135
  return null;
@@ -257,7 +175,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
257
175
  };
258
176
  }
259
177
  const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
260
- const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${sortDirection} OFFSET @offset ROWS FETCH NEXT @perPage ROWS ONLY`;
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`;
261
180
  const dataRequest = this.pool.request();
262
181
  dataRequest.input("resourceId", resourceId);
263
182
  dataRequest.input("perPage", perPage);
@@ -314,7 +233,12 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
314
233
  req.input("id", thread.id);
315
234
  req.input("resourceId", thread.resourceId);
316
235
  req.input("title", thread.title);
317
- req.input("metadata", thread.metadata ? JSON.stringify(thread.metadata) : null);
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
+ }
318
242
  req.input("createdAt", sql2__default.default.DateTime2, thread.createdAt);
319
243
  req.input("updatedAt", sql2__default.default.DateTime2, thread.updatedAt);
320
244
  await req.query(mergeSql);
@@ -341,7 +265,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
341
265
  try {
342
266
  const baseQuery = `FROM ${getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) })} WHERE [resourceId] = @resourceId`;
343
267
  const orderByField = orderBy === "createdAt" ? "[createdAt]" : "[updatedAt]";
344
- const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${sortDirection}`;
268
+ const dir = (sortDirection || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC";
269
+ const dataQuery = `SELECT id, [resourceId], title, metadata, [createdAt], [updatedAt] ${baseQuery} ORDER BY ${orderByField} ${dir}`;
345
270
  const request = this.pool.request();
346
271
  request.input("resourceId", resourceId);
347
272
  const resultSet = await request.query(dataQuery);
@@ -384,7 +309,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
384
309
  };
385
310
  try {
386
311
  const table = getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) });
387
- const sql7 = `UPDATE ${table}
312
+ const sql5 = `UPDATE ${table}
388
313
  SET title = @title,
389
314
  metadata = @metadata,
390
315
  [updatedAt] = @updatedAt
@@ -395,7 +320,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
395
320
  req.input("title", title);
396
321
  req.input("metadata", JSON.stringify(mergedMetadata));
397
322
  req.input("updatedAt", /* @__PURE__ */ new Date());
398
- const result = await req.query(sql7);
323
+ const result = await req.query(sql5);
399
324
  let thread = result.recordset && result.recordset[0];
400
325
  if (thread && "seq_id" in thread) {
401
326
  const { seq_id, ...rest } = thread;
@@ -465,8 +390,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
465
390
  }
466
391
  async _getIncludedMessages({
467
392
  threadId,
468
- selectBy,
469
- orderByStatement
393
+ selectBy
470
394
  }) {
471
395
  if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
472
396
  const include = selectBy?.include;
@@ -494,7 +418,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
494
418
  m.[resourceId],
495
419
  m.seq_id
496
420
  FROM (
497
- SELECT *, ROW_NUMBER() OVER (${orderByStatement}) as row_num
421
+ SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
498
422
  FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
499
423
  WHERE [thread_id] = ${pThreadId}
500
424
  ) AS m
@@ -502,15 +426,17 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
502
426
  OR EXISTS (
503
427
  SELECT 1
504
428
  FROM (
505
- SELECT *, ROW_NUMBER() OVER (${orderByStatement}) as row_num
429
+ SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
506
430
  FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
507
431
  WHERE [thread_id] = ${pThreadId}
508
432
  ) AS target
509
433
  WHERE target.id = ${pId}
510
434
  AND (
511
- (m.row_num <= target.row_num + ${pPrev} AND m.row_num > target.row_num)
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})
512
437
  OR
513
- (m.row_num >= target.row_num - ${pNext} AND m.row_num < target.row_num)
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})
514
440
  )
515
441
  )
516
442
  `
@@ -549,7 +475,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
549
475
  let rows = [];
550
476
  const include = selectBy?.include || [];
551
477
  if (include?.length) {
552
- const includeMessages = await this._getIncludedMessages({ threadId, selectBy, orderByStatement });
478
+ const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
553
479
  if (includeMessages) {
554
480
  rows.push(...includeMessages);
555
481
  }
@@ -590,14 +516,11 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
590
516
  error$1
591
517
  );
592
518
  this.logger?.error?.(mastraError.toString());
593
- this.logger?.trackException(mastraError);
519
+ this.logger?.trackException?.(mastraError);
594
520
  return [];
595
521
  }
596
522
  }
597
- async getMessagesById({
598
- messageIds,
599
- format
600
- }) {
523
+ async listMessagesById({ messageIds }) {
601
524
  if (messageIds.length === 0) return [];
602
525
  const selectStatement = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId`;
603
526
  const orderByStatement = `ORDER BY [seq_id] DESC`;
@@ -615,8 +538,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
615
538
  return timeDiff;
616
539
  });
617
540
  rows = rows.map(({ seq_id, ...rest }) => rest);
618
- if (format === `v1`) return this._parseAndFormatMessages(rows, format);
619
- return this._parseAndFormatMessages(rows, `v2`);
541
+ const messages = this._parseAndFormatMessages(rows, `v2`);
542
+ return messages;
620
543
  } catch (error$1) {
621
544
  const mastraError = new error.MastraError(
622
545
  {
@@ -630,10 +553,139 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
630
553
  error$1
631
554
  );
632
555
  this.logger?.error?.(mastraError.toString());
633
- this.logger?.trackException(mastraError);
556
+ this.logger?.trackException?.(mastraError);
634
557
  return [];
635
558
  }
636
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
+ }
637
689
  async getMessagesPaginated(args) {
638
690
  const { threadId, resourceId, format, selectBy } = args;
639
691
  const { page = 0, perPage: perPageInput, dateRange } = selectBy?.pagination || {};
@@ -645,7 +697,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
645
697
  const orderByStatement = `ORDER BY [seq_id] DESC`;
646
698
  let messages = [];
647
699
  if (selectBy?.include?.length) {
648
- const includeMessages = await this._getIncludedMessages({ threadId, selectBy, orderByStatement });
700
+ const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
649
701
  if (includeMessages) messages.push(...includeMessages);
650
702
  }
651
703
  const perPage = perPageInput !== void 0 ? perPageInput : storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
@@ -692,7 +744,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
692
744
  const parsed = this._parseAndFormatMessages(messages, format);
693
745
  return {
694
746
  messages: parsed,
695
- total: total + excludeIds.length,
747
+ total,
696
748
  page,
697
749
  perPage,
698
750
  hasMore: currentOffset + rows.length < total
@@ -712,7 +764,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
712
764
  error$1
713
765
  );
714
766
  this.logger?.error?.(mastraError.toString());
715
- this.logger?.trackException(mastraError);
767
+ this.logger?.trackException?.(mastraError);
716
768
  return { messages: [], total: 0, page, perPage: perPageInput || 40, hasMore: false };
717
769
  }
718
770
  }
@@ -979,8 +1031,10 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
979
1031
  return null;
980
1032
  }
981
1033
  return {
982
- ...result,
983
- workingMemory: typeof result.workingMemory === "object" ? JSON.stringify(result.workingMemory) : result.workingMemory,
1034
+ id: result.id,
1035
+ createdAt: result.createdAt,
1036
+ updatedAt: result.updatedAt,
1037
+ workingMemory: result.workingMemory,
984
1038
  metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
985
1039
  };
986
1040
  } catch (error$1) {
@@ -994,7 +1048,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
994
1048
  error$1
995
1049
  );
996
1050
  this.logger?.error?.(mastraError.toString());
997
- this.logger?.trackException(mastraError);
1051
+ this.logger?.trackException?.(mastraError);
998
1052
  throw mastraError;
999
1053
  }
1000
1054
  }
@@ -1003,7 +1057,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
1003
1057
  tableName: storage.TABLE_RESOURCES,
1004
1058
  record: {
1005
1059
  ...resource,
1006
- metadata: JSON.stringify(resource.metadata)
1060
+ metadata: resource.metadata
1007
1061
  }
1008
1062
  });
1009
1063
  return resource;
@@ -1061,132 +1115,457 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
1061
1115
  error$1
1062
1116
  );
1063
1117
  this.logger?.error?.(mastraError.toString());
1064
- this.logger?.trackException(mastraError);
1118
+ this.logger?.trackException?.(mastraError);
1065
1119
  throw mastraError;
1066
1120
  }
1067
1121
  }
1068
1122
  };
1069
- var StoreOperationsMSSQL = class extends storage.StoreOperations {
1123
+ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
1070
1124
  pool;
1071
- schemaName;
1072
- setupSchemaPromise = null;
1073
- schemaSetupComplete = void 0;
1074
- getSqlType(type, isPrimaryKey = false) {
1075
- switch (type) {
1076
- case "text":
1077
- return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(MAX)";
1078
- case "timestamp":
1079
- return "DATETIME2(7)";
1080
- case "uuid":
1081
- return "UNIQUEIDENTIFIER";
1082
- case "jsonb":
1083
- return "NVARCHAR(MAX)";
1084
- case "integer":
1085
- return "INT";
1086
- case "bigint":
1087
- return "BIGINT";
1088
- case "float":
1089
- return "FLOAT";
1090
- default:
1091
- throw new error.MastraError({
1092
- id: "MASTRA_STORAGE_MSSQL_STORE_TYPE_NOT_SUPPORTED",
1093
- domain: error.ErrorDomain.STORAGE,
1094
- category: error.ErrorCategory.THIRD_PARTY
1095
- });
1096
- }
1097
- }
1098
- constructor({ pool, schemaName }) {
1125
+ operations;
1126
+ schema;
1127
+ constructor({
1128
+ pool,
1129
+ operations,
1130
+ schema
1131
+ }) {
1099
1132
  super();
1100
1133
  this.pool = pool;
1101
- this.schemaName = schemaName;
1134
+ this.operations = operations;
1135
+ this.schema = schema;
1102
1136
  }
1103
- async hasColumn(table, column) {
1104
- const schema = this.schemaName || "dbo";
1105
- const request = this.pool.request();
1106
- request.input("schema", schema);
1107
- request.input("table", table);
1108
- request.input("column", column);
1109
- request.input("columnLower", column.toLowerCase());
1110
- const result = await request.query(
1111
- `SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND (COLUMN_NAME = @column OR COLUMN_NAME = @columnLower)`
1112
- );
1113
- return result.recordset.length > 0;
1137
+ get aiTracingStrategy() {
1138
+ return {
1139
+ preferred: "batch-with-updates",
1140
+ supported: ["batch-with-updates", "insert-only"]
1141
+ };
1114
1142
  }
1115
- async setupSchema() {
1116
- if (!this.schemaName || this.schemaSetupComplete) {
1117
- return;
1118
- }
1119
- if (!this.setupSchemaPromise) {
1120
- this.setupSchemaPromise = (async () => {
1121
- try {
1122
- const checkRequest = this.pool.request();
1123
- checkRequest.input("schemaName", this.schemaName);
1124
- const checkResult = await checkRequest.query(`
1125
- SELECT 1 AS found FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = @schemaName
1126
- `);
1127
- const schemaExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
1128
- if (!schemaExists) {
1129
- try {
1130
- await this.pool.request().query(`CREATE SCHEMA [${this.schemaName}]`);
1131
- this.logger?.info?.(`Schema "${this.schemaName}" created successfully`);
1132
- } catch (error) {
1133
- this.logger?.error?.(`Failed to create schema "${this.schemaName}"`, { error });
1134
- throw new Error(
1135
- `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.`
1136
- );
1137
- }
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
1138
1165
  }
1139
- this.schemaSetupComplete = true;
1140
- this.logger?.debug?.(`Schema "${this.schemaName}" is ready for use`);
1141
- } catch (error) {
1142
- this.schemaSetupComplete = void 0;
1143
- this.setupSchemaPromise = null;
1144
- throw error;
1145
- } finally {
1146
- this.setupSchemaPromise = null;
1147
- }
1148
- })();
1166
+ },
1167
+ error$1
1168
+ );
1149
1169
  }
1150
- await this.setupSchemaPromise;
1151
1170
  }
1152
- async insert({ tableName, record }) {
1171
+ async getAITrace(traceId) {
1153
1172
  try {
1154
- const columns = Object.keys(record).map((col) => utils.parseSqlIdentifier(col, "column name"));
1155
- const values = Object.values(record);
1156
- const paramNames = values.map((_, i) => `@param${i}`);
1157
- const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${columns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
1158
- const request = this.pool.request();
1159
- values.forEach((value, i) => {
1160
- if (value instanceof Date) {
1161
- request.input(`param${i}`, sql2__default.default.DateTime2, value);
1162
- } else if (typeof value === "object" && value !== null) {
1163
- request.input(`param${i}`, JSON.stringify(value));
1164
- } else {
1165
- request.input(`param${i}`, value);
1166
- }
1173
+ const tableName = getTableName({
1174
+ indexName: storage.TABLE_AI_SPANS,
1175
+ schemaName: getSchemaName(this.schema)
1167
1176
  });
1168
- await request.query(insertSql);
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
+ };
1169
1200
  } catch (error$1) {
1170
1201
  throw new error.MastraError(
1171
1202
  {
1172
- id: "MASTRA_STORAGE_MSSQL_STORE_INSERT_FAILED",
1203
+ id: "MSSQL_STORE_GET_AI_TRACE_FAILED",
1173
1204
  domain: error.ErrorDomain.STORAGE,
1174
- category: error.ErrorCategory.THIRD_PARTY,
1205
+ category: error.ErrorCategory.USER,
1175
1206
  details: {
1176
- tableName
1207
+ traceId
1177
1208
  }
1178
1209
  },
1179
1210
  error$1
1180
1211
  );
1181
1212
  }
1182
1213
  }
1183
- async clearTable({ tableName }) {
1184
- const fullTableName = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
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) });
1185
1564
  try {
1186
1565
  try {
1187
1566
  await this.pool.request().query(`TRUNCATE TABLE ${fullTableName}`);
1188
1567
  } catch (truncateError) {
1189
- if (truncateError.message && truncateError.message.includes("foreign key")) {
1568
+ if (truncateError?.number === 4712) {
1190
1569
  await this.pool.request().query(`DELETE FROM ${fullTableName}`);
1191
1570
  } else {
1192
1571
  throw truncateError;
@@ -1209,9 +1588,11 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1209
1588
  getDefaultValue(type) {
1210
1589
  switch (type) {
1211
1590
  case "timestamp":
1212
- return "DEFAULT SYSDATETIMEOFFSET()";
1591
+ return "DEFAULT SYSUTCDATETIME()";
1213
1592
  case "jsonb":
1214
1593
  return "DEFAULT N'{}'";
1594
+ case "boolean":
1595
+ return "DEFAULT 0";
1215
1596
  default:
1216
1597
  return super.getDefaultValue(type);
1217
1598
  }
@@ -1222,13 +1603,29 @@ var StoreOperationsMSSQL = class extends storage.StoreOperations {
1222
1603
  }) {
1223
1604
  try {
1224
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
+ ];
1225
1621
  const columns = Object.entries(schema).map(([name, def]) => {
1226
1622
  const parsedName = utils.parseSqlIdentifier(name, "column name");
1227
1623
  const constraints = [];
1228
1624
  if (def.primaryKey) constraints.push("PRIMARY KEY");
1229
1625
  if (!def.nullable) constraints.push("NOT NULL");
1230
1626
  const isIndexed = !!def.primaryKey || uniqueConstraintColumns.includes(name);
1231
- return `[${parsedName}] ${this.getSqlType(def.type, isIndexed)} ${constraints.join(" ")}`.trim();
1627
+ const useLargeStorage = largeDataColumns.includes(name);
1628
+ return `[${parsedName}] ${this.getSqlType(def.type, isIndexed, useLargeStorage)} ${constraints.join(" ")}`.trim();
1232
1629
  }).join(",\n");
1233
1630
  if (this.schemaName) {
1234
1631
  await this.setupSchema();
@@ -1315,7 +1712,19 @@ ${columns}
1315
1712
  const columnExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
1316
1713
  if (!columnExists) {
1317
1714
  const columnDef = schema[columnName];
1318
- const sqlType = this.getSqlType(columnDef.type);
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);
1319
1728
  const nullable = columnDef.nullable === false ? "NOT NULL" : "";
1320
1729
  const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
1321
1730
  const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
@@ -1324,120 +1733,660 @@ ${columns}
1324
1733
  this.logger?.debug?.(`Ensured column ${parsedColumnName} exists in table ${fullTableName}`);
1325
1734
  }
1326
1735
  }
1327
- }
1736
+ }
1737
+ } catch (error$1) {
1738
+ throw new error.MastraError(
1739
+ {
1740
+ id: "MASTRA_STORAGE_MSSQL_STORE_ALTER_TABLE_FAILED",
1741
+ domain: error.ErrorDomain.STORAGE,
1742
+ category: error.ErrorCategory.THIRD_PARTY,
1743
+ details: {
1744
+ tableName
1745
+ }
1746
+ },
1747
+ error$1
1748
+ );
1749
+ }
1750
+ }
1751
+ async load({ tableName, keys }) {
1752
+ try {
1753
+ const keyEntries = Object.entries(keys).map(([key, value]) => [utils.parseSqlIdentifier(key, "column name"), value]);
1754
+ const conditions = keyEntries.map(([key], i) => `[${key}] = @param${i}`).join(" AND ");
1755
+ const sql5 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
1756
+ const request = this.pool.request();
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
+ }
1764
+ });
1765
+ const resultSet = await request.query(sql5);
1766
+ const result = resultSet.recordset[0] || null;
1767
+ if (!result) {
1768
+ return null;
1769
+ }
1770
+ if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
1771
+ const snapshot = result;
1772
+ if (typeof snapshot.snapshot === "string") {
1773
+ snapshot.snapshot = JSON.parse(snapshot.snapshot);
1774
+ }
1775
+ return snapshot;
1776
+ }
1777
+ return result;
1778
+ } catch (error$1) {
1779
+ throw new error.MastraError(
1780
+ {
1781
+ id: "MASTRA_STORAGE_MSSQL_STORE_LOAD_FAILED",
1782
+ domain: error.ErrorDomain.STORAGE,
1783
+ category: error.ErrorCategory.THIRD_PARTY,
1784
+ details: {
1785
+ tableName
1786
+ }
1787
+ },
1788
+ error$1
1789
+ );
1790
+ }
1791
+ }
1792
+ async batchInsert({ tableName, records }) {
1793
+ const transaction = this.pool.transaction();
1794
+ try {
1795
+ await transaction.begin();
1796
+ for (const record of records) {
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);
1328
2076
  } catch (error$1) {
1329
2077
  throw new error.MastraError(
1330
2078
  {
1331
- id: "MASTRA_STORAGE_MSSQL_STORE_ALTER_TABLE_FAILED",
2079
+ id: "MASTRA_STORAGE_MSSQL_INDEX_CREATE_FAILED",
1332
2080
  domain: error.ErrorDomain.STORAGE,
1333
2081
  category: error.ErrorCategory.THIRD_PARTY,
1334
2082
  details: {
1335
- tableName
2083
+ indexName: options.name,
2084
+ tableName: options.table
1336
2085
  }
1337
2086
  },
1338
2087
  error$1
1339
2088
  );
1340
2089
  }
1341
2090
  }
1342
- async load({ tableName, keys }) {
2091
+ /**
2092
+ * Drop an existing index
2093
+ */
2094
+ async dropIndex(indexName) {
1343
2095
  try {
1344
- const keyEntries = Object.entries(keys).map(([key, value]) => [utils.parseSqlIdentifier(key, "column name"), value]);
1345
- const conditions = keyEntries.map(([key], i) => `[${key}] = @param${i}`).join(" AND ");
1346
- const values = keyEntries.map(([_, value]) => value);
1347
- const sql7 = `SELECT * FROM ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} WHERE ${conditions}`;
1348
- const request = this.pool.request();
1349
- values.forEach((value, i) => {
1350
- request.input(`param${i}`, value);
1351
- });
1352
- const resultSet = await request.query(sql7);
1353
- const result = resultSet.recordset[0] || null;
1354
- if (!result) {
1355
- return null;
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;
1356
2111
  }
1357
- if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
1358
- const snapshot = result;
1359
- if (typeof snapshot.snapshot === "string") {
1360
- snapshot.snapshot = JSON.parse(snapshot.snapshot);
1361
- }
1362
- return snapshot;
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
+ });
1363
2120
  }
1364
- return result;
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);
1365
2128
  } catch (error$1) {
1366
2129
  throw new error.MastraError(
1367
2130
  {
1368
- id: "MASTRA_STORAGE_MSSQL_STORE_LOAD_FAILED",
2131
+ id: "MASTRA_STORAGE_MSSQL_INDEX_DROP_FAILED",
1369
2132
  domain: error.ErrorDomain.STORAGE,
1370
2133
  category: error.ErrorCategory.THIRD_PARTY,
1371
2134
  details: {
1372
- tableName
2135
+ indexName
1373
2136
  }
1374
2137
  },
1375
2138
  error$1
1376
2139
  );
1377
2140
  }
1378
2141
  }
1379
- async batchInsert({ tableName, records }) {
1380
- const transaction = this.pool.transaction();
2142
+ /**
2143
+ * List indexes for a specific table or all tables
2144
+ */
2145
+ async listIndexes(tableName) {
1381
2146
  try {
1382
- await transaction.begin();
1383
- for (const record of records) {
1384
- await this.insert({ tableName, record });
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
+ `;
1385
2183
  }
1386
- await transaction.commit();
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;
1387
2212
  } catch (error$1) {
1388
- await transaction.rollback();
1389
2213
  throw new error.MastraError(
1390
2214
  {
1391
- id: "MASTRA_STORAGE_MSSQL_STORE_BATCH_INSERT_FAILED",
2215
+ id: "MASTRA_STORAGE_MSSQL_INDEX_LIST_FAILED",
1392
2216
  domain: error.ErrorDomain.STORAGE,
1393
2217
  category: error.ErrorCategory.THIRD_PARTY,
1394
- details: {
1395
- tableName,
1396
- numberOfRecords: records.length
1397
- }
2218
+ details: tableName ? {
2219
+ tableName
2220
+ } : {}
1398
2221
  },
1399
2222
  error$1
1400
2223
  );
1401
2224
  }
1402
2225
  }
1403
- async dropTable({ tableName }) {
2226
+ /**
2227
+ * Get detailed statistics for a specific index
2228
+ */
2229
+ async describeIndex(indexName) {
1404
2230
  try {
1405
- const tableNameWithSchema = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
1406
- await this.pool.request().query(`DROP TABLE IF EXISTS ${tableNameWithSchema}`);
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}"`);
2257
+ }
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
+ };
1407
2285
  } catch (error$1) {
1408
2286
  throw new error.MastraError(
1409
2287
  {
1410
- id: "MASTRA_STORAGE_MSSQL_STORE_DROP_TABLE_FAILED",
2288
+ id: "MASTRA_STORAGE_MSSQL_INDEX_DESCRIBE_FAILED",
1411
2289
  domain: error.ErrorDomain.STORAGE,
1412
2290
  category: error.ErrorCategory.THIRD_PARTY,
1413
2291
  details: {
1414
- tableName
2292
+ indexName
1415
2293
  }
1416
2294
  },
1417
2295
  error$1
1418
2296
  );
1419
2297
  }
1420
2298
  }
1421
- };
1422
- function parseJSON(jsonString) {
1423
- try {
1424
- return JSON.parse(jsonString);
1425
- } catch {
1426
- return jsonString;
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
+ ];
1427
2351
  }
1428
- }
2352
+ /**
2353
+ * Creates automatic indexes for optimal query performance
2354
+ * Uses getAutomaticIndexDefinitions() to determine which indexes to create
2355
+ */
2356
+ async createAutomaticIndexes() {
2357
+ try {
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
+ }
2366
+ } catch (error$1) {
2367
+ throw new error.MastraError(
2368
+ {
2369
+ id: "MASTRA_STORAGE_MSSQL_STORE_CREATE_PERFORMANCE_INDEXES_FAILED",
2370
+ domain: error.ErrorDomain.STORAGE,
2371
+ category: error.ErrorCategory.THIRD_PARTY
2372
+ },
2373
+ error$1
2374
+ );
2375
+ }
2376
+ }
2377
+ };
1429
2378
  function transformScoreRow(row) {
1430
2379
  return {
1431
2380
  ...row,
1432
- input: parseJSON(row.input),
1433
- scorer: parseJSON(row.scorer),
1434
- preprocessStepResult: parseJSON(row.preprocessStepResult),
1435
- analyzeStepResult: parseJSON(row.analyzeStepResult),
1436
- metadata: parseJSON(row.metadata),
1437
- output: parseJSON(row.output),
1438
- additionalContext: parseJSON(row.additionalContext),
1439
- runtimeContext: parseJSON(row.runtimeContext),
1440
- entity: parseJSON(row.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),
1441
2390
  createdAt: row.createdAt,
1442
2391
  updatedAt: row.updatedAt
1443
2392
  };
@@ -1503,7 +2452,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1503
2452
  input,
1504
2453
  output,
1505
2454
  additionalContext,
1506
- runtimeContext,
2455
+ requestContext,
1507
2456
  entity,
1508
2457
  ...rest
1509
2458
  } = validatedScore;
@@ -1512,15 +2461,15 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1512
2461
  record: {
1513
2462
  id: scoreId,
1514
2463
  ...rest,
1515
- input: JSON.stringify(input) || "",
1516
- output: JSON.stringify(output) || "",
1517
- preprocessStepResult: preprocessStepResult ? JSON.stringify(preprocessStepResult) : null,
1518
- analyzeStepResult: analyzeStepResult ? JSON.stringify(analyzeStepResult) : null,
1519
- metadata: metadata ? JSON.stringify(metadata) : null,
1520
- additionalContext: additionalContext ? JSON.stringify(additionalContext) : null,
1521
- runtimeContext: runtimeContext ? JSON.stringify(runtimeContext) : null,
1522
- entity: entity ? JSON.stringify(entity) : null,
1523
- scorer: scorer ? JSON.stringify(scorer) : null,
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,
1524
2473
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1525
2474
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1526
2475
  }
@@ -1540,14 +2489,37 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1540
2489
  }
1541
2490
  async getScoresByScorerId({
1542
2491
  scorerId,
1543
- pagination
2492
+ pagination,
2493
+ entityId,
2494
+ entityType,
2495
+ source
1544
2496
  }) {
1545
2497
  try {
1546
- const request = this.pool.request();
1547
- request.input("p1", scorerId);
1548
- const totalResult = await request.query(
1549
- `SELECT COUNT(*) as count FROM ${getTableName({ indexName: storage.TABLE_SCORERS, schemaName: getSchemaName(this.schema) })} WHERE [scorerId] = @p1`
1550
- );
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}`);
1551
2523
  const total = totalResult.recordset[0]?.count || 0;
1552
2524
  if (total === 0) {
1553
2525
  return {
@@ -1561,12 +2533,13 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1561
2533
  };
1562
2534
  }
1563
2535
  const dataRequest = this.pool.request();
1564
- dataRequest.input("p1", scorerId);
1565
- dataRequest.input("p2", pagination.perPage);
1566
- dataRequest.input("p3", pagination.page * pagination.perPage);
1567
- const result = await dataRequest.query(
1568
- `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`
1569
- );
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);
1570
2543
  return {
1571
2544
  pagination: {
1572
2545
  total: Number(total),
@@ -1746,7 +2719,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
1746
2719
  }
1747
2720
  }
1748
2721
  };
1749
- var TracesMSSQL = class extends storage.TracesStorage {
2722
+ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
1750
2723
  pool;
1751
2724
  operations;
1752
2725
  schema;
@@ -1760,207 +2733,164 @@ var TracesMSSQL = class extends storage.TracesStorage {
1760
2733
  this.operations = operations;
1761
2734
  this.schema = schema;
1762
2735
  }
1763
- /** @deprecated use getTracesPaginated instead*/
1764
- async getTraces(args) {
1765
- if (args.fromDate || args.toDate) {
1766
- args.dateRange = {
1767
- start: args.fromDate,
1768
- end: args.toDate
1769
- };
1770
- }
1771
- const result = await this.getTracesPaginated(args);
1772
- return result.traces;
1773
- }
1774
- async getTracesPaginated(args) {
1775
- const { name, scope, page = 0, perPage: perPageInput, attributes, filters, dateRange } = args;
1776
- const fromDate = dateRange?.start;
1777
- const toDate = dateRange?.end;
1778
- const perPage = perPageInput !== void 0 ? perPageInput : 100;
1779
- const currentOffset = page * perPage;
1780
- const paramMap = {};
1781
- const conditions = [];
1782
- let paramIndex = 1;
1783
- if (name) {
1784
- const paramName = `p${paramIndex++}`;
1785
- conditions.push(`[name] LIKE @${paramName}`);
1786
- paramMap[paramName] = `${name}%`;
1787
- }
1788
- if (scope) {
1789
- const paramName = `p${paramIndex++}`;
1790
- conditions.push(`[scope] = @${paramName}`);
1791
- paramMap[paramName] = scope;
1792
- }
1793
- if (attributes) {
1794
- Object.entries(attributes).forEach(([key, value]) => {
1795
- const parsedKey = utils.parseFieldKey(key);
1796
- const paramName = `p${paramIndex++}`;
1797
- conditions.push(`JSON_VALUE([attributes], '$.${parsedKey}') = @${paramName}`);
1798
- paramMap[paramName] = value;
1799
- });
1800
- }
1801
- if (filters) {
1802
- Object.entries(filters).forEach(([key, value]) => {
1803
- const parsedKey = utils.parseFieldKey(key);
1804
- const paramName = `p${paramIndex++}`;
1805
- conditions.push(`[${parsedKey}] = @${paramName}`);
1806
- paramMap[paramName] = value;
1807
- });
1808
- }
1809
- if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
1810
- const paramName = `p${paramIndex++}`;
1811
- conditions.push(`[createdAt] >= @${paramName}`);
1812
- paramMap[paramName] = fromDate.toISOString();
1813
- }
1814
- if (toDate instanceof Date && !isNaN(toDate.getTime())) {
1815
- const paramName = `p${paramIndex++}`;
1816
- conditions.push(`[createdAt] <= @${paramName}`);
1817
- 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
+ }
1818
2744
  }
1819
- const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1820
- const countQuery = `SELECT COUNT(*) as total FROM ${getTableName({ indexName: storage.TABLE_TRACES, schemaName: getSchemaName(this.schema) })} ${whereClause}`;
1821
- let total = 0;
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();
1822
2763
  try {
1823
- const countRequest = this.pool.request();
1824
- Object.entries(paramMap).forEach(([key, value]) => {
1825
- if (value instanceof Date) {
1826
- countRequest.input(key, sql2__default.default.DateTime, value);
1827
- } else {
1828
- countRequest.input(key, value);
1829
- }
1830
- });
1831
- const countResult = await countRequest.query(countQuery);
1832
- total = parseInt(countResult.recordset[0].total, 10);
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;
1833
2808
  } catch (error$1) {
2809
+ try {
2810
+ await transaction.rollback();
2811
+ } catch {
2812
+ }
1834
2813
  throw new error.MastraError(
1835
2814
  {
1836
- id: "MASTRA_STORAGE_MSSQL_STORE_GET_TRACES_PAGINATED_FAILED_TO_RETRIEVE_TOTAL_COUNT",
2815
+ id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_RESULTS_FAILED",
1837
2816
  domain: error.ErrorDomain.STORAGE,
1838
2817
  category: error.ErrorCategory.THIRD_PARTY,
1839
2818
  details: {
1840
- name: args.name ?? "",
1841
- scope: args.scope ?? ""
2819
+ workflowName,
2820
+ runId,
2821
+ stepId
1842
2822
  }
1843
2823
  },
1844
2824
  error$1
1845
2825
  );
1846
2826
  }
1847
- if (total === 0) {
1848
- return {
1849
- traces: [],
1850
- total: 0,
1851
- page,
1852
- perPage,
1853
- hasMore: false
1854
- };
1855
- }
1856
- 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`;
1857
- const dataRequest = this.pool.request();
1858
- Object.entries(paramMap).forEach(([key, value]) => {
1859
- if (value instanceof Date) {
1860
- dataRequest.input(key, sql2__default.default.DateTime, value);
1861
- } else {
1862
- dataRequest.input(key, value);
1863
- }
1864
- });
1865
- dataRequest.input("offset", currentOffset);
1866
- 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();
1867
2835
  try {
1868
- const rowsResult = await dataRequest.query(dataQuery);
1869
- const rows = rowsResult.recordset;
1870
- const traces = rows.map((row) => ({
1871
- id: row.id,
1872
- parentSpanId: row.parentSpanId,
1873
- traceId: row.traceId,
1874
- name: row.name,
1875
- scope: row.scope,
1876
- kind: row.kind,
1877
- status: JSON.parse(row.status),
1878
- events: JSON.parse(row.events),
1879
- links: JSON.parse(row.links),
1880
- attributes: JSON.parse(row.attributes),
1881
- startTime: row.startTime,
1882
- endTime: row.endTime,
1883
- other: row.other,
1884
- createdAt: row.createdAt
1885
- }));
1886
- return {
1887
- traces,
1888
- total,
1889
- page,
1890
- perPage,
1891
- hasMore: currentOffset + traces.length < total
1892
- };
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;
1893
2875
  } catch (error$1) {
2876
+ try {
2877
+ await transaction.rollback();
2878
+ } catch {
2879
+ }
1894
2880
  throw new error.MastraError(
1895
2881
  {
1896
- id: "MASTRA_STORAGE_MSSQL_STORE_GET_TRACES_PAGINATED_FAILED_TO_RETRIEVE_TRACES",
2882
+ id: "MASTRA_STORAGE_MSSQL_STORE_UPDATE_WORKFLOW_STATE_FAILED",
1897
2883
  domain: error.ErrorDomain.STORAGE,
1898
2884
  category: error.ErrorCategory.THIRD_PARTY,
1899
2885
  details: {
1900
- name: args.name ?? "",
1901
- scope: args.scope ?? ""
2886
+ workflowName,
2887
+ runId
1902
2888
  }
1903
2889
  },
1904
2890
  error$1
1905
2891
  );
1906
2892
  }
1907
2893
  }
1908
- async batchTraceInsert({ records }) {
1909
- this.logger.debug("Batch inserting traces", { count: records.length });
1910
- await this.operations.batchInsert({
1911
- tableName: storage.TABLE_TRACES,
1912
- records
1913
- });
1914
- }
1915
- };
1916
- function parseWorkflowRun(row) {
1917
- let parsedSnapshot = row.snapshot;
1918
- if (typeof parsedSnapshot === "string") {
1919
- try {
1920
- parsedSnapshot = JSON.parse(row.snapshot);
1921
- } catch (e) {
1922
- console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
1923
- }
1924
- }
1925
- return {
1926
- workflowName: row.workflow_name,
1927
- runId: row.run_id,
1928
- snapshot: parsedSnapshot,
1929
- createdAt: row.createdAt,
1930
- updatedAt: row.updatedAt,
1931
- resourceId: row.resourceId
1932
- };
1933
- }
1934
- var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
1935
- pool;
1936
- operations;
1937
- schema;
1938
- constructor({
1939
- pool,
1940
- operations,
1941
- schema
1942
- }) {
1943
- super();
1944
- this.pool = pool;
1945
- this.operations = operations;
1946
- this.schema = schema;
1947
- }
1948
- updateWorkflowResults({
1949
- // workflowName,
1950
- // runId,
1951
- // stepId,
1952
- // result,
1953
- // runtimeContext,
1954
- }) {
1955
- throw new Error("Method not implemented.");
1956
- }
1957
- updateWorkflowState({
1958
- // workflowName,
1959
- // runId,
1960
- // opts,
1961
- }) {
1962
- throw new Error("Method not implemented.");
1963
- }
1964
2894
  async persistWorkflowSnapshot({
1965
2895
  workflowName,
1966
2896
  runId,
@@ -2057,7 +2987,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2057
2987
  if (!result.recordset || result.recordset.length === 0) {
2058
2988
  return null;
2059
2989
  }
2060
- return parseWorkflowRun(result.recordset[0]);
2990
+ return this.parseWorkflowRun(result.recordset[0]);
2061
2991
  } catch (error$1) {
2062
2992
  throw new error.MastraError(
2063
2993
  {
@@ -2073,7 +3003,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2073
3003
  );
2074
3004
  }
2075
3005
  }
2076
- async getWorkflowRuns({
3006
+ async listWorkflowRuns({
2077
3007
  workflowName,
2078
3008
  fromDate,
2079
3009
  toDate,
@@ -2094,7 +3024,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2094
3024
  conditions.push(`[resourceId] = @resourceId`);
2095
3025
  paramMap["resourceId"] = resourceId;
2096
3026
  } else {
2097
- console.warn(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
3027
+ this.logger?.warn?.(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
2098
3028
  }
2099
3029
  }
2100
3030
  if (fromDate instanceof Date && !isNaN(fromDate.getTime())) {
@@ -2128,7 +3058,7 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
2128
3058
  request.input("offset", offset);
2129
3059
  }
2130
3060
  const result = await request.query(query);
2131
- const runs = (result.recordset || []).map((row) => parseWorkflowRun(row));
3061
+ const runs = (result.recordset || []).map((row) => this.parseWorkflowRun(row));
2132
3062
  return { runs, total: total || runs.length };
2133
3063
  } catch (error$1) {
2134
3064
  throw new error.MastraError(
@@ -2176,19 +3106,17 @@ var MSSQLStore = class extends storage.MastraStorage {
2176
3106
  port: config.port,
2177
3107
  options: config.options || { encrypt: true, trustServerCertificate: true }
2178
3108
  });
2179
- const legacyEvals = new LegacyEvalsMSSQL({ pool: this.pool, schema: this.schema });
2180
3109
  const operations = new StoreOperationsMSSQL({ pool: this.pool, schemaName: this.schema });
2181
3110
  const scores = new ScoresMSSQL({ pool: this.pool, operations, schema: this.schema });
2182
- const traces = new TracesMSSQL({ pool: this.pool, operations, schema: this.schema });
2183
3111
  const workflows = new WorkflowsMSSQL({ pool: this.pool, operations, schema: this.schema });
2184
3112
  const memory = new MemoryMSSQL({ pool: this.pool, schema: this.schema, operations });
3113
+ const observability = new ObservabilityMSSQL({ pool: this.pool, operations, schema: this.schema });
2185
3114
  this.stores = {
2186
3115
  operations,
2187
3116
  scores,
2188
- traces,
2189
3117
  workflows,
2190
- legacyEvals,
2191
- memory
3118
+ memory,
3119
+ observability
2192
3120
  };
2193
3121
  } catch (e) {
2194
3122
  throw new error.MastraError(
@@ -2208,6 +3136,11 @@ var MSSQLStore = class extends storage.MastraStorage {
2208
3136
  try {
2209
3137
  await this.isConnected;
2210
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
+ }
2211
3144
  } catch (error$1) {
2212
3145
  this.isConnected = null;
2213
3146
  throw new error.MastraError(
@@ -2235,28 +3168,11 @@ var MSSQLStore = class extends storage.MastraStorage {
2235
3168
  hasColumn: true,
2236
3169
  createTable: true,
2237
3170
  deleteMessages: true,
2238
- getScoresBySpan: true
3171
+ getScoresBySpan: true,
3172
+ aiTracing: true,
3173
+ indexManagement: true
2239
3174
  };
2240
3175
  }
2241
- /** @deprecated use getEvals instead */
2242
- async getEvalsByAgentName(agentName, type) {
2243
- return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
2244
- }
2245
- async getEvals(options = {}) {
2246
- return this.stores.legacyEvals.getEvals(options);
2247
- }
2248
- /**
2249
- * @deprecated use getTracesPaginated instead
2250
- */
2251
- async getTraces(args) {
2252
- return this.stores.traces.getTraces(args);
2253
- }
2254
- async getTracesPaginated(args) {
2255
- return this.stores.traces.getTracesPaginated(args);
2256
- }
2257
- async batchTraceInsert({ records }) {
2258
- return this.stores.traces.batchTraceInsert({ records });
2259
- }
2260
3176
  async createTable({
2261
3177
  tableName,
2262
3178
  schema
@@ -2316,12 +3232,6 @@ var MSSQLStore = class extends storage.MastraStorage {
2316
3232
  async getMessages(args) {
2317
3233
  return this.stores.memory.getMessages(args);
2318
3234
  }
2319
- async getMessagesById({
2320
- messageIds,
2321
- format
2322
- }) {
2323
- return this.stores.memory.getMessagesById({ messageIds, format });
2324
- }
2325
3235
  async getMessagesPaginated(args) {
2326
3236
  return this.stores.memory.getMessagesPaginated(args);
2327
3237
  }
@@ -2357,9 +3267,9 @@ var MSSQLStore = class extends storage.MastraStorage {
2357
3267
  runId,
2358
3268
  stepId,
2359
3269
  result,
2360
- runtimeContext
3270
+ requestContext
2361
3271
  }) {
2362
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
3272
+ return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
2363
3273
  }
2364
3274
  async updateWorkflowState({
2365
3275
  workflowName,
@@ -2382,7 +3292,7 @@ var MSSQLStore = class extends storage.MastraStorage {
2382
3292
  }) {
2383
3293
  return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
2384
3294
  }
2385
- async getWorkflowRuns({
3295
+ async listWorkflowRuns({
2386
3296
  workflowName,
2387
3297
  fromDate,
2388
3298
  toDate,
@@ -2390,7 +3300,7 @@ var MSSQLStore = class extends storage.MastraStorage {
2390
3300
  offset,
2391
3301
  resourceId
2392
3302
  } = {}) {
2393
- return this.stores.workflows.getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
3303
+ return this.stores.workflows.listWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
2394
3304
  }
2395
3305
  async getWorkflowRunById({
2396
3306
  runId,
@@ -2401,6 +3311,60 @@ var MSSQLStore = class extends storage.MastraStorage {
2401
3311
  async close() {
2402
3312
  await this.pool.close();
2403
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
+ }
2404
3368
  /**
2405
3369
  * Scorers
2406
3370
  */
@@ -2409,9 +3373,18 @@ var MSSQLStore = class extends storage.MastraStorage {
2409
3373
  }
2410
3374
  async getScoresByScorerId({
2411
3375
  scorerId: _scorerId,
2412
- pagination: _pagination
3376
+ pagination: _pagination,
3377
+ entityId: _entityId,
3378
+ entityType: _entityType,
3379
+ source: _source
2413
3380
  }) {
2414
- return this.stores.scores.getScoresByScorerId({ scorerId: _scorerId, pagination: _pagination });
3381
+ return this.stores.scores.getScoresByScorerId({
3382
+ scorerId: _scorerId,
3383
+ pagination: _pagination,
3384
+ entityId: _entityId,
3385
+ entityType: _entityType,
3386
+ source: _source
3387
+ });
2415
3388
  }
2416
3389
  async saveScore(_score) {
2417
3390
  return this.stores.scores.saveScore(_score);