@mastra/mssql 1.0.0-beta.2 → 1.0.0-beta.3

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,30 @@
1
1
  # @mastra/mssql
2
2
 
3
+ ## 1.0.0-beta.3
4
+
5
+ ### Patch Changes
6
+
7
+ - feat(storage): support querying messages from multiple threads ([#10663](https://github.com/mastra-ai/mastra/pull/10663))
8
+ - Fixed TypeScript errors where `threadId: string | string[]` was being passed to places expecting `Scalar` type
9
+ - Added proper multi-thread support for `listMessages` across all adapters when `threadId` is an array
10
+ - Updated `_getIncludedMessages` to look up message threadId by ID (since message IDs are globally unique)
11
+ - **upstash**: Added `msg-idx:{messageId}` index for O(1) message lookups (backwards compatible with fallback to scan for old messages, with automatic backfill)
12
+
13
+ - fix: ensure score responses match saved payloads for Mastra Stores. ([#10557](https://github.com/mastra-ai/mastra/pull/10557))
14
+
15
+ - Unify transformScoreRow functions across storage adapters ([#10648](https://github.com/mastra-ai/mastra/pull/10648))
16
+
17
+ Added a unified `transformScoreRow` function in `@mastra/core/storage` that provides schema-driven row transformation for score data. This eliminates code duplication across 10 storage adapters while maintaining store-specific behavior through configurable options:
18
+ - `preferredTimestampFields`: Preferred source fields for timestamps (PostgreSQL, Cloudflare D1)
19
+ - `convertTimestamps`: Convert timestamp strings to Date objects (MSSQL, MongoDB, ClickHouse)
20
+ - `nullValuePattern`: Skip values matching pattern (ClickHouse's `'_null_'`)
21
+ - `fieldMappings`: Map source column names to schema fields (LibSQL's `additionalLLMContext`)
22
+
23
+ Each store adapter now uses the unified function with appropriate options, reducing ~200 lines of duplicate transformation logic while ensuring consistent behavior across all storage backends.
24
+
25
+ - Updated dependencies [[`ac0d2f4`](https://github.com/mastra-ai/mastra/commit/ac0d2f4ff8831f72c1c66c2be809706d17f65789), [`1a0d3fc`](https://github.com/mastra-ai/mastra/commit/1a0d3fc811482c9c376cdf79ee615c23bae9b2d6), [`85a628b`](https://github.com/mastra-ai/mastra/commit/85a628b1224a8f64cd82ea7f033774bf22df7a7e), [`c237233`](https://github.com/mastra-ai/mastra/commit/c23723399ccedf7f5744b3f40997b79246bfbe64), [`15f9e21`](https://github.com/mastra-ai/mastra/commit/15f9e216177201ea6e3f6d0bfb063fcc0953444f), [`ff94dea`](https://github.com/mastra-ai/mastra/commit/ff94dea935f4e34545c63bcb6c29804732698809), [`5b2ff46`](https://github.com/mastra-ai/mastra/commit/5b2ff4651df70c146523a7fca773f8eb0a2272f8), [`db41688`](https://github.com/mastra-ai/mastra/commit/db4168806d007417e2e60b4f68656dca4e5f40c9), [`5ca599d`](https://github.com/mastra-ai/mastra/commit/5ca599d0bb59a1595f19f58473fcd67cc71cef58), [`bff1145`](https://github.com/mastra-ai/mastra/commit/bff114556b3cbadad9b2768488708f8ad0e91475), [`5c8ca24`](https://github.com/mastra-ai/mastra/commit/5c8ca247094e0cc2cdbd7137822fb47241f86e77), [`e191844`](https://github.com/mastra-ai/mastra/commit/e1918444ca3f80e82feef1dad506cd4ec6e2875f), [`22553f1`](https://github.com/mastra-ai/mastra/commit/22553f11c63ee5e966a9c034a349822249584691), [`7237163`](https://github.com/mastra-ai/mastra/commit/72371635dbf96a87df4b073cc48fc655afbdce3d), [`2500740`](https://github.com/mastra-ai/mastra/commit/2500740ea23da067d6e50ec71c625ab3ce275e64), [`873ecbb`](https://github.com/mastra-ai/mastra/commit/873ecbb517586aa17d2f1e99283755b3ebb2863f), [`4f9bbe5`](https://github.com/mastra-ai/mastra/commit/4f9bbe5968f42c86f4930b8193de3c3c17e5bd36), [`02e51fe`](https://github.com/mastra-ai/mastra/commit/02e51feddb3d4155cfbcc42624fd0d0970d032c0), [`8f3fa3a`](https://github.com/mastra-ai/mastra/commit/8f3fa3a652bb77da092f913ec51ae46e3a7e27dc), [`cd29ad2`](https://github.com/mastra-ai/mastra/commit/cd29ad23a255534e8191f249593849ed29160886), [`bdf4d8c`](https://github.com/mastra-ai/mastra/commit/bdf4d8cdc656d8a2c21d81834bfa3bfa70f56c16), [`854e3da`](https://github.com/mastra-ai/mastra/commit/854e3dad5daac17a91a20986399d3a51f54bf68b), [`ce18d38`](https://github.com/mastra-ai/mastra/commit/ce18d38678c65870350d123955014a8432075fd9), [`cccf9c8`](https://github.com/mastra-ai/mastra/commit/cccf9c8b2d2dfc1a5e63919395b83d78c89682a0), [`61a5705`](https://github.com/mastra-ai/mastra/commit/61a570551278b6743e64243b3ce7d73de915ca8a), [`db70a48`](https://github.com/mastra-ai/mastra/commit/db70a48aeeeeb8e5f92007e8ede52c364ce15287), [`f0fdc14`](https://github.com/mastra-ai/mastra/commit/f0fdc14ee233d619266b3d2bbdeea7d25cfc6d13), [`db18bc9`](https://github.com/mastra-ai/mastra/commit/db18bc9c3825e2c1a0ad9a183cc9935f6691bfa1), [`9b37b56`](https://github.com/mastra-ai/mastra/commit/9b37b565e1f2a76c24f728945cc740c2b09be9da), [`41a23c3`](https://github.com/mastra-ai/mastra/commit/41a23c32f9877d71810f37e24930515df2ff7a0f), [`5d171ad`](https://github.com/mastra-ai/mastra/commit/5d171ad9ef340387276b77c2bb3e83e83332d729), [`f03ae60`](https://github.com/mastra-ai/mastra/commit/f03ae60500fe350c9d828621006cdafe1975fdd8), [`d1e74a0`](https://github.com/mastra-ai/mastra/commit/d1e74a0a293866dece31022047f5dbab65a304d0), [`39e7869`](https://github.com/mastra-ai/mastra/commit/39e7869bc7d0ee391077ce291474d8a84eedccff), [`5761926`](https://github.com/mastra-ai/mastra/commit/57619260c4a2cdd598763abbacd90de594c6bc76), [`c900fdd`](https://github.com/mastra-ai/mastra/commit/c900fdd504c41348efdffb205cfe80d48c38fa33), [`604a79f`](https://github.com/mastra-ai/mastra/commit/604a79fecf276e26a54a3fe01bb94e65315d2e0e), [`887f0b4`](https://github.com/mastra-ai/mastra/commit/887f0b4746cdbd7cb7d6b17ac9f82aeb58037ea5), [`2562143`](https://github.com/mastra-ai/mastra/commit/256214336b4faa78646c9c1776612393790d8784), [`ef11a61`](https://github.com/mastra-ai/mastra/commit/ef11a61920fa0ed08a5b7ceedd192875af119749)]:
26
+ - @mastra/core@1.0.0-beta.6
27
+
3
28
  ## 1.0.0-beta.2
4
29
 
5
30
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -32,24 +32,62 @@ function buildDateRangeFilter(dateRange, fieldName) {
32
32
  }
33
33
  return filters;
34
34
  }
35
+ function isInOperator(value) {
36
+ return typeof value === "object" && value !== null && "$in" in value && Array.isArray(value.$in);
37
+ }
35
38
  function prepareWhereClause(filters, _schema) {
36
39
  const conditions = [];
37
40
  const params = {};
38
41
  let paramIndex = 1;
39
42
  Object.entries(filters).forEach(([key, value]) => {
40
43
  if (value === void 0) return;
41
- const paramName = `p${paramIndex++}`;
42
44
  if (key.endsWith("_gte")) {
45
+ const paramName = `p${paramIndex++}`;
43
46
  const fieldName = key.slice(0, -4);
44
47
  conditions.push(`[${utils.parseSqlIdentifier(fieldName, "field name")}] >= @${paramName}`);
45
48
  params[paramName] = value instanceof Date ? value.toISOString() : value;
46
49
  } else if (key.endsWith("_lte")) {
50
+ const paramName = `p${paramIndex++}`;
47
51
  const fieldName = key.slice(0, -4);
48
52
  conditions.push(`[${utils.parseSqlIdentifier(fieldName, "field name")}] <= @${paramName}`);
49
53
  params[paramName] = value instanceof Date ? value.toISOString() : value;
50
54
  } else if (value === null) {
51
55
  conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IS NULL`);
56
+ } else if (isInOperator(value)) {
57
+ const inValues = value.$in;
58
+ if (inValues.length === 0) {
59
+ conditions.push("1 = 0");
60
+ } else if (inValues.length === 1) {
61
+ const paramName = `p${paramIndex++}`;
62
+ conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
63
+ params[paramName] = inValues[0] instanceof Date ? inValues[0].toISOString() : inValues[0];
64
+ } else {
65
+ const inParamNames = [];
66
+ for (const item of inValues) {
67
+ const paramName = `p${paramIndex++}`;
68
+ inParamNames.push(`@${paramName}`);
69
+ params[paramName] = item instanceof Date ? item.toISOString() : item;
70
+ }
71
+ conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IN (${inParamNames.join(", ")})`);
72
+ }
73
+ } else if (Array.isArray(value)) {
74
+ if (value.length === 0) {
75
+ conditions.push("1 = 0");
76
+ } else if (value.length === 1) {
77
+ const paramName = `p${paramIndex++}`;
78
+ conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
79
+ params[paramName] = value[0] instanceof Date ? value[0].toISOString() : value[0];
80
+ } else {
81
+ const inParamNames = [];
82
+ for (const item of value) {
83
+ const paramName = `p${paramIndex++}`;
84
+ inParamNames.push(`@${paramName}`);
85
+ params[paramName] = item instanceof Date ? item.toISOString() : item;
86
+ }
87
+ conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] IN (${inParamNames.join(", ")})`);
88
+ }
52
89
  } else {
90
+ const paramName = `p${paramIndex++}`;
53
91
  conditions.push(`[${utils.parseSqlIdentifier(key, "field name")}] = @${paramName}`);
54
92
  params[paramName] = value instanceof Date ? value.toISOString() : value;
55
93
  }
@@ -387,23 +425,18 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
387
425
  );
388
426
  }
389
427
  }
390
- async _getIncludedMessages({
391
- threadId,
392
- include
393
- }) {
394
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
395
- if (!include) return null;
428
+ async _getIncludedMessages({ include }) {
429
+ if (!include || include.length === 0) return null;
396
430
  const unionQueries = [];
397
431
  const paramValues = [];
398
432
  let paramIdx = 1;
399
433
  const paramNames = [];
434
+ const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
400
435
  for (const inc of include) {
401
436
  const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
402
- const searchId = inc.threadId || threadId;
403
- const pThreadId = `@p${paramIdx}`;
404
- const pId = `@p${paramIdx + 1}`;
405
- const pPrev = `@p${paramIdx + 2}`;
406
- const pNext = `@p${paramIdx + 3}`;
437
+ const pId = `@p${paramIdx}`;
438
+ const pPrev = `@p${paramIdx + 1}`;
439
+ const pNext = `@p${paramIdx + 2}`;
407
440
  unionQueries.push(
408
441
  `
409
442
  SELECT
@@ -417,16 +450,16 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
417
450
  m.seq_id
418
451
  FROM (
419
452
  SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
420
- FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
421
- WHERE [thread_id] = ${pThreadId}
453
+ FROM ${tableName}
454
+ WHERE [thread_id] = (SELECT thread_id FROM ${tableName} WHERE id = ${pId})
422
455
  ) AS m
423
456
  WHERE m.id = ${pId}
424
457
  OR EXISTS (
425
458
  SELECT 1
426
459
  FROM (
427
460
  SELECT *, ROW_NUMBER() OVER (ORDER BY [createdAt] ASC) as row_num
428
- FROM ${getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) })}
429
- WHERE [thread_id] = ${pThreadId}
461
+ FROM ${tableName}
462
+ WHERE [thread_id] = (SELECT thread_id FROM ${tableName} WHERE id = ${pId})
430
463
  ) AS target
431
464
  WHERE target.id = ${pId}
432
465
  AND (
@@ -439,9 +472,9 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
439
472
  )
440
473
  `
441
474
  );
442
- paramValues.push(searchId, id, withPreviousMessages, withNextMessages);
443
- paramNames.push(`p${paramIdx}`, `p${paramIdx + 1}`, `p${paramIdx + 2}`, `p${paramIdx + 3}`);
444
- paramIdx += 4;
475
+ paramValues.push(id, withPreviousMessages, withNextMessages);
476
+ paramNames.push(`p${paramIdx}`, `p${paramIdx + 1}`, `p${paramIdx + 2}`);
477
+ paramIdx += 3;
445
478
  }
446
479
  const finalQuery = `
447
480
  SELECT * FROM (
@@ -512,15 +545,16 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
512
545
  }
513
546
  async listMessages(args) {
514
547
  const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
515
- if (!threadId.trim()) {
548
+ const threadIds = Array.isArray(threadId) ? threadId : [threadId];
549
+ if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
516
550
  throw new error.MastraError(
517
551
  {
518
552
  id: "STORAGE_MSSQL_LIST_MESSAGES_INVALID_THREAD_ID",
519
553
  domain: error.ErrorDomain.STORAGE,
520
554
  category: error.ErrorCategory.THIRD_PARTY,
521
- details: { threadId }
555
+ details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
522
556
  },
523
- new Error("threadId must be a non-empty string")
557
+ new Error("threadId must be a non-empty string or array of non-empty strings")
524
558
  );
525
559
  }
526
560
  if (page < 0) {
@@ -530,7 +564,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
530
564
  category: error.ErrorCategory.USER,
531
565
  text: "Page number must be non-negative",
532
566
  details: {
533
- threadId,
567
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
534
568
  page
535
569
  }
536
570
  });
@@ -543,7 +577,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
543
577
  const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
544
578
  const baseQuery = `SELECT seq_id, id, content, role, type, [createdAt], thread_id AS threadId, resourceId FROM ${tableName}`;
545
579
  const filters = {
546
- thread_id: threadId,
580
+ thread_id: threadIds.length === 1 ? threadIds[0] : { $in: threadIds },
547
581
  ...resourceId ? { resourceId } : {},
548
582
  ...buildDateRangeFilter(filter?.dateRange, "createdAt")
549
583
  };
@@ -587,7 +621,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
587
621
  }
588
622
  if (include?.length) {
589
623
  const messageIds = new Set(messages.map((m) => m.id));
590
- const includeMessages = await this._getIncludedMessages({ threadId, include });
624
+ const includeMessages = await this._getIncludedMessages({ include });
591
625
  includeMessages?.forEach((msg) => {
592
626
  if (!messageIds.has(msg.id)) {
593
627
  messages.push(msg);
@@ -610,7 +644,8 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
610
644
  const seqB = seqById.get(b.id);
611
645
  return seqA != null && seqB != null ? (seqA - seqB) * mult : a.id.localeCompare(b.id);
612
646
  });
613
- const returnedThreadMessageCount = finalMessages.filter((m) => m.threadId === threadId).length;
647
+ const threadIdSet = new Set(threadIds);
648
+ const returnedThreadMessageCount = finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).length;
614
649
  const hasMore = perPageInput !== false && returnedThreadMessageCount < total && offset + perPage < total;
615
650
  return {
616
651
  messages: finalMessages,
@@ -626,7 +661,7 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
626
661
  domain: error.ErrorDomain.STORAGE,
627
662
  category: error.ErrorCategory.THIRD_PARTY,
628
663
  details: {
629
- threadId,
664
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
630
665
  resourceId: resourceId ?? ""
631
666
  }
632
667
  },
@@ -2261,20 +2296,9 @@ ${columns}
2261
2296
  }
2262
2297
  };
2263
2298
  function transformScoreRow(row) {
2264
- return {
2265
- ...row,
2266
- input: storage.safelyParseJSON(row.input),
2267
- scorer: storage.safelyParseJSON(row.scorer),
2268
- preprocessStepResult: storage.safelyParseJSON(row.preprocessStepResult),
2269
- analyzeStepResult: storage.safelyParseJSON(row.analyzeStepResult),
2270
- metadata: storage.safelyParseJSON(row.metadata),
2271
- output: storage.safelyParseJSON(row.output),
2272
- additionalContext: storage.safelyParseJSON(row.additionalContext),
2273
- requestContext: storage.safelyParseJSON(row.requestContext),
2274
- entity: storage.safelyParseJSON(row.entity),
2275
- createdAt: row.createdAt,
2276
- updatedAt: row.updatedAt
2277
- };
2299
+ return storage.transformScoreRow(row, {
2300
+ convertTimestamps: true
2301
+ });
2278
2302
  }
2279
2303
  var ScoresMSSQL = class extends storage.ScoresStorage {
2280
2304
  pool;