@mastra/upstash 1.0.3 → 1.0.4-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 +12 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-working-memory.md +6 -6
- package/dist/docs/references/docs-rag-vector-databases.md +2 -2
- package/dist/docs/references/reference-storage-upstash.md +4 -4
- package/dist/docs/references/reference-vectors-upstash.md +25 -25
- package/dist/index.cjs +32 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +32 -24
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +1 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @mastra/upstash
|
|
2
2
|
|
|
3
|
+
## 1.0.4-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dependencies updates: ([#13822](https://github.com/mastra-ai/mastra/pull/13822))
|
|
8
|
+
- Updated dependency [`@upstash/redis@^1.36.3` ↗︎](https://www.npmjs.com/package/@upstash/redis/v/1.36.3) (from `^1.36.2`, in `dependencies`)
|
|
9
|
+
|
|
10
|
+
- 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))
|
|
11
|
+
|
|
12
|
+
- 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)]:
|
|
13
|
+
- @mastra/core@1.11.0-alpha.0
|
|
14
|
+
|
|
3
15
|
## 1.0.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -170,11 +170,11 @@ const memory = new Memory({
|
|
|
170
170
|
|
|
171
171
|
## Designing Effective Templates
|
|
172
172
|
|
|
173
|
-
A well-structured template keeps the information
|
|
173
|
+
A well-structured template keeps the information straightforward for the agent to parse and update. Treat the template as a short form that you want the assistant to keep up to date.
|
|
174
174
|
|
|
175
|
-
- **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example `## Personal Info` or `- Name:`) so updates are
|
|
175
|
+
- **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example `## Personal Info` or `- Name:`) so updates are readable and less likely to be truncated.
|
|
176
176
|
- **Use consistent casing.** Inconsistent capitalization (`Timezone:` vs `timezone:`) can cause messy updates. Stick to Title Case or lower case for headings and bullet labels.
|
|
177
|
-
- **Keep placeholder text
|
|
177
|
+
- **Keep placeholder text minimal.** Use hints such as `[e.g., Formal]` or `[Date]` to help the LLM fill in the correct spots.
|
|
178
178
|
- **Abbreviate very long values.** If you only need a short form, include guidance like `- Name: [First name or nickname]` or `- Address (short):` rather than the full legal text.
|
|
179
179
|
- **Mention update rules in `instructions`.** You can instruct how and when to fill or clear parts of the template directly in the agent's `instructions` field.
|
|
180
180
|
|
|
@@ -263,13 +263,13 @@ Schema-based working memory uses **merge semantics**, meaning the agent only nee
|
|
|
263
263
|
|
|
264
264
|
- **Object fields are deep merged:** Only provided fields are updated; others remain unchanged
|
|
265
265
|
- **Set a field to `null` to delete it:** This explicitly removes the field from memory
|
|
266
|
-
- **Arrays are replaced entirely:** When an array field is provided, it replaces the existing array (arrays
|
|
266
|
+
- **Arrays are replaced entirely:** When an array field is provided, it replaces the existing array (arrays aren't merged element-by-element)
|
|
267
267
|
|
|
268
268
|
## Choosing Between Template and Schema
|
|
269
269
|
|
|
270
270
|
- Use a **template** (Markdown) if you want the agent to maintain memory as a free-form text block, such as a user profile or scratchpad. Templates use **replace semantics** — the agent must provide the complete memory content on each update.
|
|
271
271
|
- Use a **schema** if you need structured, type-safe data that can be validated and programmatically accessed as JSON. Schemas use **merge semantics** — the agent only provides fields to update, and existing fields are preserved.
|
|
272
|
-
- Only one mode can be active at a time: setting both `template` and `schema`
|
|
272
|
+
- Only one mode can be active at a time: setting both `template` and `schema` isn't supported.
|
|
273
273
|
|
|
274
274
|
## Example: Multi-step Retention
|
|
275
275
|
|
|
@@ -301,7 +301,7 @@ Below is a simplified view of how the `User Profile` template updates across a s
|
|
|
301
301
|
|
|
302
302
|
The agent can now refer to `Sam` or `Berlin` in later responses without requesting the information again because it has been stored in working memory.
|
|
303
303
|
|
|
304
|
-
If your agent
|
|
304
|
+
If your agent isn't properly updating working memory when you expect it to, you can add system instructions on _how_ and _when_ to use this template in your agent's `instructions` setting.
|
|
305
305
|
|
|
306
306
|
## Setting Initial Working Memory
|
|
307
307
|
|
|
@@ -359,7 +359,7 @@ The dimension size must match the output dimension of your chosen embedding mode
|
|
|
359
359
|
- Cohere embed-multilingual-v3: 1024 dimensions
|
|
360
360
|
- Google gemini-embedding-001: 768 dimensions (or custom)
|
|
361
361
|
|
|
362
|
-
> **Warning:** Index dimensions
|
|
362
|
+
> **Warning:** Index dimensions can't be changed after creation. To use a different model, delete and recreate the index with the new dimension size.
|
|
363
363
|
|
|
364
364
|
### Naming Rules for Databases
|
|
365
365
|
|
|
@@ -583,7 +583,7 @@ Key metadata considerations:
|
|
|
583
583
|
|
|
584
584
|
## Deleting Vectors
|
|
585
585
|
|
|
586
|
-
When building RAG applications, you often need to clean up stale vectors when documents are deleted or updated. Mastra provides the `deleteVectors` method that supports deleting vectors by metadata filters, making it
|
|
586
|
+
When building RAG applications, you often need to clean up stale vectors when documents are deleted or updated. Mastra provides the `deleteVectors` method that supports deleting vectors by metadata filters, making it straightforward to remove all embeddings associated with a specific document.
|
|
587
587
|
|
|
588
588
|
### Delete by Metadata Filter
|
|
589
589
|
|
|
@@ -4,7 +4,7 @@ The Upstash storage implementation provides a serverless-friendly storage soluti
|
|
|
4
4
|
|
|
5
5
|
> **Pricing:** When using Mastra with Upstash, the pay-as-you-go model can result in unexpectedly high costs due to the high volume of Redis commands generated during agent conversations. We strongly recommend using a **fixed pricing plan** for predictable costs. See [Upstash pricing](https://upstash.com/pricing/redis) for details and [GitHub issue #5850](https://github.com/mastra-ai/mastra/issues/5850) for context.
|
|
6
6
|
|
|
7
|
-
> **Observability Not Supported:** Upstash storage **
|
|
7
|
+
> **Observability Not Supported:** Upstash storage **doesn't support the observability domain**. Traces from the `DefaultExporter` can't be persisted to Upstash, and Mastra Studio's observability features won't work with Upstash as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -46,11 +46,11 @@ const storage = new UpstashStore({
|
|
|
46
46
|
|
|
47
47
|
## Parameters
|
|
48
48
|
|
|
49
|
-
**url
|
|
49
|
+
**url** (`string`): Upstash Redis URL
|
|
50
50
|
|
|
51
|
-
**token
|
|
51
|
+
**token** (`string`): Upstash Redis authentication token
|
|
52
52
|
|
|
53
|
-
**prefix
|
|
53
|
+
**prefix** (`string`): Key prefix for all stored items (Default: `mastra:`)
|
|
54
54
|
|
|
55
55
|
## Additional Notes
|
|
56
56
|
|
|
@@ -4,9 +4,9 @@ The UpstashVector class provides vector search using [Upstash Vector](https://up
|
|
|
4
4
|
|
|
5
5
|
## Constructor Options
|
|
6
6
|
|
|
7
|
-
**url
|
|
7
|
+
**url** (`string`): Upstash Vector database URL
|
|
8
8
|
|
|
9
|
-
**token
|
|
9
|
+
**token** (`string`): Upstash Vector API token
|
|
10
10
|
|
|
11
11
|
## Methods
|
|
12
12
|
|
|
@@ -14,41 +14,41 @@ The UpstashVector class provides vector search using [Upstash Vector](https://up
|
|
|
14
14
|
|
|
15
15
|
Note: This method is a no-op for Upstash as indexes are created automatically.
|
|
16
16
|
|
|
17
|
-
**indexName
|
|
17
|
+
**indexName** (`string`): Name of the index to create
|
|
18
18
|
|
|
19
|
-
**dimension
|
|
19
|
+
**dimension** (`number`): Vector dimension (must match your embedding model)
|
|
20
20
|
|
|
21
|
-
**metric
|
|
21
|
+
**metric** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`)
|
|
22
22
|
|
|
23
23
|
### upsert()
|
|
24
24
|
|
|
25
|
-
**indexName
|
|
25
|
+
**indexName** (`string`): Name of the index to upsert into
|
|
26
26
|
|
|
27
|
-
**vectors
|
|
27
|
+
**vectors** (`number[][]`): Array of embedding vectors
|
|
28
28
|
|
|
29
|
-
**sparseVectors
|
|
29
|
+
**sparseVectors** (`{ indices: number[], values: number[] }[]`): Array of sparse vectors for hybrid search. Each sparse vector must have matching indices and values arrays.
|
|
30
30
|
|
|
31
|
-
**metadata
|
|
31
|
+
**metadata** (`Record<string, any>[]`): Metadata for each vector
|
|
32
32
|
|
|
33
|
-
**ids
|
|
33
|
+
**ids** (`string[]`): Optional vector IDs (auto-generated if not provided)
|
|
34
34
|
|
|
35
35
|
### query()
|
|
36
36
|
|
|
37
|
-
**indexName
|
|
37
|
+
**indexName** (`string`): Name of the index to query
|
|
38
38
|
|
|
39
|
-
**queryVector
|
|
39
|
+
**queryVector** (`number[]`): Query vector to find similar vectors
|
|
40
40
|
|
|
41
|
-
**sparseVector
|
|
41
|
+
**sparseVector** (`{ indices: number[], values: number[] }`): Optional sparse vector for hybrid search. Must have matching indices and values arrays.
|
|
42
42
|
|
|
43
|
-
**topK
|
|
43
|
+
**topK** (`number`): Number of results to return (Default: `10`)
|
|
44
44
|
|
|
45
|
-
**filter
|
|
45
|
+
**filter** (`Record<string, any>`): Metadata filters for the query
|
|
46
46
|
|
|
47
|
-
**includeVector
|
|
47
|
+
**includeVector** (`boolean`): Whether to include vectors in the results (Default: `false`)
|
|
48
48
|
|
|
49
|
-
**fusionAlgorithm
|
|
49
|
+
**fusionAlgorithm** (`FusionAlgorithm`): Algorithm used to combine dense and sparse search results in hybrid search (e.g., RRF - Reciprocal Rank Fusion)
|
|
50
50
|
|
|
51
|
-
**queryMode
|
|
51
|
+
**queryMode** (`QueryMode`): Search mode: 'DENSE' for dense-only, 'SPARSE' for sparse-only, or 'HYBRID' for combined search
|
|
52
52
|
|
|
53
53
|
### listIndexes()
|
|
54
54
|
|
|
@@ -56,7 +56,7 @@ Returns an array of index names (namespaces) as strings.
|
|
|
56
56
|
|
|
57
57
|
### describeIndex()
|
|
58
58
|
|
|
59
|
-
**indexName
|
|
59
|
+
**indexName** (`string`): Name of the index to describe
|
|
60
60
|
|
|
61
61
|
Returns:
|
|
62
62
|
|
|
@@ -70,15 +70,15 @@ interface IndexStats {
|
|
|
70
70
|
|
|
71
71
|
### deleteIndex()
|
|
72
72
|
|
|
73
|
-
**indexName
|
|
73
|
+
**indexName** (`string`): Name of the index (namespace) to delete
|
|
74
74
|
|
|
75
75
|
### updateVector()
|
|
76
76
|
|
|
77
|
-
**indexName
|
|
77
|
+
**indexName** (`string`): Name of the index to update
|
|
78
78
|
|
|
79
|
-
**id
|
|
79
|
+
**id** (`string`): ID of the item to update
|
|
80
80
|
|
|
81
|
-
**update
|
|
81
|
+
**update** (`object`): Update object containing vector, sparse vector, and/or metadata
|
|
82
82
|
|
|
83
83
|
The `update` object can have the following properties:
|
|
84
84
|
|
|
@@ -88,9 +88,9 @@ The `update` object can have the following properties:
|
|
|
88
88
|
|
|
89
89
|
### deleteVector()
|
|
90
90
|
|
|
91
|
-
**indexName
|
|
91
|
+
**indexName** (`string`): Name of the index from which to delete the item
|
|
92
92
|
|
|
93
|
-
**id
|
|
93
|
+
**id** (`string`): ID of the item to delete
|
|
94
94
|
|
|
95
95
|
Attempts to delete an item by its ID from the specified index. Logs an error message if the deletion fails.
|
|
96
96
|
|
package/dist/index.cjs
CHANGED
|
@@ -504,6 +504,22 @@ var StoreMemoryUpstash = class extends storage.MemoryStorage {
|
|
|
504
504
|
}
|
|
505
505
|
return messageData.threadId || null;
|
|
506
506
|
}
|
|
507
|
+
_sortMessages(messages, field, direction) {
|
|
508
|
+
return messages.sort((a, b) => {
|
|
509
|
+
const getVal = (msg) => {
|
|
510
|
+
if (field === "createdAt") {
|
|
511
|
+
return new Date(msg.createdAt).getTime();
|
|
512
|
+
}
|
|
513
|
+
const value = msg[field];
|
|
514
|
+
if (typeof value === "number") return value;
|
|
515
|
+
if (value instanceof Date) return value.getTime();
|
|
516
|
+
return 0;
|
|
517
|
+
};
|
|
518
|
+
const aValue = getVal(a);
|
|
519
|
+
const bValue = getVal(b);
|
|
520
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
521
|
+
});
|
|
522
|
+
}
|
|
507
523
|
async _getIncludedMessages(include) {
|
|
508
524
|
if (!include?.length) return [];
|
|
509
525
|
const messageIds = /* @__PURE__ */ new Set();
|
|
@@ -640,11 +656,25 @@ var StoreMemoryUpstash = class extends storage.MemoryStorage {
|
|
|
640
656
|
new Error("page must be >= 0")
|
|
641
657
|
);
|
|
642
658
|
}
|
|
659
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
660
|
+
if (perPage === 0 && (!include || include.length === 0)) {
|
|
661
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
662
|
+
}
|
|
643
663
|
let includedMessages = [];
|
|
644
664
|
if (include && include.length > 0) {
|
|
645
665
|
const included = await this._getIncludedMessages(include);
|
|
646
666
|
includedMessages = included.map(this.parseStoredMessage);
|
|
647
667
|
}
|
|
668
|
+
if (perPage === 0 && include && include.length > 0) {
|
|
669
|
+
const list2 = new agent.MessageList().add(includedMessages, "memory");
|
|
670
|
+
return {
|
|
671
|
+
messages: this._sortMessages(list2.get.all.db(), field, direction),
|
|
672
|
+
total: 0,
|
|
673
|
+
page,
|
|
674
|
+
perPage: perPageForResponse,
|
|
675
|
+
hasMore: false
|
|
676
|
+
};
|
|
677
|
+
}
|
|
648
678
|
const allMessageIdsWithThreads = [];
|
|
649
679
|
for (const tid of threadIds) {
|
|
650
680
|
const threadMessagesKey = getThreadMessagesKey(tid);
|
|
@@ -674,25 +704,7 @@ var StoreMemoryUpstash = class extends storage.MemoryStorage {
|
|
|
674
704
|
(msg) => new Date(msg.createdAt),
|
|
675
705
|
filter?.dateRange
|
|
676
706
|
);
|
|
677
|
-
|
|
678
|
-
const getFieldValue = (msg) => {
|
|
679
|
-
if (field === "createdAt") {
|
|
680
|
-
return new Date(msg.createdAt).getTime();
|
|
681
|
-
}
|
|
682
|
-
const value = msg[field];
|
|
683
|
-
if (typeof value === "number") {
|
|
684
|
-
return value;
|
|
685
|
-
}
|
|
686
|
-
if (value instanceof Date) {
|
|
687
|
-
return value.getTime();
|
|
688
|
-
}
|
|
689
|
-
return 0;
|
|
690
|
-
};
|
|
691
|
-
messagesData.sort((a, b) => {
|
|
692
|
-
const aValue = getFieldValue(a);
|
|
693
|
-
const bValue = getFieldValue(b);
|
|
694
|
-
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
695
|
-
});
|
|
707
|
+
messagesData = this._sortMessages(messagesData, field, direction);
|
|
696
708
|
const total = messagesData.length;
|
|
697
709
|
const start = offset;
|
|
698
710
|
const end = perPageInput === false ? total : start + perPage;
|
|
@@ -713,11 +725,7 @@ var StoreMemoryUpstash = class extends storage.MemoryStorage {
|
|
|
713
725
|
}
|
|
714
726
|
const list = new agent.MessageList().add(allMessages, "memory");
|
|
715
727
|
let finalMessages = list.get.all.db();
|
|
716
|
-
finalMessages =
|
|
717
|
-
const aValue = getFieldValue(a);
|
|
718
|
-
const bValue = getFieldValue(b);
|
|
719
|
-
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
720
|
-
});
|
|
728
|
+
finalMessages = this._sortMessages(finalMessages, field, direction);
|
|
721
729
|
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
722
730
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
723
731
|
const hasMore = perPageInput !== false && !allThreadMessagesReturned && end < total;
|