@mastra/mssql 1.1.1 → 1.2.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @mastra/mssql
2
2
 
3
+ ## 1.2.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added `requestContext` column to the spans table. Request context data from tracing is now persisted alongside other span data. ([#14020](https://github.com/mastra-ai/mastra/pull/14020))
8
+
9
+ ### Patch Changes
10
+
11
+ - Added resilient column handling to insert and update operations. Unknown columns in records are now silently dropped instead of causing SQL errors, ensuring forward compatibility when newer domain packages add fields that haven't been migrated yet. ([#14021](https://github.com/mastra-ai/mastra/pull/14021))
12
+
13
+ For example, calling `db.insert({ tableName, record: { id: '1', title: 'Hello', futureField: 'value' } })` will silently ignore `futureField` if it doesn't exist in the database table, rather than throwing. The same applies to `update` — unknown fields in the data payload are dropped before building the SQL statement.
14
+
15
+ - Improved semantic recall performance for large message histories. Semantic recall no longer loads entire threads when only the recalled messages are needed, eliminating delays that previously scaled with total message count. (Fixes #11702) ([#14022](https://github.com/mastra-ai/mastra/pull/14022))
16
+
17
+ - Updated dependencies [[`4f71b43`](https://github.com/mastra-ai/mastra/commit/4f71b436a4a6b8839842d8da47b57b84509af56c), [`a070277`](https://github.com/mastra-ai/mastra/commit/a07027766ce195ba74d0783116d894cbab25d44c), [`b628b91`](https://github.com/mastra-ai/mastra/commit/b628b9128b372c0f54214d902b07279f03443900), [`332c014`](https://github.com/mastra-ai/mastra/commit/332c014e076b81edf7fe45b58205882726415e90), [`6b63153`](https://github.com/mastra-ai/mastra/commit/6b63153878ea841c0f4ce632ba66bb33e57e9c1b), [`4246e34`](https://github.com/mastra-ai/mastra/commit/4246e34cec9c26636d0965942268e6d07c346671), [`b8837ee`](https://github.com/mastra-ai/mastra/commit/b8837ee77e2e84197609762bfabd8b3da326d30c), [`5d950f7`](https://github.com/mastra-ai/mastra/commit/5d950f7bf426a215a1808f0abef7de5c8336ba1c), [`28c85b1`](https://github.com/mastra-ai/mastra/commit/28c85b184fc32b40f7f160483c982da6d388ecbd), [`e9a08fb`](https://github.com/mastra-ai/mastra/commit/e9a08fbef1ada7e50e961e2f54f55e8c10b4a45c), [`631ffd8`](https://github.com/mastra-ai/mastra/commit/631ffd82fed108648b448b28e6a90e38c5f53bf5), [`aae2295`](https://github.com/mastra-ai/mastra/commit/aae2295838a2d329ad6640829e87934790ffe5b8), [`aa61f29`](https://github.com/mastra-ai/mastra/commit/aa61f29ff8095ce46a4ae16e46c4d8c79b2b685b), [`7ff3714`](https://github.com/mastra-ai/mastra/commit/7ff37148515439bb3be009a60e02c3e363299760), [`41d79a1`](https://github.com/mastra-ai/mastra/commit/41d79a14bd8cb6de1e2565fd0a04786bae2f211b), [`e673376`](https://github.com/mastra-ai/mastra/commit/e6733763ad1321aa7e5ae15096b9c2104f93b1f3), [`b2204c9`](https://github.com/mastra-ai/mastra/commit/b2204c98a42848bbfb6f0440f005dc2b6354f1cd), [`a1bf1e3`](https://github.com/mastra-ai/mastra/commit/a1bf1e385ed4c0ef6f11b56c5887442970d127f2), [`b6f647a`](https://github.com/mastra-ai/mastra/commit/b6f647ae2388e091f366581595feb957e37d5b40), [`0c57b8b`](https://github.com/mastra-ai/mastra/commit/0c57b8b0a69a97b5a4ae3f79be6c610f29f3cf7b), [`b081f27`](https://github.com/mastra-ai/mastra/commit/b081f272cf411716e1d6bd72ceac4bcee2657b19), [`0c09eac`](https://github.com/mastra-ai/mastra/commit/0c09eacb1926f64cfdc9ae5c6d63385cf8c9f72c), [`6b9b93d`](https://github.com/mastra-ai/mastra/commit/6b9b93d6f459d1ba6e36f163abf62a085ddb3d64), [`31b6067`](https://github.com/mastra-ai/mastra/commit/31b6067d0cc3ab10e1b29c36147f3b5266bc714a), [`797ac42`](https://github.com/mastra-ai/mastra/commit/797ac4276de231ad2d694d9aeca75980f6cd0419), [`0bc289e`](https://github.com/mastra-ai/mastra/commit/0bc289e2d476bf46c5b91c21969e8d0c6864691c), [`9b75a06`](https://github.com/mastra-ai/mastra/commit/9b75a06e53ebb0b950ba7c1e83a0142047185f46), [`4c3a1b1`](https://github.com/mastra-ai/mastra/commit/4c3a1b122ea083e003d71092f30f3b31680b01c0), [`85cc3b3`](https://github.com/mastra-ai/mastra/commit/85cc3b3b6f32ae4b083c26498f50d5b250ba944b), [`97ea28c`](https://github.com/mastra-ai/mastra/commit/97ea28c746e9e4147d56047bbb1c4a92417a3fec), [`d567299`](https://github.com/mastra-ai/mastra/commit/d567299cf81e02bd9d5221d4bc05967d6c224161), [`716ffe6`](https://github.com/mastra-ai/mastra/commit/716ffe68bed81f7c2690bc8581b9e140f7bf1c3d), [`8296332`](https://github.com/mastra-ai/mastra/commit/8296332de21c16e3dfc3d0b2d615720a6dc88f2f), [`4df2116`](https://github.com/mastra-ai/mastra/commit/4df211619dd922c047d396ca41cd7027c8c4c8e7), [`2219c1a`](https://github.com/mastra-ai/mastra/commit/2219c1acbd21da116da877f0036ffb985a9dd5a3), [`17c4145`](https://github.com/mastra-ai/mastra/commit/17c4145166099354545582335b5252bdfdfd908b)]:
18
+ - @mastra/core@1.11.0-alpha.0
19
+
3
20
  ## 1.1.1
4
21
 
5
22
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-mssql
3
3
  description: Documentation for @mastra/mssql. Use when working with @mastra/mssql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/mssql"
6
- version: "1.1.1"
6
+ version: "1.2.0-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.1",
2
+ "version": "1.2.0-alpha.0",
3
3
  "package": "@mastra/mssql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -41,9 +41,9 @@ const storage = new MSSQLStore({
41
41
 
42
42
  ## Parameters
43
43
 
44
- **connectionString:** (`string`): MSSQL connection string (e.g., Server=localhost,1433;Database=mydb;User Id=sa;Password=password;Encrypt=true;TrustServerCertificate=true)
44
+ **connectionString** (`string`): MSSQL connection string (e.g., Server=localhost,1433;Database=mydb;User Id=sa;Password=password;Encrypt=true;TrustServerCertificate=true)
45
45
 
46
- **schemaName?:** (`string`): The name of the schema you want the storage to use. Will use the default schema if not provided.
46
+ **schemaName** (`string`): The name of the schema you want the storage to use. Will use the default schema if not provided.
47
47
 
48
48
  ## Constructor Examples
49
49
 
@@ -138,7 +138,7 @@ const memoryStore = await storage.getStore('memory')
138
138
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
139
139
  ```
140
140
 
141
- > **Warning:** If `init()` is not called, tables won't be created and storage operations will fail silently or throw errors.
141
+ > **Warning:** If `init()` isn't called, tables won't be created and storage operations will fail silently or throw errors.
142
142
 
143
143
  ### Direct Database and Pool Access
144
144
 
package/dist/index.cjs CHANGED
@@ -58,6 +58,8 @@ var MssqlDB = class extends base.MastraBase {
58
58
  skipDefaultIndexes;
59
59
  setupSchemaPromise = null;
60
60
  schemaSetupComplete = void 0;
61
+ /** Cache of actual table columns: tableName -> Set<columnName> */
62
+ tableColumnsCache = /* @__PURE__ */ new Map();
61
63
  /**
62
64
  * Columns that participate in composite indexes need smaller sizes (NVARCHAR(100)).
63
65
  * MSSQL has a 900-byte index key limit, so composite indexes with NVARCHAR(400) columns fail.
@@ -142,6 +144,41 @@ var MssqlDB = class extends base.MastraBase {
142
144
  this.schemaName = schemaName;
143
145
  this.skipDefaultIndexes = skipDefaultIndexes;
144
146
  }
147
+ /**
148
+ * Gets the set of column names that actually exist in the database table.
149
+ * Results are cached; the cache is invalidated when alterTable() adds new columns.
150
+ */
151
+ async getTableColumns(tableName) {
152
+ const cached = this.tableColumnsCache.get(tableName);
153
+ if (cached) return cached;
154
+ const schema = this.schemaName || "dbo";
155
+ const request = this.pool.request();
156
+ request.input("schema", schema);
157
+ request.input("tableName", tableName);
158
+ const result = await request.query(
159
+ `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @tableName`
160
+ );
161
+ const columns = new Set((result.recordset || []).map((r) => r.COLUMN_NAME));
162
+ if (columns.size > 0) {
163
+ this.tableColumnsCache.set(tableName, columns);
164
+ }
165
+ return columns;
166
+ }
167
+ /**
168
+ * Filters a record to only include columns that exist in the actual database table.
169
+ * Unknown columns are silently dropped to ensure forward compatibility.
170
+ */
171
+ async filterRecordToKnownColumns(tableName, record) {
172
+ const knownColumns = await this.getTableColumns(tableName);
173
+ if (knownColumns.size === 0) return record;
174
+ const filtered = {};
175
+ for (const [key, value] of Object.entries(record)) {
176
+ if (knownColumns.has(key)) {
177
+ filtered[key] = value;
178
+ }
179
+ }
180
+ return filtered;
181
+ }
145
182
  async hasColumn(table, column) {
146
183
  const schema = this.schemaName || "dbo";
147
184
  const request = this.pool.request();
@@ -197,13 +234,15 @@ var MssqlDB = class extends base.MastraBase {
197
234
  transaction
198
235
  }) {
199
236
  try {
200
- const columns = Object.keys(record);
237
+ const filteredRecord = await this.filterRecordToKnownColumns(tableName, record);
238
+ const columns = Object.keys(filteredRecord);
239
+ if (columns.length === 0) return;
201
240
  const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
202
241
  const paramNames = columns.map((_, i) => `@param${i}`);
203
242
  const insertSql = `INSERT INTO ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} (${parsedColumns.map((c) => `[${c}]`).join(", ")}) VALUES (${paramNames.join(", ")})`;
204
243
  const request = transaction ? transaction.request() : this.pool.request();
205
244
  columns.forEach((col, i) => {
206
- const value = record[col];
245
+ const value = filteredRecord[col];
207
246
  const preparedValue = this.prepareValue(value, col, tableName);
208
247
  if (preparedValue instanceof Date) {
209
248
  request.input(`param${i}`, sql__default.default.DateTime2, preparedValue);
@@ -394,6 +433,8 @@ Note: This migration may take some time for large tables.
394
433
  },
395
434
  error$1
396
435
  );
436
+ } finally {
437
+ this.tableColumnsCache.delete(tableName);
397
438
  }
398
439
  }
399
440
  /**
@@ -621,6 +662,8 @@ Note: This migration may take some time for large tables.
621
662
  },
622
663
  error$1
623
664
  );
665
+ } finally {
666
+ this.tableColumnsCache.delete(tableName);
624
667
  }
625
668
  }
626
669
  async load({ tableName, keys }) {
@@ -704,6 +747,8 @@ Note: This migration may take some time for large tables.
704
747
  },
705
748
  error$1
706
749
  );
750
+ } finally {
751
+ this.tableColumnsCache.delete(tableName);
707
752
  }
708
753
  }
709
754
  /**
@@ -795,10 +840,12 @@ Note: This migration may take some time for large tables.
795
840
  text: "Cannot update without keys to identify records"
796
841
  });
797
842
  }
843
+ const filteredData = await this.filterRecordToKnownColumns(tableName, data);
844
+ if (Object.keys(filteredData).length === 0) return;
798
845
  const setClauses = [];
799
846
  const request = transaction ? transaction.request() : this.pool.request();
800
847
  let paramIndex = 0;
801
- Object.entries(data).forEach(([key, value]) => {
848
+ Object.entries(filteredData).forEach(([key, value]) => {
802
849
  const parsedKey = utils.parseSqlIdentifier(key, "column name");
803
850
  const paramName = `set${paramIndex++}`;
804
851
  setClauses.push(`[${parsedKey}] = @${paramName}`);
@@ -1734,6 +1781,18 @@ var MemoryMSSQL = class _MemoryMSSQL extends storage.MemoryStorage {
1734
1781
  );
1735
1782
  }
1736
1783
  }
1784
+ _sortMessages(messages, field, direction) {
1785
+ const mult = direction === "ASC" ? 1 : -1;
1786
+ return messages.sort((a, b) => {
1787
+ const aVal = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1788
+ const bVal = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1789
+ if (aVal == null || bVal == null) {
1790
+ return aVal == null && bVal == null ? a.id.localeCompare(b.id) : aVal == null ? 1 : -1;
1791
+ }
1792
+ const diff = (typeof aVal === "number" && typeof bVal === "number" ? aVal - bVal : String(aVal).localeCompare(String(bVal))) * mult;
1793
+ return diff !== 0 ? diff : a.id.localeCompare(b.id);
1794
+ });
1795
+ }
1737
1796
  async _getIncludedMessages({ include }) {
1738
1797
  if (!include || include.length === 0) return null;
1739
1798
  const unionQueries = [];
@@ -1895,6 +1954,20 @@ var MemoryMSSQL = class _MemoryMSSQL extends storage.MemoryStorage {
1895
1954
  const bindWhereParams = (req) => {
1896
1955
  Object.entries(whereParams).forEach(([paramName, paramValue]) => req.input(paramName, paramValue));
1897
1956
  };
1957
+ if (perPage === 0 && (!include || include.length === 0)) {
1958
+ return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
1959
+ }
1960
+ if (perPage === 0 && include && include.length > 0) {
1961
+ const includeMessages = await this._getIncludedMessages({ include });
1962
+ const messages2 = this._parseAndFormatMessages(includeMessages ?? [], "v2");
1963
+ return {
1964
+ messages: this._sortMessages(messages2, field, direction),
1965
+ total: 0,
1966
+ page,
1967
+ perPage: perPageForResponse,
1968
+ hasMore: false
1969
+ };
1970
+ }
1898
1971
  const countRequest = this.pool.request();
1899
1972
  bindWhereParams(countRequest);
1900
1973
  const countResult = await countRequest.query(`SELECT COUNT(*) as total FROM ${tableName}${actualWhereClause}`);
@@ -2360,6 +2433,11 @@ var ObservabilityMSSQL = class _ObservabilityMSSQL extends storage.Observability
2360
2433
  this.needsConnect = false;
2361
2434
  }
2362
2435
  await this.db.createTable({ tableName: storage.TABLE_SPANS, schema: storage.SPAN_SCHEMA });
2436
+ await this.db.alterTable({
2437
+ tableName: storage.TABLE_SPANS,
2438
+ schema: storage.SPAN_SCHEMA,
2439
+ ifNotExists: ["requestContext"]
2440
+ });
2363
2441
  await this.createDefaultIndexes();
2364
2442
  await this.createCustomIndexes();
2365
2443
  }
@@ -2672,7 +2750,8 @@ var ObservabilityMSSQL = class _ObservabilityMSSQL extends storage.Observability
2672
2750
  }
2673
2751
  async listTraces(args) {
2674
2752
  const { filters, pagination, orderBy } = storage.listTracesArgsSchema.parse(args);
2675
- const { page, perPage } = pagination;
2753
+ const page = pagination?.page ?? 0;
2754
+ const perPage = pagination?.perPage ?? 10;
2676
2755
  const tableName = getTableName2({
2677
2756
  indexName: storage.TABLE_SPANS,
2678
2757
  schemaName: getSchemaName2(this.schema)
@@ -2837,8 +2916,8 @@ var ObservabilityMSSQL = class _ObservabilityMSSQL extends storage.Observability
2837
2916
  }
2838
2917
  }
2839
2918
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2840
- const sortField = orderBy.field;
2841
- const sortDirection = orderBy.direction;
2919
+ const sortField = orderBy?.field ?? "startedAt";
2920
+ const sortDirection = orderBy?.direction ?? "DESC";
2842
2921
  const countRequest = this.pool.request();
2843
2922
  Object.entries(params).forEach(([key, value]) => {
2844
2923
  countRequest.input(key, value);