@mastra/couchbase 0.0.0-redis-cloud-transporter-20250508203756 → 0.0.0-taofeeqInngest-20250603090617

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.
@@ -0,0 +1,23 @@
1
+
2
+ > @mastra/couchbase@0.10.1-alpha.1 build /home/runner/work/mastra/mastra/stores/couchbase
3
+ > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
+
5
+ CLI Building entry: src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.4.0
8
+ TSC Build start
9
+ TSC ⚡️ Build success in 6294ms
10
+ DTS Build start
11
+ CLI Target: es2022
12
+ Analysis will use the bundled TypeScript version 5.8.3
13
+ Writing package typings: /home/runner/work/mastra/mastra/stores/couchbase/dist/_tsup-dts-rollup.d.ts
14
+ Analysis will use the bundled TypeScript version 5.8.3
15
+ Writing package typings: /home/runner/work/mastra/mastra/stores/couchbase/dist/_tsup-dts-rollup.d.cts
16
+ DTS ⚡️ Build success in 8860ms
17
+ CLI Cleaning output folder
18
+ ESM Build start
19
+ CJS Build start
20
+ CJS dist/index.cjs 10.90 KB
21
+ CJS ⚡️ Build success in 674ms
22
+ ESM dist/index.js 10.84 KB
23
+ ESM ⚡️ Build success in 674ms
package/CHANGELOG.md CHANGED
@@ -1,6 +1,173 @@
1
1
  # @mastra/couchbase
2
2
 
3
- ## 0.0.0-redis-cloud-transporter-20250508203756
3
+ ## 0.0.0-taofeeqInngest-20250603090617
4
+
5
+ ### Patch Changes
6
+
7
+ - f0d559f: Fix peerdeps for alpha channel
8
+ - 915ca1a: Added disconnect function for couchbase and added docs
9
+ Added prompt for OpenSearchVector
10
+ - Updated dependencies [ee77e78]
11
+ - Updated dependencies [592a2db]
12
+ - Updated dependencies [e5dc18d]
13
+ - Updated dependencies [ab5adbe]
14
+ - Updated dependencies [1e8bb40]
15
+ - Updated dependencies [195c428]
16
+ - Updated dependencies [f73e11b]
17
+ - Updated dependencies [c5bf1ce]
18
+ - Updated dependencies [12b7002]
19
+ - Updated dependencies [2901125]
20
+ - @mastra/core@0.0.0-taofeeqInngest-20250603090617
21
+
22
+ ## 0.10.1-alpha.1
23
+
24
+ ### Patch Changes
25
+
26
+ - f0d559f: Fix peerdeps for alpha channel
27
+ - Updated dependencies [1e8bb40]
28
+ - @mastra/core@0.10.2-alpha.2
29
+
30
+ ## 0.10.1-alpha.0
31
+
32
+ ### Patch Changes
33
+
34
+ - 915ca1a: Added disconnect function for couchbase and added docs
35
+ Added prompt for OpenSearchVector
36
+ - Updated dependencies [ee77e78]
37
+ - Updated dependencies [2901125]
38
+ - @mastra/core@0.10.2-alpha.1
39
+
40
+ ## 0.10.0
41
+
42
+ ### Minor Changes
43
+
44
+ - 83da932: Move @mastra/core to peerdeps
45
+
46
+ ### Patch Changes
47
+
48
+ - d0ee3c6: Change all public functions and constructors in vector stores to use named args and prepare to phase out positional args
49
+ - a7292b0: BREAKING(@mastra/core, all vector stores): Vector store breaking changes (remove deprecated functions and positional arguments)
50
+ - Updated dependencies [b3a3d63]
51
+ - Updated dependencies [344f453]
52
+ - Updated dependencies [0a3ae6d]
53
+ - Updated dependencies [95911be]
54
+ - Updated dependencies [f53a6ac]
55
+ - Updated dependencies [5eb5a99]
56
+ - Updated dependencies [7e632c5]
57
+ - Updated dependencies [1e9fbfa]
58
+ - Updated dependencies [eabdcd9]
59
+ - Updated dependencies [90be034]
60
+ - Updated dependencies [99f050a]
61
+ - Updated dependencies [d0ee3c6]
62
+ - Updated dependencies [b2ae5aa]
63
+ - Updated dependencies [23f258c]
64
+ - Updated dependencies [a7292b0]
65
+ - Updated dependencies [0dcb9f0]
66
+ - Updated dependencies [2672a05]
67
+ - @mastra/core@0.10.0
68
+
69
+ ## 0.1.0-alpha.1
70
+
71
+ ### Minor Changes
72
+
73
+ - 83da932: Move @mastra/core to peerdeps
74
+
75
+ ### Patch Changes
76
+
77
+ - a7292b0: BREAKING(@mastra/core, all vector stores): Vector store breaking changes (remove deprecated functions and positional arguments)
78
+ - Updated dependencies [b3a3d63]
79
+ - Updated dependencies [344f453]
80
+ - Updated dependencies [0a3ae6d]
81
+ - Updated dependencies [95911be]
82
+ - Updated dependencies [5eb5a99]
83
+ - Updated dependencies [7e632c5]
84
+ - Updated dependencies [1e9fbfa]
85
+ - Updated dependencies [b2ae5aa]
86
+ - Updated dependencies [a7292b0]
87
+ - Updated dependencies [0dcb9f0]
88
+ - @mastra/core@0.10.0-alpha.1
89
+
90
+ ## 0.0.5-alpha.0
91
+
92
+ ### Patch Changes
93
+
94
+ - d0ee3c6: Change all public functions and constructors in vector stores to use named args and prepare to phase out positional args
95
+ - Updated dependencies [f53a6ac]
96
+ - Updated dependencies [eabdcd9]
97
+ - Updated dependencies [90be034]
98
+ - Updated dependencies [99f050a]
99
+ - Updated dependencies [d0ee3c6]
100
+ - Updated dependencies [23f258c]
101
+ - Updated dependencies [2672a05]
102
+ - @mastra/core@0.9.5-alpha.0
103
+
104
+ ## 0.0.4
105
+
106
+ ### Patch Changes
107
+
108
+ - c3bd795: [MASTRA-3358] Deprecate updateIndexById and deleteIndexById
109
+ - Updated dependencies [396be50]
110
+ - Updated dependencies [ab80e7e]
111
+ - Updated dependencies [c3bd795]
112
+ - Updated dependencies [da082f8]
113
+ - Updated dependencies [a5810ce]
114
+ - Updated dependencies [3e9c131]
115
+ - Updated dependencies [3171b5b]
116
+ - Updated dependencies [973e5ac]
117
+ - Updated dependencies [daf942f]
118
+ - Updated dependencies [0b8b868]
119
+ - Updated dependencies [9e1eff5]
120
+ - Updated dependencies [6fa1ad1]
121
+ - Updated dependencies [c28d7a0]
122
+ - Updated dependencies [edf1e88]
123
+ - @mastra/core@0.9.4
124
+
125
+ ## 0.0.4-alpha.4
126
+
127
+ ### Patch Changes
128
+
129
+ - Updated dependencies [3e9c131]
130
+ - @mastra/core@0.9.4-alpha.4
131
+
132
+ ## 0.0.4-alpha.3
133
+
134
+ ### Patch Changes
135
+
136
+ - c3bd795: [MASTRA-3358] Deprecate updateIndexById and deleteIndexById
137
+ - Updated dependencies [396be50]
138
+ - Updated dependencies [c3bd795]
139
+ - Updated dependencies [da082f8]
140
+ - Updated dependencies [a5810ce]
141
+ - @mastra/core@0.9.4-alpha.3
142
+
143
+ ## 0.0.4-alpha.2
144
+
145
+ ### Patch Changes
146
+
147
+ - Updated dependencies [3171b5b]
148
+ - Updated dependencies [973e5ac]
149
+ - Updated dependencies [9e1eff5]
150
+ - @mastra/core@0.9.4-alpha.2
151
+
152
+ ## 0.0.4-alpha.1
153
+
154
+ ### Patch Changes
155
+
156
+ - Updated dependencies [ab80e7e]
157
+ - Updated dependencies [6fa1ad1]
158
+ - Updated dependencies [c28d7a0]
159
+ - Updated dependencies [edf1e88]
160
+ - @mastra/core@0.9.4-alpha.1
161
+
162
+ ## 0.0.4-alpha.0
163
+
164
+ ### Patch Changes
165
+
166
+ - Updated dependencies [daf942f]
167
+ - Updated dependencies [0b8b868]
168
+ - @mastra/core@0.9.4-alpha.0
169
+
170
+ ## 0.0.3
4
171
 
