@mastra/upstash 0.0.0-working-memory-per-user-20250620163010 → 0.0.0-zod-v4-compat-part-2-20250820135355

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +268 -6
  2. package/LICENSE.md +12 -4
  3. package/README.md +98 -0
  4. package/dist/index.cjs +1629 -626
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.ts +4 -4
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +1645 -642
  9. package/dist/index.js.map +1 -0
  10. package/dist/storage/domains/legacy-evals/index.d.ts +28 -0
  11. package/dist/storage/domains/legacy-evals/index.d.ts.map +1 -0
  12. package/dist/storage/domains/memory/index.d.ts +86 -0
  13. package/dist/storage/domains/memory/index.d.ts.map +1 -0
  14. package/dist/storage/domains/operations/index.d.ts +40 -0
  15. package/dist/storage/domains/operations/index.d.ts.map +1 -0
  16. package/dist/storage/domains/scores/index.d.ts +65 -0
  17. package/dist/storage/domains/scores/index.d.ts.map +1 -0
  18. package/dist/storage/domains/traces/index.d.ts +28 -0
  19. package/dist/storage/domains/traces/index.d.ts.map +1 -0
  20. package/dist/storage/domains/utils.d.ts +12 -0
  21. package/dist/storage/domains/utils.d.ts.map +1 -0
  22. package/dist/storage/domains/workflows/index.d.ts +36 -0
  23. package/dist/storage/domains/workflows/index.d.ts.map +1 -0
  24. package/dist/storage/index.d.ts +208 -0
  25. package/dist/storage/index.d.ts.map +1 -0
  26. package/dist/vector/filter.d.ts +21 -0
  27. package/dist/vector/filter.d.ts.map +1 -0
  28. package/dist/vector/index.d.ts +79 -0
  29. package/dist/vector/index.d.ts.map +1 -0
  30. package/dist/vector/prompt.d.ts +6 -0
  31. package/dist/vector/prompt.d.ts.map +1 -0
  32. package/dist/vector/types.d.ts +23 -0
  33. package/dist/vector/types.d.ts.map +1 -0
  34. package/docker-compose.yaml +1 -1
  35. package/package.json +12 -12
  36. package/src/storage/domains/legacy-evals/index.ts +279 -0
  37. package/src/storage/domains/memory/index.ts +972 -0
  38. package/src/storage/domains/operations/index.ts +168 -0
  39. package/src/storage/domains/scores/index.ts +216 -0
  40. package/src/storage/domains/traces/index.ts +172 -0
  41. package/src/storage/domains/utils.ts +57 -0
  42. package/src/storage/domains/workflows/index.ts +243 -0
  43. package/src/storage/index.test.ts +13 -0
  44. package/src/storage/index.ts +149 -1078
  45. package/src/vector/filter.test.ts +7 -6
  46. package/src/vector/filter.ts +10 -4
  47. package/src/vector/hybrid.test.ts +1455 -0
  48. package/src/vector/index.test.ts +4 -4
  49. package/src/vector/index.ts +155 -69
  50. package/src/vector/types.ts +26 -0
  51. package/tsconfig.build.json +9 -0
  52. package/tsconfig.json +1 -1
  53. package/tsup.config.ts +22 -0
  54. package/dist/_tsup-dts-rollup.d.cts +0 -318
  55. package/dist/_tsup-dts-rollup.d.ts +0 -318
  56. package/dist/index.d.cts +0 -4
  57. package/src/storage/upstash.test.ts +0 -1386
