@mastra/upstash 0.1.13-alpha.0 → 0.2.0-alpha.1
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +11 -0
- package/dist/_tsup-dts-rollup.d.cts +5 -0
- package/dist/_tsup-dts-rollup.d.ts +5 -0
- package/dist/index.cjs +32 -0
- package/dist/index.js +32 -0
- package/package.json +3 -2
- package/src/vector/index.test.ts +152 -25
- package/src/vector/index.ts +47 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/upstash@0.
|
|
2
|
+
> @mastra/upstash@0.2.0-alpha.1 build /home/runner/work/mastra/mastra/stores/upstash
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.4.0
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 9696ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.8.2
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/upstash/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.8.2
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/upstash/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 10580ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
|
-
[
|
|
21
|
-
[
|
|
22
|
-
[
|
|
23
|
-
[
|
|
20
|
+
[32mESM[39m [1mdist/index.js [22m[32m17.07 KB[39m
|
|
21
|
+
[32mESM[39m ⚡️ Build success in 746ms
|
|
22
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m17.20 KB[39m
|
|
23
|
+
[32mCJS[39m ⚡️ Build success in 747ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @mastra/upstash
|
|
2
2
|
|
|
3
|
+
## 0.2.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c0b2496: Added new operations implementations for MastraVector methods in upstash store
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [6794797]
|
|
12
|
+
- @mastra/core@0.6.4-alpha.1
|
|
13
|
+
|
|
3
14
|
## 0.1.13-alpha.0
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -126,6 +126,11 @@ declare class UpstashVector extends MastraVector {
|
|
|
126
126
|
metric: "cosine" | "euclidean" | "dotproduct";
|
|
127
127
|
}>;
|
|
128
128
|
deleteIndex(indexName: string): Promise<void>;
|
|
129
|
+
updateIndexById(indexName: string, id: string, update: {
|
|
130
|
+
vector?: number[];
|
|
131
|
+
metadata?: Record<string, any>;
|
|
132
|
+
}): Promise<void>;
|
|
133
|
+
deleteIndexById(indexName: string, id: string): Promise<void>;
|
|
129
134
|
}
|
|
130
135
|
export { UpstashVector }
|
|
131
136
|
export { UpstashVector as UpstashVector_alias_1 }
|
|
@@ -126,6 +126,11 @@ declare class UpstashVector extends MastraVector {
|
|
|
126
126
|
metric: "cosine" | "euclidean" | "dotproduct";
|
|
127
127
|
}>;
|
|
128
128
|
deleteIndex(indexName: string): Promise<void>;
|
|
129
|
+
updateIndexById(indexName: string, id: string, update: {
|
|
130
|
+
vector?: number[];
|
|
131
|
+
metadata?: Record<string, any>;
|
|
132
|
+
}): Promise<void>;
|
|
133
|
+
deleteIndexById(indexName: string, id: string): Promise<void>;
|
|
129
134
|
}
|
|
130
135
|
export { UpstashVector }
|
|
131
136
|
export { UpstashVector as UpstashVector_alias_1 }
|
package/dist/index.cjs
CHANGED
|
@@ -474,6 +474,38 @@ var UpstashVector = class extends vector.MastraVector {
|
|
|
474
474
|
console.error("Failed to delete namespace:", error);
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
|
+
async updateIndexById(indexName, id, update) {
|
|
478
|
+
if (!update.vector && !update.metadata) {
|
|
479
|
+
throw new Error("No update data provided");
|
|
480
|
+
}
|
|
481
|
+
if (!update.vector && update.metadata) {
|
|
482
|
+
throw new Error("Both vector and metadata must be provided for an update");
|
|
483
|
+
}
|
|
484
|
+
const updatePayload = { id };
|
|
485
|
+
if (update.vector) {
|
|
486
|
+
updatePayload.vector = update.vector;
|
|
487
|
+
}
|
|
488
|
+
if (update.metadata) {
|
|
489
|
+
updatePayload.metadata = update.metadata;
|
|
490
|
+
}
|
|
491
|
+
const points = {
|
|
492
|
+
id: updatePayload.id,
|
|
493
|
+
vector: updatePayload.vector,
|
|
494
|
+
metadata: updatePayload.metadata
|
|
495
|
+
};
|
|
496
|
+
await this.client.upsert(points, {
|
|
497
|
+
namespace: indexName
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
async deleteIndexById(indexName, id) {
|
|
501
|
+
try {
|
|
502
|
+
await this.client.delete(id, {
|
|
503
|
+
namespace: indexName
|
|
504
|
+
});
|
|
505
|
+
} catch (error) {
|
|
506
|
+
console.error("Failed to delete index by ID:", error);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
477
509
|
};
|
|
478
510
|
|
|
479
511
|
exports.UpstashStore = UpstashStore;
|
package/dist/index.js
CHANGED
|
@@ -472,6 +472,38 @@ var UpstashVector = class extends MastraVector {
|
|
|
472
472
|
console.error("Failed to delete namespace:", error);
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
|
+
async updateIndexById(indexName, id, update) {
|
|
476
|
+
if (!update.vector && !update.metadata) {
|
|
477
|
+
throw new Error("No update data provided");
|
|
478
|
+
}
|
|
479
|
+
if (!update.vector && update.metadata) {
|
|
480
|
+
throw new Error("Both vector and metadata must be provided for an update");
|
|
481
|
+
}
|
|
482
|
+
const updatePayload = { id };
|
|
483
|
+
if (update.vector) {
|
|
484
|
+
updatePayload.vector = update.vector;
|
|
485
|
+
}
|
|
486
|
+
if (update.metadata) {
|
|
487
|
+
updatePayload.metadata = update.metadata;
|
|
488
|
+
}
|
|
489
|
+
const points = {
|
|
490
|
+
id: updatePayload.id,
|
|
491
|
+
vector: updatePayload.vector,
|
|
492
|
+
metadata: updatePayload.metadata
|
|
493
|
+
};
|
|
494
|
+
await this.client.upsert(points, {
|
|
495
|
+
namespace: indexName
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
async deleteIndexById(indexName, id) {
|
|
499
|
+
try {
|
|
500
|
+
await this.client.delete(id, {
|
|
501
|
+
namespace: indexName
|
|
502
|
+
});
|
|
503
|
+
} catch (error) {
|
|
504
|
+
console.error("Failed to delete index by ID:", error);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
475
507
|
};
|
|
476
508
|
|
|
477
509
|
export { UpstashStore, UpstashVector };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/upstash",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-alpha.1",
|
|
4
4
|
"description": "Upstash provider for Mastra - includes both vector and db storage capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,11 +21,12 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@upstash/redis": "^1.34.5",
|
|
23
23
|
"@upstash/vector": "^1.2.1",
|
|
24
|
-
"@mastra/core": "^0.6.4-alpha.
|
|
24
|
+
"@mastra/core": "^0.6.4-alpha.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@microsoft/api-extractor": "^7.52.1",
|
|
28
28
|
"@types/node": "^22.13.10",
|
|
29
|
+
"dotenv": "^16.4.7",
|
|
29
30
|
"eslint": "^9.22.0",
|
|
30
31
|
"tsup": "^8.4.0",
|
|
31
32
|
"typescript": "^5.8.2",
|
package/src/vector/index.test.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
|
|
1
3
|
import { describe, it, expect, beforeAll, afterAll, beforeEach, vi, afterEach } from 'vitest';
|
|
2
4
|
|
|
3
5
|
import { UpstashVector } from './';
|
|
6
|
+
import type { QueryResult } from '@mastra/core';
|
|
7
|
+
|
|
8
|
+
dotenv.config();
|
|
4
9
|
|
|
5
10
|
function waitUntilVectorsIndexed(vector: UpstashVector, indexName: string, expectedCount: number) {
|
|
6
11
|
return new Promise((resolve, reject) => {
|
|
@@ -98,19 +103,145 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
98
103
|
}, 5000000);
|
|
99
104
|
|
|
100
105
|
it('should query vectors and return vector in results', async () => {
|
|
101
|
-
const results = await vectorStore.query({
|
|
106
|
+
const results = await vectorStore.query({
|
|
107
|
+
indexName: testIndexName,
|
|
108
|
+
queryVector: createVector(0, 0.9),
|
|
109
|
+
topK: 3,
|
|
110
|
+
includeVector: true,
|
|
111
|
+
});
|
|
102
112
|
expect(results).toHaveLength(3);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
results.forEach(result => {
|
|
114
|
+
expect(result.vector).toBeDefined();
|
|
115
|
+
expect(result.vector).toHaveLength(VECTOR_DIMENSION);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('Vector update operations', () => {
|
|
120
|
+
const testVectors = [createVector(0, 1.0), createVector(1, 1.0), createVector(2, 1.0)];
|
|
121
|
+
|
|
122
|
+
const testIndexName = 'test-index';
|
|
123
|
+
|
|
124
|
+
afterEach(async () => {
|
|
125
|
+
await vectorStore.deleteIndex(testIndexName);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should update the vector by id', async () => {
|
|
129
|
+
const ids = await vectorStore.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
130
|
+
expect(ids).toHaveLength(3);
|
|
131
|
+
|
|
132
|
+
const idToBeUpdated = ids[0];
|
|
133
|
+
const newVector = createVector(0, 4.0);
|
|
134
|
+
const newMetaData = {
|
|
135
|
+
test: 'updates',
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const update = {
|
|
139
|
+
vector: newVector,
|
|
140
|
+
metadata: newMetaData,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
await vectorStore.updateIndexById(testIndexName, idToBeUpdated, update);
|
|
144
|
+
|
|
145
|
+
await waitUntilVectorsIndexed(vectorStore, testIndexName, 3);
|
|
146
|
+
|
|
147
|
+
const results: QueryResult[] = await vectorStore.query({
|
|
148
|
+
indexName: testIndexName,
|
|
149
|
+
queryVector: newVector,
|
|
150
|
+
topK: 2,
|
|
151
|
+
includeVector: true,
|
|
152
|
+
});
|
|
153
|
+
expect(results[0]?.id).toBe(idToBeUpdated);
|
|
154
|
+
expect(results[0]?.vector).toEqual(newVector);
|
|
155
|
+
expect(results[0]?.metadata).toEqual(newMetaData);
|
|
156
|
+
}, 500000);
|
|
157
|
+
|
|
158
|
+
it('should only update the metadata by id', async () => {
|
|
159
|
+
const ids = await vectorStore.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
160
|
+
expect(ids).toHaveLength(3);
|
|
161
|
+
|
|
162
|
+
const idToBeUpdated = ids[0];
|
|
163
|
+
const newMetaData = {
|
|
164
|
+
test: 'updates',
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const update = {
|
|
168
|
+
metadata: newMetaData,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
await expect(vectorStore.updateIndexById(testIndexName, 'id', update)).rejects.toThrow(
|
|
172
|
+
'Both vector and metadata must be provided for an update',
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should only update vector embeddings by id', async () => {
|
|
177
|
+
const ids = await vectorStore.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
178
|
+
expect(ids).toHaveLength(3);
|
|
179
|
+
|
|
180
|
+
const idToBeUpdated = ids[0];
|
|
181
|
+
const newVector = createVector(0, 4.0);
|
|
182
|
+
|
|
183
|
+
const update = {
|
|
184
|
+
vector: newVector,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
await vectorStore.updateIndexById(testIndexName, idToBeUpdated, update);
|
|
188
|
+
|
|
189
|
+
await waitUntilVectorsIndexed(vectorStore, testIndexName, 3);
|
|
190
|
+
|
|
191
|
+
const results: QueryResult[] = await vectorStore.query({
|
|
192
|
+
indexName: testIndexName,
|
|
193
|
+
queryVector: newVector,
|
|
194
|
+
topK: 2,
|
|
195
|
+
includeVector: true,
|
|
196
|
+
});
|
|
197
|
+
expect(results[0]?.id).toBe(idToBeUpdated);
|
|
198
|
+
expect(results[0]?.vector).toEqual(newVector);
|
|
199
|
+
}, 500000);
|
|
200
|
+
|
|
201
|
+
it('should throw exception when no updates are given', async () => {
|
|
202
|
+
await expect(vectorStore.updateIndexById(testIndexName, 'id', {})).rejects.toThrow('No update data provided');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('Vector delete operations', () => {
|
|
207
|
+
const testVectors = [createVector(0, 1.0), createVector(1, 1.0), createVector(2, 1.0)];
|
|
208
|
+
|
|
209
|
+
afterEach(async () => {
|
|
210
|
+
await vectorStore.deleteIndex(testIndexName);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should delete the vector by id', async () => {
|
|
214
|
+
const ids = await vectorStore.upsert({ indexName: testIndexName, vectors: testVectors });
|
|
215
|
+
expect(ids).toHaveLength(3);
|
|
216
|
+
const idToBeDeleted = ids[0];
|
|
217
|
+
|
|
218
|
+
await vectorStore.deleteIndexById(testIndexName, idToBeDeleted);
|
|
219
|
+
|
|
220
|
+
const results: QueryResult[] = await vectorStore.query({
|
|
221
|
+
indexName: testIndexName,
|
|
222
|
+
queryVector: createVector(0, 1.0),
|
|
223
|
+
topK: 2,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(results).toHaveLength(2);
|
|
227
|
+
expect(results.map(res => res.id)).not.toContain(idToBeDeleted);
|
|
228
|
+
});
|
|
109
229
|
});
|
|
110
230
|
});
|
|
111
231
|
describe('Index Operations', () => {
|
|
232
|
+
const createVector = (primaryDimension: number, value: number = 1.0): number[] => {
|
|
233
|
+
const vector = new Array(VECTOR_DIMENSION).fill(0);
|
|
234
|
+
vector[primaryDimension] = value;
|
|
235
|
+
// Normalize the vector for cosine similarity
|
|
236
|
+
const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
|
|
237
|
+
return vector.map(val => val / magnitude);
|
|
238
|
+
};
|
|
112
239
|
it('should create and list an index', async () => {
|
|
113
|
-
|
|
240
|
+
// since, we do not have to create index explictly in case of upstash. Upserts are enough
|
|
241
|
+
// for testing the listIndexes() function
|
|
242
|
+
// await vectorStore.createIndex({ indexName: testIndexName, dimension: 3, metric: 'cosine' });
|
|
243
|
+
const ids = await vectorStore.upsert({ indexName: testIndexName, vectors: [createVector(0, 1.0)] });
|
|
244
|
+
expect(ids).toHaveLength(1);
|
|
114
245
|
const indexes = await vectorStore.listIndexes();
|
|
115
246
|
expect(indexes).toEqual([testIndexName]);
|
|
116
247
|
});
|
|
@@ -1068,10 +1199,6 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1068
1199
|
|
|
1069
1200
|
let warnSpy;
|
|
1070
1201
|
|
|
1071
|
-
beforeAll(async () => {
|
|
1072
|
-
await vectorStore.createIndex({ indexName: indexName, dimension: 3 });
|
|
1073
|
-
});
|
|
1074
|
-
|
|
1075
1202
|
afterAll(async () => {
|
|
1076
1203
|
await vectorStore.deleteIndex(indexName);
|
|
1077
1204
|
await vectorStore.deleteIndex(indexName2);
|
|
@@ -1086,16 +1213,16 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1086
1213
|
await vectorStore.deleteIndex(indexName2);
|
|
1087
1214
|
});
|
|
1088
1215
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1216
|
+
const createVector = (primaryDimension: number, value: number = 1.0): number[] => {
|
|
1217
|
+
const vector = new Array(VECTOR_DIMENSION).fill(0);
|
|
1218
|
+
vector[primaryDimension] = value;
|
|
1219
|
+
// Normalize the vector for cosine similarity
|
|
1220
|
+
const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
|
|
1221
|
+
return vector.map(val => val / magnitude);
|
|
1222
|
+
};
|
|
1096
1223
|
|
|
1097
1224
|
it('should show deprecation warning when using individual args for upsert', async () => {
|
|
1098
|
-
await vectorStore.upsert(indexName, [
|
|
1225
|
+
await vectorStore.upsert(indexName, [createVector(0, 2)], [{ test: 'data' }]);
|
|
1099
1226
|
|
|
1100
1227
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
1101
1228
|
expect.stringContaining('Deprecation Warning: Passing individual arguments to upsert() is deprecated'),
|
|
@@ -1103,7 +1230,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1103
1230
|
});
|
|
1104
1231
|
|
|
1105
1232
|
it('should show deprecation warning when using individual args for query', async () => {
|
|
1106
|
-
await vectorStore.query(indexName,
|
|
1233
|
+
await vectorStore.query(indexName, createVector(0, 2), 5);
|
|
1107
1234
|
|
|
1108
1235
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
1109
1236
|
expect.stringContaining('Deprecation Warning: Passing individual arguments to query() is deprecated'),
|
|
@@ -1113,7 +1240,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1113
1240
|
it('should not show deprecation warning when using object param for query', async () => {
|
|
1114
1241
|
await vectorStore.query({
|
|
1115
1242
|
indexName,
|
|
1116
|
-
queryVector:
|
|
1243
|
+
queryVector: createVector(0, 2),
|
|
1117
1244
|
topK: 5,
|
|
1118
1245
|
});
|
|
1119
1246
|
|
|
@@ -1133,7 +1260,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1133
1260
|
it('should not show deprecation warning when using object param for upsert', async () => {
|
|
1134
1261
|
await vectorStore.upsert({
|
|
1135
1262
|
indexName,
|
|
1136
|
-
vectors: [
|
|
1263
|
+
vectors: [createVector(0, 2)],
|
|
1137
1264
|
metadata: [{ test: 'data' }],
|
|
1138
1265
|
});
|
|
1139
1266
|
|
|
@@ -1142,7 +1269,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1142
1269
|
|
|
1143
1270
|
it('should maintain backward compatibility with individual args', async () => {
|
|
1144
1271
|
// Query
|
|
1145
|
-
const queryResults = await vectorStore.query(indexName,
|
|
1272
|
+
const queryResults = await vectorStore.query(indexName, createVector(0, 2), 5);
|
|
1146
1273
|
expect(Array.isArray(queryResults)).toBe(true);
|
|
1147
1274
|
|
|
1148
1275
|
// CreateIndex
|
|
@@ -1151,7 +1278,7 @@ describe.skipIf(!process.env.UPSTASH_VECTOR_URL || !process.env.UPSTASH_VECTOR_T
|
|
|
1151
1278
|
// Upsert
|
|
1152
1279
|
const upsertResults = await vectorStore.upsert({
|
|
1153
1280
|
indexName,
|
|
1154
|
-
vectors: [
|
|
1281
|
+
vectors: [createVector(0, 2)],
|
|
1155
1282
|
metadata: [{ test: 'data' }],
|
|
1156
1283
|
});
|
|
1157
1284
|
expect(Array.isArray(upsertResults)).toBe(true);
|
package/src/vector/index.ts
CHANGED
|
@@ -97,4 +97,51 @@ export class UpstashVector extends MastraVector {
|
|
|
97
97
|
console.error('Failed to delete namespace:', error);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
async updateIndexById(
|
|
102
|
+
indexName: string,
|
|
103
|
+
id: string,
|
|
104
|
+
update: {
|
|
105
|
+
vector?: number[];
|
|
106
|
+
metadata?: Record<string, any>;
|
|
107
|
+
},
|
|
108
|
+
): Promise<void> {
|
|
109
|
+
if (!update.vector && !update.metadata) {
|
|
110
|
+
throw new Error('No update data provided');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// The upstash client throws an exception as: 'This index requires dense vectors' when
|
|
114
|
+
// only metadata is present in the update object.
|
|
115
|
+
if (!update.vector && update.metadata) {
|
|
116
|
+
throw new Error('Both vector and metadata must be provided for an update');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const updatePayload: any = { id: id };
|
|
120
|
+
if (update.vector) {
|
|
121
|
+
updatePayload.vector = update.vector;
|
|
122
|
+
}
|
|
123
|
+
if (update.metadata) {
|
|
124
|
+
updatePayload.metadata = update.metadata;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const points = {
|
|
128
|
+
id: updatePayload.id,
|
|
129
|
+
vector: updatePayload.vector,
|
|
130
|
+
metadata: updatePayload.metadata,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
await this.client.upsert(points, {
|
|
134
|
+
namespace: indexName,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async deleteIndexById(indexName: string, id: string): Promise<void> {
|
|
139
|
+
try {
|
|
140
|
+
await this.client.delete(id, {
|
|
141
|
+
namespace: indexName,
|
|
142
|
+
});
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error('Failed to delete index by ID:', error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
100
147
|
}
|