5
172
  ### Patch Changes
6
173
 
@@ -9,11 +176,24 @@
9
176
  - Updated dependencies [8902157]
10
177
  - Updated dependencies [ca0dc88]
11
178
  - Updated dependencies [526c570]
179
+ - Updated dependencies [d7a6a33]
12
180
  - Updated dependencies [9cd1a46]
13
181
  - Updated dependencies [b5d2de0]
14
182
  - Updated dependencies [644f8ad]
15
183
  - Updated dependencies [70dbf51]
16
- - @mastra/core@0.0.0-redis-cloud-transporter-20250508203756
184
+ - @mastra/core@0.9.3
185
+
186
+ ## 0.0.3-alpha.1
187
+
188
+ ### Patch Changes
189
+
190
+ - 9cd1a46: [MASTRA-3338] update naming scheme for embedding index based on vector store rules and added duplicate index checks
191
+ - Updated dependencies [e450778]
192
+ - Updated dependencies [8902157]
193
+ - Updated dependencies [ca0dc88]
194
+ - Updated dependencies [9cd1a46]
195
+ - Updated dependencies [70dbf51]
196
+ - @mastra/core@0.9.3-alpha.1
17
197
 
18
198
  ## 0.0.3-alpha.0
19
199
 
package/README.md CHANGED
@@ -51,7 +51,14 @@ const bucketName = 'your_vector_bucket';
51
51
  const scopeName = '_default'; // Or your custom scope name
52
52
  const collectionName = 'vector_data'; // Or your custom collection name
53
53
 
54
- const vectorStore = new CouchbaseVector(connectionString, username, password, bucketName, scopeName, collectionName);
54
+ const vectorStore = new CouchbaseVector({
55
+ connectionString,
56
+ username,
57
+ password,
58
+ bucketName,
59
+ scopeName,
60
+ collectionName,
61
+ });
55
62
 
56
63
  console.log('CouchbaseVector instance created. Connecting...');
