@mastra/upstash 1.2.1-alpha.1 → 1.2.2-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,53 @@
1
1
  # @mastra/upstash
2
2
 
3
+ ## 1.2.2-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Add optional `batchId`, `datasetId`, and `datasetItemId` fields to persisted scores so saved baseline scores can be grouped as one scoring pass and joined back to the dataset items they came from. ([#18331](https://github.com/mastra-ai/mastra/pull/18331))
8
+ - `scoreTrace()` accepts top-level `batchId`, `datasetId`, and `datasetItemId` when persisting a score for a stored trace.
9
+ - `ScoreRowData` and score save payloads now include nullable `batchId`, `datasetId`, and `datasetItemId`.
10
+ - Built-in stores with explicit score schema or attribute mappings now persist these provenance fields on saved scores.
11
+ - D1, DSQL, MSSQL, and Upstash score stores now apply additive provenance migrations or deterministic score ordering for persisted score reads.
12
+
13
+ ```ts
14
+ await scoreTrace({
15
+ storage,
16
+ scorer,
17
+ target: { traceId },
18
+ batchId: 'baseline-batch-1',
19
+ datasetId,
20
+ datasetItemId,
21
+ });
22
+ ```
23
+
24
+ - Added optional `organizationId` and `projectId` fields to scores for multi-tenant isolation. Scores can now be saved with tenancy metadata and the `listScoresBy*` methods accept a `filters` option to scope results by organization and project. ([#18331](https://github.com/mastra-ai/mastra/pull/18331))
25
+
26
+ ```ts
27
+ await storage.saveScore({ ...score, organizationId: 'org-a', projectId: 'proj-1' });
28
+
29
+ const result = await storage.listScoresByScorerId({
30
+ scorerId,
31
+ filters: { organizationId: 'org-a', projectId: 'proj-1' },
32
+ });
33
+ ```
34
+
35
+ `projectId` identifies the project scope, separate from `resourceId` which continues to mean the agent memory resource.
36
+
37
+ - Updated dependencies [[`9250acd`](https://github.com/mastra-ai/mastra/commit/9250acd1357f0f1f33d0dcca16f9655084c58eca), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`c64c2a8`](https://github.com/mastra-ai/mastra/commit/c64c2a8503a50252f9ca6b8e8c54cadee31b92a2), [`06e2680`](https://github.com/mastra-ai/mastra/commit/06e26806b51d2cbd858afdc66daa2b86ff3ba64a), [`1240f05`](https://github.com/mastra-ai/mastra/commit/1240f051c8e5371f1c014448bf37b1a1b9a05e47), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748)]:
38
+ - @mastra/core@1.49.0-alpha.5
39
+ - @mastra/redis@1.2.2-alpha.0
40
+
41
+ ## 1.2.1
42
+
43
+ ### Patch Changes
44
+
45
+ - Fixed workflow runs preserving their original creation time when re-persisted in Upstash storage, including concurrent saves. ([#18004](https://github.com/mastra-ai/mastra/pull/18004))
46
+
47
+ - Updated dependencies [[`86623c1`](https://github.com/mastra-ai/mastra/commit/86623c1adf7d22de32cc916dda17f4155184db36), [`023766f`](https://github.com/mastra-ai/mastra/commit/023766f44d59b30a50f3a381e33eddde8ab56c00), [`0200e75`](https://github.com/mastra-ai/mastra/commit/0200e7552d02d4221cd6040bf4eddf189a97a156), [`7c9dd77`](https://github.com/mastra-ai/mastra/commit/7c9dd77bd18cb8dc72797e25f1a0fbdc71a11347), [`7f9ae70`](https://github.com/mastra-ai/mastra/commit/7f9ae70826b047e5a66218f9e92f20e54a2d791f), [`a0509c7`](https://github.com/mastra-ai/mastra/commit/a0509c731a08aa3ed626557c5338126362856f57), [`06e0d63`](https://github.com/mastra-ai/mastra/commit/06e0d63d42bc2a202e18bc091f3781f409f5e6fb), [`bf3fe49`](https://github.com/mastra-ai/mastra/commit/bf3fe49f9467dbbdb8f9eaf74e0f7971ffb19559), [`01caf93`](https://github.com/mastra-ai/mastra/commit/01caf93d71ae2c1e65f49735cafb531975187426), [`438a971`](https://github.com/mastra-ai/mastra/commit/438a9715c8b4398e5eaf8914a1f19dc8a85dc1de), [`9990965`](https://github.com/mastra-ai/mastra/commit/999096571635a83b42ef40841fd7028cfa630779), [`77518cc`](https://github.com/mastra-ai/mastra/commit/77518ccb5bb8cc684875081e64213dc85cffdbee), [`fbeda0c`](https://github.com/mastra-ai/mastra/commit/fbeda0c0f35def07e6837936dd3a003b2b7c5172), [`8a68844`](https://github.com/mastra-ai/mastra/commit/8a688443013816105a09f89c6afa34b5ff13e26d), [`bb2a13b`](https://github.com/mastra-ai/mastra/commit/bb2a13bb4b32e6bb807200fe7b18ae8fa4322118), [`24ceaea`](https://github.com/mastra-ai/mastra/commit/24ceaea0bdd8609cabbab764380608ca6621a194), [`a73cd1a`](https://github.com/mastra-ai/mastra/commit/a73cd1a62a5e4ca023dcc39ba150029f4f1f74c1), [`c0ffa3c`](https://github.com/mastra-ai/mastra/commit/c0ffa3c897ccd326de880df734740a7f0681a18f), [`462a769`](https://github.com/mastra-ai/mastra/commit/462a769da61850862ca1be3d74134d33078ee6a7), [`0504bf5`](https://github.com/mastra-ai/mastra/commit/0504bf5e8cffc571a4b343326178de371e6f859b), [`0b5cc47`](https://github.com/mastra-ai/mastra/commit/0b5cc4726dc18d9a685a27520db39ff1b36bb89a), [`87f38a3`](https://github.com/mastra-ai/mastra/commit/87f38a3de03e24731f2dd6f8ed6a60b6722b85a1), [`d5fa3cd`](https://github.com/mastra-ai/mastra/commit/d5fa3cda1788c3cb93a361a3c6ec47de6ba21e98), [`fe98ef2`](https://github.com/mastra-ai/mastra/commit/fe98ef2e66dbfcbd7d645c88c9ee1e67b458a136), [`6ccf67b`](https://github.com/mastra-ai/mastra/commit/6ccf67bf075753754927a57bc2e1734ba2c820c5), [`793ea0f`](https://github.com/mastra-ai/mastra/commit/793ea0f52f831178837f21c83af6af93bf4ce638), [`825d8de`](https://github.com/mastra-ai/mastra/commit/825d8def9fa64c2bcc3d8dd6b49e09342c3ac5c7), [`bf026c5`](https://github.com/mastra-ai/mastra/commit/bf026c5b641019c97facfe5924d14dd363866cb0), [`507a5c4`](https://github.com/mastra-ai/mastra/commit/507a5c461bdc3136ad80744c0efbb55ce1f18f97), [`5afe423`](https://github.com/mastra-ai/mastra/commit/5afe423e4badf040f1b0d4525183a856fcb8146e), [`307573b`](https://github.com/mastra-ai/mastra/commit/307573b9ff3149b70c79540dbc86f1319b180f29), [`79b3626`](https://github.com/mastra-ai/mastra/commit/79b3626f8d647307eb07c8da14c9073c2699719d), [`c2c1d7b`](https://github.com/mastra-ai/mastra/commit/c2c1d7bb61d2602955f14ed3952f807c2d6eb576), [`86623c1`](https://github.com/mastra-ai/mastra/commit/86623c1adf7d22de32cc916dda17f4155184db36), [`1505c07`](https://github.com/mastra-ai/mastra/commit/1505c07603f6346bae12aa82f140e8b88ffea9ab), [`f328049`](https://github.com/mastra-ai/mastra/commit/f3280498c324afd2a8d36cd828f5b9f94a2dddc1), [`e545228`](https://github.com/mastra-ai/mastra/commit/e54522856934a5dc030b7b6385771e3548020d59), [`3eb852e`](https://github.com/mastra-ai/mastra/commit/3eb852e5435bc908b800193498103dc724f455b0), [`ffa09e7`](https://github.com/mastra-ai/mastra/commit/ffa09e772a5c92270eabe2090fc42d45bd8ec4b7), [`8c9f1c0`](https://github.com/mastra-ai/mastra/commit/8c9f1c0361d89066f9bcd14a2f69e761b01766c8), [`461a7c5`](https://github.com/mastra-ai/mastra/commit/461a7c501449295287f4f0ee4b0b42344f39fcf8), [`4211472`](https://github.com/mastra-ai/mastra/commit/4211472a5a2bd319c60cd2e42d9109c3eef7ac1c), [`9e45902`](https://github.com/mastra-ai/mastra/commit/9e4590208e745055cecca202e2db0e5c65e17d3c), [`5c0df77`](https://github.com/mastra-ai/mastra/commit/5c0df776c40efa420f8c07a2f3ee66010296618e), [`e940f09`](https://github.com/mastra-ai/mastra/commit/e940f099ef5d18b403e6f2b4937e086a4da857b1)]:
48
+ - @mastra/core@1.47.0
49
+ - @mastra/redis@1.2.1
50
+
3
51
  ## 1.2.1-alpha.1
4
52
 
5
53
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-upstash
3
3
  description: Documentation for @mastra/upstash. Use when working with @mastra/upstash APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/upstash"
6
- version: "1.2.1-alpha.1"
6
+ version: "1.2.2-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.1-alpha.1",
2
+ "version": "1.2.2-alpha.0",
3
3
  "package": "@mastra/upstash",
4
4
  "exports": {
5
5
  "RedisServerCache": {
@@ -1,3 +1,5 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
1
3
  # Working Memory
2
4
 
3
5
  While [message history](https://mastra.ai/docs/memory/message-history) and [semantic recall](https://mastra.ai/docs/memory/semantic-recall) help agents remember conversations, working memory allows them to maintain persistent information about users across interactions.
@@ -6,6 +8,8 @@ Think of it as the agent's active thoughts or scratchpad – the key information
6
8
 
7
9
  This is useful for maintaining ongoing state that's always relevant and should always be available to the agent.
8
10
 
11
+ If you use [Observational Memory](https://mastra.ai/docs/memory/observational-memory), `observationalMemory.observation.manageWorkingMemory` lets OM update working memory for the agent.
12
+
9
13
  Working memory can persist at two different scopes:
10
14
 
11
15
  - **Resource-scoped** (default): Memory persists across all conversation threads for the same user
@@ -1,3 +1,5 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
1
3
  # Retrieval in RAG systems
2
4
 
3
5
  After storing embeddings, you need to retrieve relevant chunks to answer user queries.
@@ -1,3 +1,5 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
1
3
  # Storing embeddings in a vector database
2
4
 
3
5
  After generating embeddings, you need to store them in a database that supports vector similarity search. Mastra provides a consistent interface for storing and querying embeddings across various vector databases.
@@ -1,3 +1,5 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
1
3
  # Upstash storage
2
4
 
3
5
  The Upstash storage implementation provides a serverless-friendly storage solution using Upstash's Redis-compatible key-value store.
@@ -1,3 +1,5 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
1
3
  # Upstash vector store
2
4
 
3
5
  The UpstashVector class provides vector search using [Upstash Vector](https://upstash.com/vector), a serverless vector database service that provides vector similarity search with metadata filtering capabilities and hybrid search support.
package/dist/index.cjs CHANGED
@@ -1456,6 +1456,16 @@ var StoreMemoryUpstash = class extends storage.MemoryStorage {
1456
1456
  function transformScoreRow(row) {
1457
1457
  return storage.transformScoreRow(row);
1458
1458
  }
1459
+ function matchesTenancy(row, filters) {
1460
+ if (filters?.organizationId !== void 0 && row.organizationId !== filters.organizationId) return false;
1461
+ if (filters?.projectId !== void 0 && row.projectId !== filters.projectId) return false;
1462
+ return true;
1463
+ }
1464
+ function compareScoresByCreatedAtDesc(a, b) {
1465
+ const createdAtDiff = new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
1466
+ if (createdAtDiff !== 0) return createdAtDiff;
1467
+ return String(b.id ?? "").localeCompare(String(a.id ?? ""));
1468
+ }
1459
1469
  var ScoresUpstash = class extends storage.ScoresStorage {
1460
1470
  client;
1461
1471
  #db;
@@ -1495,7 +1505,8 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1495
1505
  entityId,
1496
1506
  entityType,
1497
1507
  source,
1498
- pagination = { page: 0, perPage: 20 }
1508
+ pagination = { page: 0, perPage: 20 },
1509
+ filters
1499
1510
  }) {
1500
1511
  const pattern = `${storage.TABLE_SCORERS}:*`;
1501
1512
  const keys = await this.#db.scanKeys(pattern);
@@ -1525,13 +1536,14 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1525
1536
  if (entityId && row.entityId !== entityId) return false;
1526
1537
  if (entityType && row.entityType !== entityType) return false;
1527
1538
  if (source && row.source !== source) return false;
1539
+ if (!matchesTenancy(row, filters)) return false;
1528
1540
  return true;
1529
1541
  });
1530
1542
  const perPage = storage.normalizePerPage(perPageInput, 100);
1531
1543
  const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
1532
1544
  const end = perPageInput === false ? filtered.length : start + perPage;
1533
1545
  const total = filtered.length;
1534
- const paged = filtered.slice(start, end);
1546
+ const paged = [...filtered].sort(compareScoresByCreatedAtDesc).slice(start, end);
1535
1547
  const scores = paged.map((row) => transformScoreRow(row));
1536
1548
  return {
1537
1549
  scores,
@@ -1592,7 +1604,8 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1592
1604
  }
1593
1605
  async listScoresByRunId({
1594
1606
  runId,
1595
- pagination = { page: 0, perPage: 20 }
1607
+ pagination = { page: 0, perPage: 20 },
1608
+ filters
1596
1609
  }) {
1597
1610
  const pattern = `${storage.TABLE_SCORERS}:*`;
1598
1611
  const keys = await this.#db.scanKeys(pattern);
@@ -1616,12 +1629,14 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1616
1629
  }
1617
1630
  }
1618
1631
  return raw;
1619
- }).filter((row) => !!row && typeof row === "object" && row.runId === runId);
1632
+ }).filter(
1633
+ (row) => !!row && typeof row === "object" && row.runId === runId && matchesTenancy(row, filters)
1634
+ );
1620
1635
  const total = filtered.length;
1621
1636
  const perPage = storage.normalizePerPage(perPageInput, 100);
1622
1637
  const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
1623
1638
  const end = perPageInput === false ? filtered.length : start + perPage;
1624
- const paged = filtered.slice(start, end);
1639
+ const paged = [...filtered].sort(compareScoresByCreatedAtDesc).slice(start, end);
1625
1640
  const scores = paged.map((row) => transformScoreRow(row));
1626
1641
  return {
1627
1642
  scores,
@@ -1636,7 +1651,8 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1636
1651
  async listScoresByEntityId({
1637
1652
  entityId,
1638
1653
  entityType,
1639
- pagination = { page: 0, perPage: 20 }
1654
+ pagination = { page: 0, perPage: 20 },
1655
+ filters
1640
1656
  }) {
1641
1657
  const pattern = `${storage.TABLE_SCORERS}:*`;
1642
1658
  const keys = await this.#db.scanKeys(pattern);
@@ -1664,13 +1680,14 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1664
1680
  if (!row || typeof row !== "object") return false;
1665
1681
  if (row.entityId !== entityId) return false;
1666
1682
  if (entityType && row.entityType !== entityType) return false;
1683
+ if (!matchesTenancy(row, filters)) return false;
1667
1684
  return true;
1668
1685
  });
1669
1686
  const total = filtered.length;
1670
1687
  const perPage = storage.normalizePerPage(perPageInput, 100);
1671
1688
  const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
1672
1689
  const end = perPageInput === false ? filtered.length : start + perPage;
1673
- const paged = filtered.slice(start, end);
1690
+ const paged = [...filtered].sort(compareScoresByCreatedAtDesc).slice(start, end);
1674
1691
  const scores = paged.map((row) => transformScoreRow(row));
1675
1692
  return {
1676
1693
  scores,
@@ -1685,7 +1702,8 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1685
1702
  async listScoresBySpan({
1686
1703
  traceId,
1687
1704
  spanId,
1688
- pagination = { page: 0, perPage: 20 }
1705
+ pagination = { page: 0, perPage: 20 },
1706
+ filters
1689
1707
  }) {
1690
1708
  const pattern = `${storage.TABLE_SCORERS}:*`;
1691
1709
  const keys = await this.#db.scanKeys(pattern);
@@ -1713,13 +1731,14 @@ var ScoresUpstash = class extends storage.ScoresStorage {
1713
1731
  if (!row || typeof row !== "object") return false;
1714
1732
  if (row.traceId !== traceId) return false;
1715
1733
  if (row.spanId !== spanId) return false;
1734
+ if (!matchesTenancy(row, filters)) return false;
1716
1735
  return true;
1717
1736
  });
1718
1737
  const total = filtered.length;
1719
1738
  const perPage = storage.normalizePerPage(perPageInput, 100);
1720
1739
  const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
1721
1740
  const end = perPageInput === false ? filtered.length : start + perPage;
1722
- const paged = filtered.slice(start, end);
1741
+ const paged = [...filtered].sort(compareScoresByCreatedAtDesc).slice(start, end);
1723
1742
  const scores = paged.map((row) => transformScoreRow(row));
1724
1743
  return {
1725
1744
  scores,