@@ -37,7 +37,7 @@ function waitUntilVectorsIndexed(vector: UpstashVector, indexName: string, expec
37
37
  */
38
38
  describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_TOKEN)('UpstashVector', () => {
39
39
  let vectorStore: UpstashVector;
40
- const VECTOR_DIMENSION = 1536;
40
+ const VECTOR_DIMENSION = 1024;
41
41
  const testIndexName = 'default';
42
42
  const filterIndexName = 'filter-index';
43
43
 
@@ -250,7 +250,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
250
250
  it('should describe an index correctly', async () => {
251
251
  const stats = await vectorStore.describeIndex({ indexName: 'mastra_default' });
252
252
  expect(stats).toEqual({
253
- dimension: 1536,
253
+ dimension: 1024,
254
254
  metric: 'cosine',
255
255
  count: 0,
256
256
  });
@@ -1146,7 +1146,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
1146
1146
  vectorStore.query({
1147
1147
  indexName: filterIndexName,
1148
1148
  queryVector: createVector(0),
1149
- filter: { field: { $invalidOp: 'value' } },
1149
+ filter: { field: { $invalidOp: 'value' } as any },
1150
1150
  }),
1151
1151
  ).rejects.toThrow();
1152
1152
  });
@@ -1196,7 +1196,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
1196
1196
  const results = await vectorStore.query({
1197
1197
  indexName: filterIndexName,
1198
1198
  queryVector: createVector(0),
1199
- filter: { $and: { not: 'an array' } },
1199
+ filter: { $and: { not: 'an array' } as any },
1200
1200
  });
1201
1201
  expect(results.length).toBeGreaterThan(0);
1202
1202
  });
@@ -1,3 +1,4 @@
1
+ import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';
1
2
  import { MastraVector } from '@mastra/core/vector';