57
64
  ```
@@ -214,6 +221,9 @@ _Note_: Deleting Index does NOT delete the vectors in the associated Couchbase C
214
221
  - `listIndexes()`: Lists the names of all Search Indexes in the cluster. Returns fully qualified names (e.g., `bucket.scope.index`).
215
222
  - `describeIndex(indexName)`: Gets the configured dimension, metric (Mastra name), and document count (currently returns -1) for a specific Search Index (using its short name).
216
223
  - `deleteIndex(indexName)`: Deletes a Search Index (using its short name).
224
+ - `deleteVector(indexName, id)`: Deletes a specific vector entry from an index by its ID.
225
+ - `updateVector(indexName, id, update)`: Updates a specific vector entry by its ID with new vector data and/or metadata.
226
+ - `disconnect()`: Closes the Couchbase client connection. Should be called when done using the store.
217
227
 
218
228
  ## Configuration Details
219
229
 
@@ -1,9 +1,13 @@
1
1
  import type { Collection } from 'couchbase';
2
2
  import type { CreateIndexParams } from '@mastra/core/vector';
3
+ import type { DeleteIndexParams } from '@mastra/core/vector';
4
+ import type { DeleteVectorParams } from '@mastra/core/vector';
5
+ import type { DescribeIndexParams } from '@mastra/core/vector';
3
6
  import type { IndexStats } from '@mastra/core/vector';
4
7
  import { MastraVector } from '@mastra/core/vector';
5
8
  import type { QueryResult } from '@mastra/core/vector';
6
9
  import type { QueryVectorParams } from '@mastra/core/vector';
10
+ import type { UpdateVectorParams } from '@mastra/core/vector';
7
11
  import type { UpsertVectorParams } from '@mastra/core/vector';
8
12
 
9
13
  declare type CouchbaseMetric = 'cosine' | 'l2_norm' | 'dot_product';
@@ -18,18 +22,55 @@ declare class CouchbaseVector extends MastraVector {
18
22
  private bucket;
19
23
  private scope;
20
24
  private vector_dimension;
21
- constructor(cnn_string: string, username: string, password: string, bucketName: string, scopeName: string, collectionName: string);
25
+ constructor({ connectionString, username, password, bucketName, scopeName, collectionName }: CouchbaseVectorParams);
22
26
  getCollection(): Promise<Collection>;
23
- createIndex(params: CreateIndexParams): Promise<void>;
24
- upsert(params: UpsertVectorParams): Promise<string[]>;
25
- query(params: QueryVectorParams): Promise<QueryResult[]>;
27
+ createIndex({ indexName, dimension, metric }: CreateIndexParams): Promise<void>;
28
+ upsert({ vectors, metadata, ids }: UpsertVectorParams): Promise<string[]>;
29
+ query({ indexName, queryVector, topK, includeVector }: QueryVectorParams): Promise<QueryResult[]>;
26
30
  listIndexes(): Promise<string[]>;
27
- describeIndex(indexName: string): Promise<IndexStats>;
28
- deleteIndex(indexName: string): Promise<void>;
31
+ /**
32
+ * Retrieves statistics about a vector index.
33
+ *
34
+ * @param {string} indexName - The name of the index to describe
35
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
36
+ */
37
+ describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats>;
38
+ deleteIndex({ indexName }: DeleteIndexParams): Promise<void>;
39
+ /**
40
+ * Updates a vector by its ID with the provided vector and/or metadata.
41
+ * @param indexName - The name of the index containing the vector.
42
+ * @param id - The ID of the vector to update.
43
+ * @param update - An object containing the vector and/or metadata to update.
44
+ * @param update.vector - An optional array of numbers representing the new vector.
45
+ * @param update.metadata - An optional record containing the new metadata.
46
+ * @returns A promise that resolves when the update is complete.
47
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
48
+ */
49
+ updateVector({ id, update }: UpdateVectorParams): Promise<void>;
50
+ /**
51
+ * Deletes a vector by its ID.
52
+ * @param indexName - The name of the index containing the vector.
53
+ * @param id - The ID of the vector to delete.
54
+ * @returns A promise that resolves when the deletion is complete.
55
+ * @throws Will throw an error if the deletion operation fails.
56
+ */
57
+ deleteVector({ id }: DeleteVectorParams): Promise<void>;
58
+ disconnect(): Promise<void>;
29
59
  }
30
60
  export { CouchbaseVector }
31
61
  export { CouchbaseVector as CouchbaseVector_alias_1 }
32
62
 
63
+ declare type CouchbaseVectorParams = {
64
+ connectionString: string;
65
+ username: string;
66
+ password: string;
67
+ bucketName: string;
68
+ scopeName: string;
69
+ collectionName: string;
70
+ };
71
+ export { CouchbaseVectorParams }
72
+ export { CouchbaseVectorParams as CouchbaseVectorParams_alias_1 }
73
+
33
74
  declare const DISTANCE_MAPPING: Record<MastraMetric, CouchbaseMetric>;
34
75
  export { DISTANCE_MAPPING }
35
76
  export { DISTANCE_MAPPING as DISTANCE_MAPPING_alias_1 }
@@ -1,9 +1,13 @@
1
1
  import type { Collection } from 'couchbase';
2
2
  import type { CreateIndexParams } from '@mastra/core/vector';
3
+ import type { DeleteIndexParams } from '@mastra/core/vector';
4
+ import type { DeleteVectorParams } from '@mastra/core/vector';
5
+ import type { DescribeIndexParams } from '@mastra/core/vector';
3
6
  import type { IndexStats } from '@mastra/core/vector';
4
7
  import { MastraVector } from '@mastra/core/vector';
5
8
  import type { QueryResult } from '@mastra/core/vector';
6
9
  import type { QueryVectorParams } from '@mastra/core/vector';
10
+ import type { UpdateVectorParams } from '@mastra/core/vector';
7
11
  import type { UpsertVectorParams } from '@mastra/core/vector';
8
12
 
9
13
  declare type CouchbaseMetric = 'cosine' | 'l2_norm' | 'dot_product';
@@ -18,18 +22,55 @@ declare class CouchbaseVector extends MastraVector {
18
22
  private bucket;
19
23
  private scope;
20
24
  private vector_dimension;
21
- constructor(cnn_string: string, username: string, password: string, bucketName: string, scopeName: string, collectionName: string);
25
+ constructor({ connectionString, username, password, bucketName, scopeName, collectionName }: CouchbaseVectorParams);
22
26
  getCollection(): Promise<Collection>;
23
- createIndex(params: CreateIndexParams): Promise<void>;
24
- upsert(params: UpsertVectorParams): Promise<string[]>;
25
- query(params: QueryVectorParams): Promise<QueryResult[]>;
27
+ createIndex({ indexName, dimension, metric }: CreateIndexParams): Promise<void>;
28
+ upsert({ vectors, metadata, ids }: UpsertVectorParams): Promise<string[]>;
29
+ query({ indexName, queryVector, topK, includeVector }: QueryVectorParams): Promise<QueryResult[]>;
26
30
  listIndexes(): Promise<string[]>;
27
- describeIndex(indexName: string): Promise<IndexStats>;
28
- deleteIndex(indexName: string): Promise<void>;
31
+ /**
32
+ * Retrieves statistics about a vector index.
33
+ *
34
+ * @param {string} indexName - The name of the index to describe
35
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
36
+ */
37
+ describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats>;
38
+ deleteIndex({ indexName }: DeleteIndexParams): Promise<void>;
39
+ /**
40
+ * Updates a vector by its ID with the provided vector and/or metadata.
41
+ * @param indexName - The name of the index containing the vector.
42
+ * @param id - The ID of the vector to update.
43
+ * @param update - An object containing the vector and/or metadata to update.
44
+ * @param update.vector - An optional array of numbers representing the new vector.
45
+ * @param update.metadata - An optional record containing the new metadata.
46
+ * @returns A promise that resolves when the update is complete.
47
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
48
+ */
49
+ updateVector({ id, update }: UpdateVectorParams): Promise<void>;
50
+ /**
51
+ * Deletes a vector by its ID.
52
+ * @param indexName - The name of the index containing the vector.
53
+ * @param id - The ID of the vector to delete.
54
+ * @returns A promise that resolves when the deletion is complete.
55
+ * @throws Will throw an error if the deletion operation fails.
56
+ */
57
+ deleteVector({ id }: DeleteVectorParams): Promise<void>;
58
+ disconnect(): Promise<void>;
29
59
  }
30
60
  export { CouchbaseVector }
31
61
  export { CouchbaseVector as CouchbaseVector_alias_1 }
32
62
 
63
+ declare type CouchbaseVectorParams = {
64
+ connectionString: string;
65
+ username: string;
66
+ password: string;
67
+ bucketName: string;
68
+ scopeName: string;
69
+ collectionName: string;
70
+ };
71
+ export { CouchbaseVectorParams }
72
+ export { CouchbaseVectorParams as CouchbaseVectorParams_alias_1 }
73
+
33
74
  declare const DISTANCE_MAPPING: Record<MastraMetric, CouchbaseMetric>;
34
75
  export { DISTANCE_MAPPING }
35
76
  export { DISTANCE_MAPPING as DISTANCE_MAPPING_alias_1 }
package/dist/index.cjs CHANGED
@@ -19,9 +19,9 @@ var CouchbaseVector = class extends vector.MastraVector {
19
19
  bucket;
20
20
  scope;
21
21
  vector_dimension;
22
- constructor(cnn_string, username, password, bucketName, scopeName, collectionName) {
22
+ constructor({ connectionString, username, password, bucketName, scopeName, collectionName }) {
23
23
  super();
24
- const baseClusterPromise = couchbase.connect(cnn_string, {
24
+ const baseClusterPromise = couchbase.connect(connectionString, {
25
25
  username,
26
26
  password,
27
27
  configProfile: "wanDevelopment"
@@ -53,8 +53,7 @@ var CouchbaseVector = class extends vector.MastraVector {
53
53
  }
54
54
  return this.collection;
55
55
  }
56
- async createIndex(params) {
57
- const { indexName, dimension, metric = "dotproduct" } = params;
56
+ async createIndex({ indexName, dimension, metric = "dotproduct" }) {
58
57
  await this.getCollection();
59
58
  if (!Number.isInteger(dimension) || dimension <= 0) {
60
59
  throw new Error("Dimension must be a positive integer");
@@ -149,8 +148,7 @@ var CouchbaseVector = class extends vector.MastraVector {
149
148
  throw error;
150
149
  }
151
150
  }
152
- async upsert(params) {
153
- const { vectors, metadata, ids } = params;
151
+ async upsert({ vectors, metadata, ids }) {
154
152
  await this.getCollection();
155
153
  if (!vectors || vectors.length === 0) {
156
154
  throw new Error("No vectors provided");
@@ -181,10 +179,9 @@ var CouchbaseVector = class extends vector.MastraVector {
181
179
  await Promise.all(allPromises);
182
180
  return pointIds;
183
181
  }
184
- async query(params) {
185
- const { indexName, queryVector, topK = 10, includeVector = false } = params;
182
+ async query({ indexName, queryVector, topK = 10, includeVector = false }) {
186
183
  await this.getCollection();
187
- const index_stats = await this.describeIndex(indexName);
184
+ const index_stats = await this.describeIndex({ indexName });
188
185
  if (queryVector.length !== index_stats.dimension) {
189
186
  throw new Error(`Query vector dimension mismatch. Expected ${index_stats.dimension}, got ${queryVector.length}`);
190
187
  }
@@ -221,7 +218,13 @@ var CouchbaseVector = class extends vector.MastraVector {
221
218
  const indexes = await this.scope.searchIndexes().getAllIndexes();
222
219
  return indexes?.map((index) => index.name) || [];
223
220
  }
224
- async describeIndex(indexName) {
221
+ /**
222
+ * Retrieves statistics about a vector index.
223
+ *
224
+ * @param {string} indexName - The name of the index to describe
225
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
226
+ */
227
+ async describeIndex({ indexName }) {
225
228
  await this.getCollection();
226
229
  if (!(await this.listIndexes()).includes(indexName)) {
227
230
  throw new Error(`Index ${indexName} does not exist`);
@@ -238,7 +241,7 @@ var CouchbaseVector = class extends vector.MastraVector {
238
241
  )
239
242
  };
240
243
  }
241
- async deleteIndex(indexName) {
244
+ async deleteIndex({ indexName }) {
242
245
  await this.getCollection();
243
246
  if (!(await this.listIndexes()).includes(indexName)) {
244
247
  throw new Error(`Index ${indexName} does not exist`);
@@ -246,6 +249,62 @@ var CouchbaseVector = class extends vector.MastraVector {
246
249
  await this.scope.searchIndexes().dropIndex(indexName);
247
250
  this.vector_dimension = null;
248
251
  }
252
+ /**
253
+ * Updates a vector by its ID with the provided vector and/or metadata.
254
+ * @param indexName - The name of the index containing the vector.
255
+ * @param id - The ID of the vector to update.
256
+ * @param update - An object containing the vector and/or metadata to update.
257
+ * @param update.vector - An optional array of numbers representing the new vector.
258
+ * @param update.metadata - An optional record containing the new metadata.
259
+ * @returns A promise that resolves when the update is complete.
260
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
261
+ */
262
+ async updateVector({ id, update }) {
263
+ if (!update.vector && !update.metadata) {
264
+ throw new Error("No updates provided");
265
+ }
266
+ if (update.vector && this.vector_dimension && update.vector.length !== this.vector_dimension) {
267
+ throw new Error("Vector dimension mismatch");
268
+ }
269
+ const collection = await this.getCollection();
270
+ try {
271
+ await collection.get(id);
272
+ } catch (err) {
273
+ if (err.code === 13 || err.message?.includes("document not found")) {
274
+ throw new Error(`Vector with id ${id} does not exist`);
275
+ }
276
+ throw err;
277
+ }
278
+ const specs = [];
279
+ if (update.vector) specs.push(couchbase.MutateInSpec.replace("embedding", update.vector));
280
+ if (update.metadata) specs.push(couchbase.MutateInSpec.replace("metadata", update.metadata));
281
+ await collection.mutateIn(id, specs);
282
+ }
283
+ /**
284
+ * Deletes a vector by its ID.
285
+ * @param indexName - The name of the index containing the vector.
286
+ * @param id - The ID of the vector to delete.
287
+ * @returns A promise that resolves when the deletion is complete.
288
+ * @throws Will throw an error if the deletion operation fails.
289
+ */
290
+ async deleteVector({ id }) {
291
+ const collection = await this.getCollection();
292
+ try {
293
+ await collection.get(id);
294
+ } catch (err) {
295
+ if (err.code === 13 || err.message?.includes("document not found")) {
296
+ throw new Error(`Vector with id ${id} does not exist`);
297
+ }
298
+ throw err;
299
+ }
300
+ await collection.remove(id);
301
+ }
302
+ async disconnect() {
303
+ if (!this.cluster) {
304
+ return;
305
+ }
306
+ await this.cluster.close();
307
+ }
249
308
  };
250
309
 
251
310
  exports.CouchbaseVector = CouchbaseVector;
package/dist/index.d.cts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { DISTANCE_MAPPING } from './_tsup-dts-rollup.cjs';
2
+ export { CouchbaseVectorParams } from './_tsup-dts-rollup.cjs';
2
3
  export { CouchbaseVector } from './_tsup-dts-rollup.cjs';
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { DISTANCE_MAPPING } from './_tsup-dts-rollup.js';
2
+ export { CouchbaseVectorParams } from './_tsup-dts-rollup.js';
2
3
  export { CouchbaseVector } from './_tsup-dts-rollup.js';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MastraVector } from '@mastra/core/vector';
2
- import { connect, SearchRequest, VectorSearch, VectorQuery } from 'couchbase';
2
+ import { connect, SearchRequest, VectorSearch, VectorQuery, MutateInSpec } from 'couchbase';
3
3
 
4
4
  // src/vector/index.ts
5
5
  var DISTANCE_MAPPING = {
@@ -17,9 +17,9 @@ var CouchbaseVector = class extends MastraVector {
17
17
  bucket;
18
18
  scope;
19
19
  vector_dimension;
20
- constructor(cnn_string, username, password, bucketName, scopeName, collectionName) {
20
+ constructor({ connectionString, username, password, bucketName, scopeName, collectionName }) {
21
21
  super();
22
- const baseClusterPromise = connect(cnn_string, {
22
+ const baseClusterPromise = connect(connectionString, {
23
23
  username,
24
24
  password,
25
25
  configProfile: "wanDevelopment"
@@ -51,8 +51,7 @@ var CouchbaseVector = class extends MastraVector {
51
51
  }
52
52
  return this.collection;
53
53
  }
54
- async createIndex(params) {
55
- const { indexName, dimension, metric = "dotproduct" } = params;
54
+ async createIndex({ indexName, dimension, metric = "dotproduct" }) {
56
55
  await this.getCollection();
57
56
  if (!Number.isInteger(dimension) || dimension <= 0) {
58
57
  throw new Error("Dimension must be a positive integer");
@@ -147,8 +146,7 @@ var CouchbaseVector = class extends MastraVector {
147
146
  throw error;
148
147
  }
149
148
  }
150
- async upsert(params) {
151
- const { vectors, metadata, ids } = params;
149
+ async upsert({ vectors, metadata, ids }) {
152
150
  await this.getCollection();
153
151
  if (!vectors || vectors.length === 0) {
154
152
  throw new Error("No vectors provided");
@@ -179,10 +177,9 @@ var CouchbaseVector = class extends MastraVector {
179
177
  await Promise.all(allPromises);
180
178
  return pointIds;
181
179
  }
182
- async query(params) {
183
- const { indexName, queryVector, topK = 10, includeVector = false } = params;
180
+ async query({ indexName, queryVector, topK = 10, includeVector = false }) {
184
181
  await this.getCollection();
185
- const index_stats = await this.describeIndex(indexName);
182
+ const index_stats = await this.describeIndex({ indexName });
186
183
  if (queryVector.length !== index_stats.dimension) {
187
184
  throw new Error(`Query vector dimension mismatch. Expected ${index_stats.dimension}, got ${queryVector.length}`);
188
185
  }
@@ -219,7 +216,13 @@ var CouchbaseVector = class extends MastraVector {
219
216
  const indexes = await this.scope.searchIndexes().getAllIndexes();
220
217
  return indexes?.map((index) => index.name) || [];
221
218
  }
222
- async describeIndex(indexName) {
219
+ /**
220
+ * Retrieves statistics about a vector index.
221
+ *
222
+ * @param {string} indexName - The name of the index to describe
223
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
224
+ */
225
+ async describeIndex({ indexName }) {
223
226
  await this.getCollection();
224
227
  if (!(await this.listIndexes()).includes(indexName)) {
225
228
  throw new Error(`Index ${indexName} does not exist`);
@@ -236,7 +239,7 @@ var CouchbaseVector = class extends MastraVector {
236
239
  )
237
240
  };
238
241
  }
239
- async deleteIndex(indexName) {
242
+ async deleteIndex({ indexName }) {
240
243
  await this.getCollection();
241
244
  if (!(await this.listIndexes()).includes(indexName)) {
242
245
  throw new Error(`Index ${indexName} does not exist`);
@@ -244,6 +247,62 @@ var CouchbaseVector = class extends MastraVector {
244
247
  await this.scope.searchIndexes().dropIndex(indexName);
245
248
  this.vector_dimension = null;
246
249
  }
250
+ /**
251
+ * Updates a vector by its ID with the provided vector and/or metadata.
252
+ * @param indexName - The name of the index containing the vector.
253
+ * @param id - The ID of the vector to update.
254
+ * @param update - An object containing the vector and/or metadata to update.
255
+ * @param update.vector - An optional array of numbers representing the new vector.
256
+ * @param update.metadata - An optional record containing the new metadata.
257
+ * @returns A promise that resolves when the update is complete.
258
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
259
+ */
260
+ async updateVector({ id, update }) {
261
+ if (!update.vector && !update.metadata) {
262
+ throw new Error("No updates provided");
263
+ }
264
+ if (update.vector && this.vector_dimension && update.vector.length !== this.vector_dimension) {
265
+ throw new Error("Vector dimension mismatch");
266
+ }
267
+ const collection = await this.getCollection();
268
+ try {
269
+ await collection.get(id);
270
+ } catch (err) {
271
+ if (err.code === 13 || err.message?.includes("document not found")) {
272
+ throw new Error(`Vector with id ${id} does not exist`);
273
+ }
274
+ throw err;
275
+ }
276
+ const specs = [];
277
+ if (update.vector) specs.push(MutateInSpec.replace("embedding", update.vector));
278
+ if (update.metadata) specs.push(MutateInSpec.replace("metadata", update.metadata));
279
+ await collection.mutateIn(id, specs);
280
+ }
281
+ /**
282
+ * Deletes a vector by its ID.
283
+ * @param indexName - The name of the index containing the vector.
284
+ * @param id - The ID of the vector to delete.
285
+ * @returns A promise that resolves when the deletion is complete.
286
+ * @throws Will throw an error if the deletion operation fails.
287
+ */
288
+ async deleteVector({ id }) {
289
+ const collection = await this.getCollection();
290
+ try {
291
+ await collection.get(id);
292
+ } catch (err) {
293
+ if (err.code === 13 || err.message?.includes("document not found")) {
294
+ throw new Error(`Vector with id ${id} does not exist`);
295
+ }
296
+ throw err;
297
+ }
298
+ await collection.remove(id);
299
+ }
300
+ async disconnect() {
301
+ if (!this.cluster) {
302
+ return;
303
+ }
304
+ await this.cluster.close();
305
+ }
247
306
  };
248
307
 
249
308
  export { CouchbaseVector, DISTANCE_MAPPING };
@@ -2,20 +2,20 @@ services:
2
2
  mastra_couchbase_testing:
3
3
  image: couchbase:enterprise-7.6.4
4
4
  ports:
5
- - "8091-8095:8091-8095"
6
- - "11210:11210"
7
- - "9102:9102"
5
+ - '8091-8095:8091-8095'
6
+ - '11210:11210'
7
+ - '9102:9102'
8
8
  expose:
9
- - "8091"
10
- - "8092"
11
- - "8093"
12
- - "8094"
13
- - "8095"
14
- - "9102"
15
- - "11210"
9
+ - '8091'
10
+ - '8092'
11
+ - '8093'
12
+ - '8094'
13
+ - '8095'
14
+ - '9102'
15
+ - '11210'
16
16
  healthcheck: # checks couchbase server is up
17
- test: ["CMD", "curl", "-v", "http://localhost:8091/pools"]
17
+ test: ['CMD', 'curl', '-v', 'http://localhost:8091/pools']
18
18
  interval: 20s
19
19
  timeout: 20s
20
20
  retries: 5
21
- container_name: mastra_couchbase_testing
21
+ container_name: mastra_couchbase_testing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/couchbase",
3
- "version": "0.0.0-redis-cloud-transporter-20250508203756",
3
+ "version": "0.0.0-taofeeqInngest-20250603090617",
4
4
  "description": "Couchbase vector store provider for Mastra",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -19,8 +19,7 @@
19
19
  "./package.json": "./package.json"
20
20
  },
21
21
  "dependencies": {
22
- "couchbase": "^4.4.5",
23
- "@mastra/core": "0.0.0-redis-cloud-transporter-20250508203756"
22
+ "couchbase": "^4.4.5"
24
23
  },
25
24
  "devDependencies": {
26
25
  "@microsoft/api-extractor": "^7.52.1",
@@ -32,7 +31,11 @@
32
31
  "tsup": "^8.4.0",
33
32
  "typescript": "^5.8.2",
34
33
  "vitest": "^3.0.9",
35
- "@internal/lint": "0.0.0-redis-cloud-transporter-20250508203756"
34
+ "@internal/lint": "0.0.0-taofeeqInngest-20250603090617",
35
+ "@mastra/core": "0.0.0-taofeeqInngest-20250603090617"
36
+ },
37
+ "peerDependencies": {
38
+ "@mastra/core": "^0.10.0-alpha.0"
36
39
  },
37
40
  "scripts": {
38
41
  "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
@@ -173,14 +173,14 @@ describe('Integration Testing CouchbaseVector', async () => {
173
173
 
174
174
  describe('Connection', () => {
175
175
  it('should connect to couchbase', async () => {
176
- couchbase_client = new CouchbaseVector(
176
+ couchbase_client = new CouchbaseVector({
177
177
  connectionString,
178
178
  username,
179
179
  password,
180
- test_bucketName,
181
- test_scopeName,
182
- test_collectionName,
183
- );
180
+ bucketName: test_bucketName,
181
+ scopeName: test_scopeName,
182
+ collectionName: test_collectionName,
183
+ });
184
184
  expect(couchbase_client).toBeDefined();
185
185
  const collection = await couchbase_client.getCollection();
186
186
  expect(collection).toBeDefined();
@@ -211,14 +211,14 @@ describe('Integration Testing CouchbaseVector', async () => {
211
211
  }, 50000);
212
212
 
213
213
  it('should describe index', async () => {
214
- const stats = await couchbase_client.describeIndex(test_indexName);
214
+ const stats = await couchbase_client.describeIndex({ indexName: test_indexName });
215
215
  expect(stats.dimension).toBe(dimension);
216
216
  expect(stats.metric).toBe('euclidean'); // similiarity(=="l2_norm") is mapped to euclidean in couchbase
217
217
  expect(typeof stats.count).toBe('number');
218
218
  }, 50000);
219
219
 
220
220
  it('should delete index', async () => {
221
- await couchbase_client.deleteIndex(test_indexName);
221
+ await couchbase_client.deleteIndex({ indexName: test_indexName });
222
222
  await new Promise(resolve => setTimeout(resolve, 5000));
223
223
  await expect(scope.searchIndexes().getIndex(test_indexName)).rejects.toThrowError();
224
224
  }, 50000);
@@ -246,7 +246,7 @@ describe('Integration Testing CouchbaseVector', async () => {
246
246
  }, 50000);
247
247
 
248
248
  afterAll(async () => {
249
- await couchbase_client.deleteIndex(test_indexName);
249
+ await couchbase_client.deleteIndex({ indexName: test_indexName });
250
250
  await new Promise(resolve => setTimeout(resolve, 5000));
251
251
  }, 50000);
252
252
 
@@ -380,6 +380,120 @@ describe('Integration Testing CouchbaseVector', async () => {
380
380
  }),
381
381
  ).rejects.toThrow('Including vectors in search results is not yet supported by the Couchbase vector store');
382
382
  }, 50000);
383
+
384
+ it('should upsert vectors with generated ids', async () => {
385
+ const ids = await couchbase_client.upsert({ indexName: test_indexName, vectors: testVectors });
386
+ expect(ids).toHaveLength(testVectors.length);
387
+ ids.forEach(id => expect(typeof id).toBe('string'));
388
+
389
+ // Count is not supported by Couchbase
390
+ const stats = await couchbase_client.describeIndex({ indexName: test_indexName });
391
+ expect(stats.count).toBe(-1);
392
+ });
393
+
394
+ it('should update existing vectors', async () => {
395
+ // Initial upsert
396
+ await couchbase_client.upsert({
397
+ indexName: test_indexName,
398
+ vectors: testVectors,
399
+ metadata: testMetadata,
400
+ ids: testVectorIds,
401
+ });
402
+
403
+ // Update first vector
404
+ const updatedVector = [[0.5, 0.5, 0.0]];
405
+ const updatedMetadata = [{ label: 'updated-x-axis' }];
406
+ await couchbase_client.upsert({
407
+ indexName: test_indexName,
408
+ vectors: updatedVector,
409
+ metadata: updatedMetadata,
410
+ ids: [testVectorIds?.[0]!],
411
+ });
412
+
413
+ // Verify update
414
+ const result = await collection.get(testVectorIds?.[0]!);
415
+ expect(result.content.embedding).toEqual(updatedVector[0]);
416
+ expect(result.content.metadata).toEqual(updatedMetadata[0]);
417
+ });
418
+
419
+ it('should update the vector by id', async () => {
420
+ const ids = await couchbase_client.upsert({ indexName: test_indexName, vectors: testVectors });
421
+ expect(ids).toHaveLength(3);
422
+
423
+ const idToBeUpdated = ids[0];
424
+ const newVector = [1, 2, 3];
425
+ const newMetaData = {
426
+ test: 'updates',
427
+ };
428
+
429
+ const update = {
430
+ vector: newVector,
431
+ metadata: newMetaData,
432
+ };
433
+
434
+ await couchbase_client.updateVector({ indexName: test_indexName, id: idToBeUpdated, update });
435
+
436
+ const result = await collection.get(idToBeUpdated);
437
+ expect(result.content.embedding).toEqual(newVector);
438
+ expect(result.content.metadata).toEqual(newMetaData);
439
+ });
440
+
441
+ it('should only update the metadata by id', async () => {
442
+ const ids = await couchbase_client.upsert({ indexName: test_indexName, vectors: testVectors });
443
+ expect(ids).toHaveLength(3);
444
+
445
+ const idToBeUpdated = ids[0];
446
+ const newMetaData = {
447
+ test: 'updates',
448
+ };
449
+
450
+ const update = {
451
+ metadata: newMetaData,
452
+ };
453
+
454
+ await couchbase_client.updateVector({ indexName: test_indexName, id: idToBeUpdated, update });
455
+
456
+ const result = await collection.get(idToBeUpdated);
457
+ expect(result.content.embedding).toEqual(testVectors[0]);
458
+ expect(result.content.metadata).toEqual(newMetaData);
459
+ });
460
+
461
+ it('should only update vector embeddings by id', async () => {
462
+ const ids = await couchbase_client.upsert({ indexName: test_indexName, vectors: testVectors });
463
+ expect(ids).toHaveLength(3);
464
+
465
+ const idToBeUpdated = ids[0];
466
+ const newVector = [1, 2, 3];
467
+
468
+ const update = {
469
+ vector: newVector,
470
+ };
471
+
472
+ await couchbase_client.updateVector({ indexName: test_indexName, id: idToBeUpdated, update });
473
+
474
+ const result = await collection.get(idToBeUpdated);
475
+ expect(result.content.embedding).toEqual(newVector);
476
+ });
477
+
478
+ it('should throw exception when no updates are given', async () => {
479
+ await expect(couchbase_client.updateVector({ indexName: test_indexName, id: 'id', update: {} })).rejects.toThrow(
480
+ 'No updates provided',
481
+ );
482
+ });
483
+
484
+ it('should delete the vector by id', async () => {
485
+ const ids = await couchbase_client.upsert({ indexName: test_indexName, vectors: testVectors });
486
+ expect(ids).toHaveLength(3);
487
+ const idToBeDeleted = ids[0];
488
+
489
+ await couchbase_client.deleteVector({ indexName: test_indexName, id: idToBeDeleted });
490
+
491
+ try {
492
+ await collection.get(idToBeDeleted);
493
+ } catch (error) {
494
+ expect(error).toBeInstanceOf(Error);
495
+ }
496
+ });
383
497
  });
384
498
 
385
499
  describe('Error Cases and Edge Cases', () => {
@@ -409,7 +523,7 @@ describe('Integration Testing CouchbaseVector', async () => {
409
523
  expect(allIndexes.find(idx => idx.name === nonExistentIndex)).toBeUndefined();
410
524
 
411
525
  // Now test the couchbase_client method
412
- await expect(couchbase_client.describeIndex(nonExistentIndex)).rejects.toThrow();
526
+ await expect(couchbase_client.describeIndex({ indexName: nonExistentIndex })).rejects.toThrow();
413
527
  }, 50000);
414
528
 
415
529
  it('should throw error when deleting a non-existent index', async () => {
@@ -420,7 +534,7 @@ describe('Integration Testing CouchbaseVector', async () => {
420
534
  expect(allIndexes.find(idx => idx.name === nonExistentIndex)).toBeUndefined();
421
535
 
422
536
  // Now test the couchbase_client method
423
- await expect(couchbase_client.deleteIndex(nonExistentIndex)).rejects.toThrow();
537
+ await expect(couchbase_client.deleteIndex({ indexName: nonExistentIndex })).rejects.toThrow();
424
538
  }, 50000);
425
539
 
426
540
  it('should throw error for empty vectors array in upsert', async () => {
@@ -489,7 +603,7 @@ describe('Integration Testing CouchbaseVector', async () => {
489
603
  infoSpy.mockRestore();
490
604
  warnSpy.mockRestore();
491
605
  // Cleanup
492
- await couchbase_client.deleteIndex(duplicateIndexName);
606
+ await couchbase_client.deleteIndex({ indexName: duplicateIndexName });
493
607
  }
494
608
  }, 50000);
495
609
  });
@@ -499,7 +613,7 @@ describe('Integration Testing CouchbaseVector', async () => {
499
613
  const indexes = await couchbase_client.listIndexes();
500
614
  if (indexes.length > 0) {
501
615
  for (const index of indexes) {
502
- await couchbase_client.deleteIndex(index);
616
+ await couchbase_client.deleteIndex({ indexName: index });
503
617
  await new Promise(resolve => setTimeout(resolve, 5000));
504
618
  }
505
619
  }
@@ -562,7 +676,7 @@ describe('Integration Testing CouchbaseVector', async () => {
562
676
  expect((couchbase_client as any).vector_dimension).toBe(testDimension);
563
677
 
564
678
  // Delete the index
565
- await couchbase_client.deleteIndex(testIndexName);
679
+ await couchbase_client.deleteIndex({ indexName: testIndexName });
566
680
  await new Promise(resolve => setTimeout(resolve, 5000));
567
681
 
568
682
  // Verify dimension is reset
@@ -578,7 +692,7 @@ describe('Integration Testing CouchbaseVector', async () => {
578
692
  const indexes = await couchbase_client.listIndexes();
579
693
  if (indexes.length > 0) {
580
694
  for (const index of indexes) {
581
- await couchbase_client.deleteIndex(index);
695
+ await couchbase_client.deleteIndex({ indexName: index });
582
696
  await new Promise(resolve => setTimeout(resolve, 5000));
583
697
  }
584
698
  }
@@ -607,11 +721,11 @@ describe('Integration Testing CouchbaseVector', async () => {
607
721
  expect(similarityParam).toBe(couchbaseMetric);
608
722
 
609
723
  // Verify through our API
610
- const stats = await couchbase_client.describeIndex(testIndexName);
724
+ const stats = await couchbase_client.describeIndex({ indexName: testIndexName });
611
725
  expect(stats.metric).toBe(mastraMetric);
612
726
 
613
727
  // Clean up
614
- await couchbase_client.deleteIndex(testIndexName);
728
+ await couchbase_client.deleteIndex({ indexName: testIndexName });
615
729
  await new Promise(resolve => setTimeout(resolve, 5000));
616
730
  }
617
731
  }, 50000);
@@ -5,9 +5,13 @@ import type {
5
5
  CreateIndexParams,
6
6
  UpsertVectorParams,
7
7
  QueryVectorParams,
8
+ DescribeIndexParams,
9
+ DeleteIndexParams,
10
+ DeleteVectorParams,
11
+ UpdateVectorParams,
8
12
  } from '@mastra/core/vector';
9
13
  import type { Bucket, Cluster, Collection, Scope } from 'couchbase';
10
- import { connect, SearchRequest, VectorQuery, VectorSearch } from 'couchbase';
14
+ import { MutateInSpec, connect, SearchRequest, VectorQuery, VectorSearch } from 'couchbase';
11
15
 
12
16
  type MastraMetric = 'cosine' | 'euclidean' | 'dotproduct';
13
17
  type CouchbaseMetric = 'cosine' | 'l2_norm' | 'dot_product';
@@ -17,6 +21,15 @@ export const DISTANCE_MAPPING: Record<MastraMetric, CouchbaseMetric> = {
17
21
  dotproduct: 'dot_product',
18
22
  };
19
23
 
24
+ export type CouchbaseVectorParams = {
25
+ connectionString: string;
26
+ username: string;
27
+ password: string;
28
+ bucketName: string;
29
+ scopeName: string;
30
+ collectionName: string;
31
+ };
32
+
20
33
  export class CouchbaseVector extends MastraVector {
21
34
  private clusterPromise: Promise<Cluster>;
22
35
  private cluster: Cluster;
@@ -28,17 +41,10 @@ export class CouchbaseVector extends MastraVector {
28
41
  private scope: Scope;
29
42
  private vector_dimension: number;
30
43
 
31
- constructor(
32
- cnn_string: string,
33
- username: string,
34
- password: string,
35
- bucketName: string,
36
- scopeName: string,
37
- collectionName: string,
38
- ) {
44
+ constructor({ connectionString, username, password, bucketName, scopeName, collectionName }: CouchbaseVectorParams) {
39
45
  super();
40
46
 
41
- const baseClusterPromise = connect(cnn_string, {
47
+ const baseClusterPromise = connect(connectionString, {
42
48
  username,
43
49
  password,
44
50
  configProfile: 'wanDevelopment',
@@ -76,8 +82,7 @@ export class CouchbaseVector extends MastraVector {
76
82
  return this.collection;
77
83
  }
78
84
 
79
- async createIndex(params: CreateIndexParams): Promise<void> {
80
- const { indexName, dimension, metric = 'dotproduct' as MastraMetric } = params;
85
+ async createIndex({ indexName, dimension, metric = 'dotproduct' as MastraMetric }: CreateIndexParams): Promise<void> {
81
86
  await this.getCollection();
82
87
 
83
88
  if (!Number.isInteger(dimension) || dimension <= 0) {
@@ -172,8 +177,7 @@ export class CouchbaseVector extends MastraVector {
172
177
  }
173
178
  }
174
179
 
175
- async upsert(params: UpsertVectorParams): Promise<string[]> {
176
- const { vectors, metadata, ids } = params;
180
+ async upsert({ vectors, metadata, ids }: UpsertVectorParams): Promise<string[]> {
177
181
  await this.getCollection();
178
182
 
179
183
  if (!vectors || vectors.length === 0) {
@@ -210,12 +214,10 @@ export class CouchbaseVector extends MastraVector {
210
214
  return pointIds;
211
215
  }
212
216
 
213
- async query(params: QueryVectorParams): Promise<QueryResult[]> {
214
- const { indexName, queryVector, topK = 10, includeVector = false } = params;
215
-
217
+ async query({ indexName, queryVector, topK = 10, includeVector = false }: QueryVectorParams): Promise<QueryResult[]> {
216
218
  await this.getCollection();
217
219
 
218
- const index_stats = await this.describeIndex(indexName);
220
+ const index_stats = await this.describeIndex({ indexName });
219
221
  if (queryVector.length !== index_stats.dimension) {
220
222
  throw new Error(`Query vector dimension mismatch. Expected ${index_stats.dimension}, got ${queryVector.length}`);
221
223
  }
@@ -255,7 +257,13 @@ export class CouchbaseVector extends MastraVector {
255
257
  return indexes?.map(index => index.name) || [];
256
258
  }
257
259
 
258
- async describeIndex(indexName: string): Promise<IndexStats> {
260
+ /**
261
+ * Retrieves statistics about a vector index.
262
+ *
263
+ * @param {string} indexName - The name of the index to describe
264
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
265
+ */
266
+ async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {
259
267
  await this.getCollection();
260
268
  if (!(await this.listIndexes()).includes(indexName)) {
261
269
  throw new Error(`Index ${indexName} does not exist`);
@@ -276,7 +284,7 @@ export class CouchbaseVector extends MastraVector {
276
284
  };
277
285
  }
278
286
 
279
- async deleteIndex(indexName: string): Promise<void> {
287
+ async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {
280
288
  await this.getCollection();
281
289
  if (!(await this.listIndexes()).includes(indexName)) {
282
290
  throw new Error(`Index ${indexName} does not exist`);
@@ -284,4 +292,70 @@ export class CouchbaseVector extends MastraVector {
284
292
  await this.scope.searchIndexes().dropIndex(indexName);
285
293
  this.vector_dimension = null as unknown as number;
286
294
  }
295
+
296
+ /**
297
+ * Updates a vector by its ID with the provided vector and/or metadata.
298
+ * @param indexName - The name of the index containing the vector.
299
+ * @param id - The ID of the vector to update.
300
+ * @param update - An object containing the vector and/or metadata to update.
301
+ * @param update.vector - An optional array of numbers representing the new vector.
302
+ * @param update.metadata - An optional record containing the new metadata.
303
+ * @returns A promise that resolves when the update is complete.
304
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
305
+ */
306
+ async updateVector({ id, update }: UpdateVectorParams): Promise<void> {
307
+ if (!update.vector && !update.metadata) {
308
+ throw new Error('No updates provided');
309
+ }
310
+ if (update.vector && this.vector_dimension && update.vector.length !== this.vector_dimension) {
311
+ throw new Error('Vector dimension mismatch');
312
+ }
313
+ const collection = await this.getCollection();
314
+
315
+ // Check if document exists
316
+ try {
317
+ await collection.get(id);
318
+ } catch (err: any) {
319
+ if (err.code === 13 || err.message?.includes('document not found')) {
320
+ throw new Error(`Vector with id ${id} does not exist`);
321
+ }
322
+ throw err;
323
+ }
324
+
325
+ const specs: MutateInSpec[] = [];
326
+ if (update.vector) specs.push(MutateInSpec.replace('embedding', update.vector));
327
+ if (update.metadata) specs.push(MutateInSpec.replace('metadata', update.metadata));
328
+
329
+ await collection.mutateIn(id, specs);
330
+ }
331
+
332
+ /**
333
+ * Deletes a vector by its ID.
334
+ * @param indexName - The name of the index containing the vector.
335
+ * @param id - The ID of the vector to delete.
336
+ * @returns A promise that resolves when the deletion is complete.
337
+ * @throws Will throw an error if the deletion operation fails.
338
+ */
339
+ async deleteVector({ id }: DeleteVectorParams): Promise<void> {
340
+ const collection = await this.getCollection();
341
+
342
+ // Check if document exists
343
+ try {
344
+ await collection.get(id);
345
+ } catch (err: any) {
346
+ if (err.code === 13 || err.message?.includes('document not found')) {
347
+ throw new Error(`Vector with id ${id} does not exist`);
348
+ }
349
+ throw err;
350
+ }
351
+
352
+ await collection.remove(id);
353
+ }
354
+
355
+ async disconnect() {
356
+ if (!this.cluster) {
357
+ return;
358
+ }
359
+ await this.cluster.close();
360
+ }
287
361
  }
@@ -165,14 +165,14 @@ describe('Unit Testing CouchbaseVector', () => {
165
165
  });
166
166
 
167
167
  it('should connect to couchbase', async () => {
168
- couchbase_client = new CouchbaseVector(
169
- 'COUCHBASE_CONNECTION_STRING',
170
- 'COUCHBASE_USERNAME',
171
- 'COUCHBASE_PASSWORD',
172
- test_bucketName,
173
- test_scopeName,
174
- test_collectionName,
175
- );
168
+ couchbase_client = new CouchbaseVector({
169
+ connectionString: 'COUCHBASE_CONNECTION_STRING',
170
+ username: 'COUCHBASE_USERNAME',
171
+ password: 'COUCHBASE_PASSWORD',
172
+ bucketName: test_bucketName,
173
+ scopeName: test_scopeName,
174
+ collectionName: test_collectionName,
175
+ });
176
176
  expect(mockCouchbaseConnectFn).toHaveBeenCalledTimes(1);
177
177
  expect(mockCouchbaseConnectFn).toHaveBeenCalledWith('COUCHBASE_CONNECTION_STRING', {
178
178
  username: 'COUCHBASE_USERNAME',
@@ -200,14 +200,14 @@ describe('Unit Testing CouchbaseVector', () => {
200
200
  describe('Index Operations', () => {
201
201
  beforeAll(async () => {
202
202
  clearAllMocks();
203
- couchbase_client = new CouchbaseVector(
204
- 'COUCHBASE_CONNECTION_STRING',
205
- 'COUCHBASE_USERNAME',
206
- 'COUCHBASE_PASSWORD',
207
- test_bucketName,
208
- test_scopeName,
209
- test_collectionName,
210
- );
203
+ couchbase_client = new CouchbaseVector({
204
+ connectionString: 'COUCHBASE_CONNECTION_STRING',
205
+ username: 'COUCHBASE_USERNAME',
206
+ password: 'COUCHBASE_PASSWORD',
207
+ bucketName: test_bucketName,
208
+ scopeName: test_scopeName,
209
+ collectionName: test_collectionName,
210
+ });
211
211
  await couchbase_client.getCollection();
212
212
  });
213
213
 
@@ -311,7 +311,7 @@ describe('Unit Testing CouchbaseVector', () => {
311
311
  }, 50000);
312
312
 
313
313
  it('should describe index', async () => {
314
- const stats = await couchbase_client.describeIndex(test_indexName);
314
+ const stats = await couchbase_client.describeIndex({ indexName: test_indexName });
315
315
 
316
316
  expect(mockScopeSearchIndexesFn).toHaveBeenCalledTimes(2);
317
317
 
@@ -328,7 +328,7 @@ describe('Unit Testing CouchbaseVector', () => {
328
328
  }, 50000);
329
329
 
330
330
  it('should delete index', async () => {
331
- await couchbase_client.deleteIndex(test_indexName);
331
+ await couchbase_client.deleteIndex({ indexName: test_indexName });
332
332
 
333
333
  expect(mockScopeSearchIndexesFn).toHaveBeenCalledTimes(2);
334
334
 
@@ -343,14 +343,14 @@ describe('Unit Testing CouchbaseVector', () => {
343
343
 
344
344
  describe('Vector Operations', () => {
345
345
  beforeAll(async () => {
346
- couchbase_client = new CouchbaseVector(
347
- 'COUCHBASE_CONNECTION_STRING',
348
- 'COUCHBASE_USERNAME',
349
- 'COUCHBASE_PASSWORD',
350
- test_bucketName,
351
- test_scopeName,
352
- test_collectionName,
353
- );
346
+ couchbase_client = new CouchbaseVector({
347
+ connectionString: 'COUCHBASE_CONNECTION_STRING',
348
+ username: 'COUCHBASE_USERNAME',
349
+ password: 'COUCHBASE_PASSWORD',
350
+ bucketName: test_bucketName,
351
+ scopeName: test_scopeName,
352
+ collectionName: test_collectionName,
353
+ });
354
354
 
355
355
  await couchbase_client.getCollection();
356
356
  });
@@ -510,14 +510,14 @@ describe('Unit Testing CouchbaseVector', () => {
510
510
  describe('Error Cases and Edge Cases', () => {
511
511
  beforeAll(async () => {
512
512
  clearAllMocks();
513
- couchbase_client = new CouchbaseVector(
514
- 'COUCHBASE_CONNECTION_STRING',
515
- 'COUCHBASE_USERNAME',
516
- 'COUCHBASE_PASSWORD',
517
- test_bucketName,
518
- test_scopeName,
519
- test_collectionName,
520
- );
513
+ couchbase_client = new CouchbaseVector({
514
+ connectionString: 'COUCHBASE_CONNECTION_STRING',
515
+ username: 'COUCHBASE_USERNAME',
516
+ password: 'COUCHBASE_PASSWORD',
517
+ bucketName: test_bucketName,
518
+ scopeName: test_scopeName,
519
+ collectionName: test_collectionName,
520
+ });
521
521
  await couchbase_client.getCollection();
522
522
  });
523
523
 
@@ -542,13 +542,13 @@ describe('Unit Testing CouchbaseVector', () => {
542
542
  });
543
543
 
544
544
  it('should throw error when describing a non-existent index', async () => {
545
- await expect(couchbase_client.describeIndex('non_existent_index')).rejects.toThrow(
545
+ await expect(couchbase_client.describeIndex({ indexName: 'non_existent_index' })).rejects.toThrow(
546
546
  `Index non_existent_index does not exist`,
547
547
  );
548
548
  });
549
549
 
550
550
  it('should throw error when deleting a non-existent index', async () => {
551
- await expect(couchbase_client.deleteIndex('non_existent_index')).rejects.toThrow(
551
+ await expect(couchbase_client.deleteIndex({ indexName: 'non_existent_index' })).rejects.toThrow(
552
552
  `Index non_existent_index does not exist`,
553
553
  );
554
554
  });
@@ -577,14 +577,14 @@ describe('Unit Testing CouchbaseVector', () => {
577
577
  describe('Vector Dimension Tracking', () => {
578
578
  beforeEach(async () => {
579
579
  clearAllMocks();
580
- couchbase_client = new CouchbaseVector(
581
- 'COUCHBASE_CONNECTION_STRING',
582
- 'COUCHBASE_USERNAME',
583
- 'COUCHBASE_PASSWORD',
584
- test_bucketName,
585
- test_scopeName,
586
- test_collectionName,
587
- );
580
+ couchbase_client = new CouchbaseVector({
581
+ connectionString: 'COUCHBASE_CONNECTION_STRING',
582
+ username: 'COUCHBASE_USERNAME',
583
+ password: 'COUCHBASE_PASSWORD',
584
+ bucketName: test_bucketName,
585
+ scopeName: test_scopeName,
586
+ collectionName: test_collectionName,
587
+ });
588
588
  await couchbase_client.getCollection();
589
589
  });
590
590
 
@@ -637,7 +637,7 @@ describe('Unit Testing CouchbaseVector', () => {
637
637
  clearAllMocks();
638
638
 
639
639
  // Delete the index
640
- await couchbase_client.deleteIndex(test_indexName);
640
+ await couchbase_client.deleteIndex({ indexName: test_indexName });
641
641
 
642
642
  // Verify dimension is reset
643
643
  expect((couchbase_client as any).vector_dimension).toBeNull();
@@ -647,14 +647,14 @@ describe('Unit Testing CouchbaseVector', () => {
647
647
  describe('Implementation Details', () => {
648
648
  beforeEach(async () => {
649
649
  clearAllMocks();
650
- couchbase_client = new CouchbaseVector(
651
- 'COUCHBASE_CONNECTION_STRING',
652
- 'COUCHBASE_USERNAME',
653
- 'COUCHBASE_PASSWORD',
654
- test_bucketName,
655
- test_scopeName,
656
- test_collectionName,
657
- );
650
+ couchbase_client = new CouchbaseVector({
651
+ connectionString: 'COUCHBASE_CONNECTION_STRING',
652
+ username: 'COUCHBASE_USERNAME',
653
+ password: 'COUCHBASE_PASSWORD',
654
+ bucketName: test_bucketName,
655
+ scopeName: test_scopeName,
656
+ collectionName: test_collectionName,
657
+ });
658
658
  await couchbase_client.getCollection();
659
659
  });
660
660
 
@@ -713,7 +713,7 @@ describe('Unit Testing CouchbaseVector', () => {
713
713
  },
714
714
  });
715
715
 
716
- const stats = await couchbase_client.describeIndex(test_indexName);
716
+ const stats = await couchbase_client.describeIndex({ indexName: test_indexName });
717
717
  expect(stats.metric).toBe(mastraMetric);
718
718
  }
719
719
  });