2
3
  import type {
3
4
  CreateIndexParams,
@@ -6,16 +7,14 @@ import type {
6
7
  DescribeIndexParams,
7
8
  IndexStats,
8
9
  QueryResult,
9
- QueryVectorParams,
10
- UpdateVectorParams,
11
- UpsertVectorParams,
12
10
  } from '@mastra/core/vector';
13
- import type { VectorFilter } from '@mastra/core/vector/filter';
14
11
  import { Index } from '@upstash/vector';
15
12
 
16
13
  import { UpstashFilterTranslator } from './filter';
14
+ import type { UpstashVectorFilter } from './filter';
15
+ import type { UpstashUpsertVectorParams, UpstashQueryVectorParams, UpstashUpdateVectorParams } from './types';
17
16
 
18
- export class UpstashVector extends MastraVector {
17
+ export class UpstashVector extends MastraVector<UpstashVectorFilter> {
19
18
  private client: Index;
20
19
 
21
20
  /**
@@ -37,27 +36,46 @@ export class UpstashVector extends MastraVector {
37
36
  * @param {UpsertVectorParams} params - The parameters for the upsert operation.
38
37
  * @returns {Promise<string[]>} A promise that resolves to the IDs of the upserted vectors.
39
38
  */
40
- async upsert({ indexName: namespace, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]> {
39
+ async upsert({
40
+ indexName: namespace,
41
+ vectors,
42
+ metadata,
43
+ ids,
44
+ sparseVectors,
45
+ }: UpstashUpsertVectorParams): Promise<string[]> {
41
46
  const generatedIds = ids || vectors.map(() => crypto.randomUUID());
42
47
 
43
48
  const points = vectors.map((vector, index) => ({
44
49
  id: generatedIds[index]!,
45
50
  vector,
51
+ ...(sparseVectors?.[index] && { sparseVector: sparseVectors[index] }),
46
52
  metadata: metadata?.[index],
47
53
  }));
48
54
 
49
- await this.client.upsert(points, {
50
- namespace,
51
- });
52
- return generatedIds;
55
+ try {
56
+ await this.client.upsert(points, {
57
+ namespace,
58
+ });
59
+ return generatedIds;
60
+ } catch (error) {
61
+ throw new MastraError(
62
+ {
63
+ id: 'STORAGE_UPSTASH_VECTOR_UPSERT_FAILED',
64
+ domain: ErrorDomain.STORAGE,
65
+ category: ErrorCategory.THIRD_PARTY,
66
+ details: { namespace, vectorCount: vectors.length },
67
+ },
68
+ error,
69
+ );
70
+ }
53
71
  }
54
72
 
55
73
  /**
56
74
  * Transforms a Mastra vector filter into an Upstash-compatible filter string.
57
- * @param {VectorFilter} [filter] - The filter to transform.
75
+ * @param {UpstashVectorFilter} [filter] - The filter to transform.
58
76
  * @returns {string | undefined} The transformed filter string, or undefined if no filter is provided.
59
77
  */
60
- transformFilter(filter?: VectorFilter) {
78
+ transformFilter(filter?: UpstashVectorFilter) {
61
79
  const translator = new UpstashFilterTranslator();
62
80
  return translator.translate(filter);
63
81
  }
@@ -82,25 +100,43 @@ export class UpstashVector extends MastraVector {
82
100
  topK = 10,
83
101
  filter,
84
102
  includeVector = false,
85
- }: QueryVectorParams): Promise<QueryResult[]> {
86
- const ns = this.client.namespace(namespace);
87
-
88
- const filterString = this.transformFilter(filter);
89
- const results = await ns.query({
90
- topK,
91
- vector: queryVector,
92
- includeVectors: includeVector,
93
- includeMetadata: true,
94
- ...(filterString ? { filter: filterString } : {}),
95
- });
103
+ sparseVector,
104
+ fusionAlgorithm,
105
+ queryMode,
106
+ }: UpstashQueryVectorParams): Promise<QueryResult[]> {
107
+ try {
108
+ const ns = this.client.namespace(namespace);
96
109
 
97
- // Map the results to our expected format
98
- return (results || []).map(result => ({
99
- id: `${result.id}`,
100
- score: result.score,
101
- metadata: result.metadata,
102
- ...(includeVector && { vector: result.vector || [] }),
103
- }));
110
+ const filterString = this.transformFilter(filter);
111
+ const results = await ns.query({
112
+ topK,
113
+ vector: queryVector,
114
+ ...(sparseVector && { sparseVector }),
115
+ includeVectors: includeVector,
116
+ includeMetadata: true,
117
+ ...(filterString ? { filter: filterString } : {}),
118
+ ...(fusionAlgorithm && { fusionAlgorithm }),
119
+ ...(queryMode && { queryMode }),
120
+ });
121
+
122
+ // Map the results to our expected format
123
+ return (results || []).map(result => ({
124
+ id: `${result.id}`,
125
+ score: result.score,
126
+ metadata: result.metadata,
127
+ ...(includeVector && { vector: result.vector || [] }),
128
+ }));
129
+ } catch (error) {
130
+ throw new MastraError(
131
+ {
132
+ id: 'STORAGE_UPSTASH_VECTOR_QUERY_FAILED',
133
+ domain: ErrorDomain.STORAGE,
134
+ category: ErrorCategory.THIRD_PARTY,
135
+ details: { namespace, topK },
136
+ },
137
+ error,
138
+ );
139
+ }
104
140
  }
105
141
 
106
142
  /**
@@ -108,8 +144,19 @@ export class UpstashVector extends MastraVector {
108
144
  * @returns {Promise<string[]>} A promise that resolves to a list of index names.
109
145
  */
110
146
  async listIndexes(): Promise<string[]> {
111
- const indexes = await this.client.listNamespaces();
112
- return indexes.filter(Boolean);
147
+ try {
148
+ const indexes = await this.client.listNamespaces();
149
+ return indexes.filter(Boolean);
150
+ } catch (error) {
151
+ throw new MastraError(
152
+ {
153
+ id: 'STORAGE_UPSTASH_VECTOR_LIST_INDEXES_FAILED',
154
+ domain: ErrorDomain.STORAGE,
155
+ category: ErrorCategory.THIRD_PARTY,
156
+ },
157
+ error,
158
+ );
159
+ }
113
160
  }
114
161
 
115
162
  /**
@@ -119,13 +166,25 @@ export class UpstashVector extends MastraVector {
119
166
  * @returns A promise that resolves to the index statistics including dimension, count and metric
120
167
  */
121
168
  async describeIndex({ indexName: namespace }: DescribeIndexParams): Promise<IndexStats> {
122
- const info = await this.client.info();
169
+ try {
170
+ const info = await this.client.info();
123
171
 
124
- return {
125
- dimension: info.dimension,
126
- count: info.namespaces?.[namespace]?.vectorCount || 0,
127
- metric: info?.similarityFunction?.toLowerCase() as 'cosine' | 'euclidean' | 'dotproduct',
128
- };
172
+ return {
173
+ dimension: info.dimension,
174
+ count: info.namespaces?.[namespace]?.vectorCount || 0,
175
+ metric: info?.similarityFunction?.toLowerCase() as 'cosine' | 'euclidean' | 'dotproduct',
176
+ };
177
+ } catch (error) {
178
+ throw new MastraError(
179
+ {
180
+ id: 'STORAGE_UPSTASH_VECTOR_DESCRIBE_INDEX_FAILED',
181
+ domain: ErrorDomain.STORAGE,
182
+ category: ErrorCategory.THIRD_PARTY,
183
+ details: { namespace },
184
+ },
185
+ error,
186
+ );
187
+ }
129
188
  }
130
189
 
131
190
  /**
@@ -137,7 +196,15 @@ export class UpstashVector extends MastraVector {
137
196
  try {
138
197
  await this.client.deleteNamespace(namespace);
139
198
  } catch (error) {
140
- this.logger.error('Failed to delete namespace:', error);
199
+ throw new MastraError(
200
+ {
201
+ id: 'STORAGE_UPSTASH_VECTOR_DELETE_INDEX_FAILED',
202
+ domain: ErrorDomain.STORAGE,
203
+ category: ErrorCategory.THIRD_PARTY,
204
+ details: { namespace },
205
+ },
206
+ error,
207
+ );
141
208
  }
142
209
  }
143
210
 
@@ -151,37 +218,47 @@ export class UpstashVector extends MastraVector {
151
218
  * @returns A promise that resolves when the update is complete.
152
219
  * @throws Will throw an error if no updates are provided or if the update operation fails.
153
220
  */
154
- async updateVector({ indexName: namespace, id, update }: UpdateVectorParams): Promise<void> {
155
- try {
156
- if (!update.vector && !update.metadata) {
157
- throw new Error('No update data provided');
158
- }
159
-
160
- // The upstash client throws an exception as: 'This index requires dense vectors' when
161
- // only metadata is present in the update object.
162
- if (!update.vector && update.metadata) {
163
- throw new Error('Both vector and metadata must be provided for an update');
164
- }
165
-
166
- const updatePayload: any = { id: id };
167
- if (update.vector) {
168
- updatePayload.vector = update.vector;
169
- }
170
- if (update.metadata) {
171
- updatePayload.metadata = update.metadata;
172
- }
173
-
174
- const points = {
175
- id: updatePayload.id,
176
- vector: updatePayload.vector,
177
- metadata: updatePayload.metadata,
178
- };
221
+ async updateVector({ indexName: namespace, id, update }: UpstashUpdateVectorParams): Promise<void> {
222
+ if (!update.vector && !update.metadata && !update.sparseVector) {
223
+ throw new MastraError({
224
+ id: 'STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED',
225
+ domain: ErrorDomain.STORAGE,
226
+ category: ErrorCategory.THIRD_PARTY,
227
+ details: { namespace, id },
228
+ text: 'No update data provided',
229
+ });
230
+ }
179
231
 
180
- await this.client.upsert(points, {
181
- namespace,
232
+ // The upstash client throws an exception as: 'This index requires dense/sparse vectors' when
233
+ // only metadata is present in the update object.
234
+ if (!update.vector && !update.sparseVector && update.metadata) {
235
+ throw new MastraError({
236
+ id: 'STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED',
237
+ domain: ErrorDomain.STORAGE,
238
+ category: ErrorCategory.THIRD_PARTY,
239
+ details: { namespace, id },
240
+ text: 'Both vector and metadata must be provided for an update',
182
241
  });
183
- } catch (error: any) {
184
- throw new Error(`Failed to update vector by id: ${id} for index name: ${namespace}: ${error.message}`);
242
+ }
243
+
244
+ try {
245
+ const points: any = { id };
246
+
247
+ if (update.vector) points.vector = update.vector;
248
+ if (update.metadata) points.metadata = update.metadata;
249
+ if (update.sparseVector) points.sparseVector = update.sparseVector;
250
+
251
+ await this.client.upsert(points, { namespace });
252
+ } catch (error) {
253
+ throw new MastraError(
254
+ {
255
+ id: 'STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED',
256
+ domain: ErrorDomain.STORAGE,
257
+ category: ErrorCategory.THIRD_PARTY,
258
+ details: { namespace, id },
259
+ },
260
+ error,
261
+ );
185
262
  }
186
263
  }
187
264
 
@@ -198,7 +275,16 @@ export class UpstashVector extends MastraVector {
198
275
  namespace,
199
276
  });
200
277
  } catch (error) {
201
- this.logger.error(`Failed to delete vector by id: ${id} for namespace: ${namespace}:`, error);
278
+ const mastraError = new MastraError(
279
+ {
280
+ id: 'STORAGE_UPSTASH_VECTOR_DELETE_VECTOR_FAILED',
281
+ domain: ErrorDomain.STORAGE,
282
+ category: ErrorCategory.THIRD_PARTY,
283
+ details: { namespace, id },
284
+ },
285
+ error,
286
+ );
287
+ this.logger?.error(mastraError.toString());
202
288
  }
203
289
  }
204
290
  }
@@ -0,0 +1,26 @@
1
+ import type { UpsertVectorParams, QueryVectorParams, UpdateVectorParams } from '@mastra/core/vector';
2
+ import type { FusionAlgorithm, QueryMode } from '@upstash/vector';
3
+ import type { UpstashVectorFilter } from './filter';
4
+
5
+ export interface UpstashSparseVector {
6
+ indices: number[];
7
+ values: number[];
8
+ }
9
+
10
+ export interface UpstashUpsertVectorParams extends UpsertVectorParams {
11
+ sparseVectors?: UpstashSparseVector[];
12
+ }
13
+
14
+ export interface UpstashQueryVectorParams extends QueryVectorParams<UpstashVectorFilter> {
15
+ sparseVector?: UpstashSparseVector;
16
+ fusionAlgorithm?: FusionAlgorithm;
17
+ queryMode?: QueryMode;
18
+ }
19
+
20
+ export interface UpstashUpdateVectorParams extends UpdateVectorParams {
21
+ update: {
22
+ vector?: number[];
23
+ metadata?: Record<string, any>;
24
+ sparseVector?: UpstashSparseVector;
25
+ };
26
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": ["./tsconfig.json", "../../tsconfig.build.json"],
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "**/*.test.ts", "src/**/*.mock.ts"]
9
+ }
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "extends": "../../tsconfig.node.json",
3
- "include": ["src/**/*"],
3
+ "include": ["src/**/*", "tsup.config.ts"],
4
4
  "exclude": ["node_modules", "**/*.test.ts"]
5
5
  }
package/tsup.config.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { spawn } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import { defineConfig } from 'tsup';
4
+
5
+ const exec = promisify(spawn);
6
+
7
+ export default defineConfig({
8
+ entry: ['src/index.ts'],
9
+ format: ['esm', 'cjs'],
10
+ clean: true,
11
+ dts: false,
12
+ splitting: true,
13
+ treeshake: {
14
+ preset: 'smallest',
15
+ },
16
+ sourcemap: true,
17
+ onSuccess: async () => {
18
+ await exec('pnpm', ['tsc', '-p', 'tsconfig.build.json'], {
19
+ stdio: 'inherit',
20
+ });
21
+ },
22
+ });