@mastra/chroma 0.0.0-trigger-playground-ui-package-20250506151043 → 0.0.0-tsconfig-compile-20250703214351

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.
@@ -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
  QueryResult,
@@ -5,29 +6,25 @@ import type {
5
6
  CreateIndexParams,
6
7
  UpsertVectorParams,
7
8
  QueryVectorParams,
8
- ParamsToArgs,
9
- QueryVectorArgs,
10
- UpsertVectorArgs,
9
+ DescribeIndexParams,
10
+ DeleteIndexParams,
11
+ DeleteVectorParams,
12
+ UpdateVectorParams,
11
13
  } from '@mastra/core/vector';
12
-
13
- import type { VectorFilter } from '@mastra/core/vector/filter';
14
14
  import { ChromaClient } from 'chromadb';
15
15
  import type { UpdateRecordsParams, Collection } from 'chromadb';
16
+ import type { ChromaVectorDocumentFilter, ChromaVectorFilter } from './filter';
16
17
  import { ChromaFilterTranslator } from './filter';
17
18
 
18
19
  interface ChromaUpsertVectorParams extends UpsertVectorParams {
19
20
  documents?: string[];
20
21
  }
21
22
 
22
- type ChromaUpsertArgs = [...UpsertVectorArgs, string[]?];
23
-
24
- interface ChromaQueryVectorParams extends QueryVectorParams {
25
- documentFilter?: VectorFilter;
23
+ interface ChromaQueryVectorParams extends QueryVectorParams<ChromaVectorFilter> {
24
+ documentFilter?: ChromaVectorDocumentFilter;
26
25
  }
27
26
 
28
- type ChromaQueryArgs = [...QueryVectorArgs, VectorFilter?];
29
-
30
- export class ChromaVector extends MastraVector {
27
+ export class ChromaVector extends MastraVector<ChromaVectorFilter> {
31
28
  private client: ChromaClient;
32
29
  private collections: Map<string, any>;
33
30
 
@@ -72,33 +69,35 @@ export class ChromaVector extends MastraVector {
72
69
  }
73
70
  }
74
71
 
75
- async upsert(...args: ParamsToArgs<ChromaUpsertVectorParams> | ChromaUpsertArgs): Promise<string[]> {
76
- const params = this.normalizeArgs<ChromaUpsertVectorParams, ChromaUpsertArgs>('upsert', args, ['documents']);
77
-
78
- const { indexName, vectors, metadata, ids, documents } = params;
79
-
80
- const collection = await this.getCollection(indexName);
81
-
82
- // Get index stats to check dimension
83
- const stats = await this.describeIndex(indexName);
84
-
85
- // Validate vector dimensions
86
- this.validateVectorDimensions(vectors, stats.dimension);
87
-
88
- // Generate IDs if not provided
89
- const generatedIds = ids || vectors.map(() => crypto.randomUUID());
72
+ async upsert({ indexName, vectors, metadata, ids, documents }: ChromaUpsertVectorParams): Promise<string[]> {
73
+ try {
74
+ const collection = await this.getCollection(indexName);
90
75
 
91
- // Ensure metadata exists for each vector
92
- const normalizedMetadata = metadata || vectors.map(() => ({}));
76
+ const stats = await this.describeIndex({ indexName });
77
+ this.validateVectorDimensions(vectors, stats.dimension);
78
+ const generatedIds = ids || vectors.map(() => crypto.randomUUID());
79
+ const normalizedMetadata = metadata || vectors.map(() => ({}));
93
80
 
94
- await collection.upsert({
95
- ids: generatedIds,
96
- embeddings: vectors,
97
- metadatas: normalizedMetadata,
98
- documents: documents,
99
- });
81
+ await collection.upsert({
82
+ ids: generatedIds,
83
+ embeddings: vectors,
84
+ metadatas: normalizedMetadata,
85
+ documents: documents,
86
+ });
100
87
 
101
- return generatedIds;
88
+ return generatedIds;
89
+ } catch (error: any) {
90
+ if (error instanceof MastraError) throw error;
91
+ throw new MastraError(
92
+ {
93
+ id: 'CHROMA_VECTOR_UPSERT_FAILED',
94
+ domain: ErrorDomain.MASTRA_VECTOR,
95
+ category: ErrorCategory.THIRD_PARTY,
96
+ details: { indexName },
97
+ },
98
+ error,
99
+ );
100
+ }
102
101
  }
103
102
 
104
103
  private HnswSpaceMap = {
@@ -109,113 +108,233 @@ export class ChromaVector extends MastraVector {
109
108
  ip: 'dotproduct',
110
109
  };
111
110
 
112
- async createIndex(...args: ParamsToArgs<CreateIndexParams>): Promise<void> {
113
- const params = this.normalizeArgs<CreateIndexParams>('createIndex', args);
114
-
115
- const { indexName, dimension, metric = 'cosine' } = params;
116
-
111
+ async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {
117
112
  if (!Number.isInteger(dimension) || dimension <= 0) {
118
- throw new Error('Dimension must be a positive integer');
113
+ throw new MastraError({
114
+ id: 'CHROMA_VECTOR_CREATE_INDEX_INVALID_DIMENSION',
115
+ text: 'Dimension must be a positive integer',
116
+ domain: ErrorDomain.MASTRA_VECTOR,
117
+ category: ErrorCategory.USER,
118
+ details: { dimension },
119
+ });
119
120
  }
120
121
  const hnswSpace = this.HnswSpaceMap[metric];
121
- if (!['cosine', 'l2', 'ip'].includes(hnswSpace)) {
122
- throw new Error(`Invalid metric: "${metric}". Must be one of: cosine, euclidean, dotproduct`);
122
+ if (!hnswSpace || !['cosine', 'l2', 'ip'].includes(hnswSpace)) {
123
+ throw new MastraError({
124
+ id: 'CHROMA_VECTOR_CREATE_INDEX_INVALID_METRIC',
125
+ text: `Invalid metric: "${metric}". Must be one of: cosine, euclidean, dotproduct`,
126
+ domain: ErrorDomain.MASTRA_VECTOR,
127
+ category: ErrorCategory.USER,
128
+ details: { metric },
129
+ });
130
+ }
131
+ try {
132
+ await this.client.createCollection({
133
+ name: indexName,
134
+ metadata: {
135
+ dimension,
136
+ 'hnsw:space': hnswSpace,
137
+ },
138
+ });
139
+ } catch (error: any) {
140
+ // Check for 'already exists' error
141
+ const message = error?.message || error?.toString();
142
+ if (message && message.toLowerCase().includes('already exists')) {
143
+ // Fetch collection info and check dimension
144
+ await this.validateExistingIndex(indexName, dimension, metric);
145
+ return;
146
+ }
147
+ throw new MastraError(
148
+ {
149
+ id: 'CHROMA_VECTOR_CREATE_INDEX_FAILED',
150
+ domain: ErrorDomain.MASTRA_VECTOR,
151
+ category: ErrorCategory.THIRD_PARTY,
152
+ details: { indexName },
153
+ },
154
+ error,
155
+ );
123
156
  }
124
- await this.client.createCollection({
125
- name: indexName,
126
- metadata: {
127
- dimension,
128
- 'hnsw:space': this.HnswSpaceMap[metric],
129
- },
130
- });
131
157
  }
132
158
 
133
- transformFilter(filter?: VectorFilter) {
159
+ transformFilter(filter?: ChromaVectorFilter) {
134
160
  const translator = new ChromaFilterTranslator();
135
161
  return translator.translate(filter);
136
162
  }
137
- async query(...args: ParamsToArgs<ChromaQueryVectorParams> | ChromaQueryArgs): Promise<QueryResult[]> {
138
- const params = this.normalizeArgs<ChromaQueryVectorParams, ChromaQueryArgs>('query', args, ['documentFilter']);
139
-
140
- const { indexName, queryVector, topK = 10, filter, includeVector = false, documentFilter } = params;
141
-
142
- const collection = await this.getCollection(indexName, true);
143
-
144
- const defaultInclude = ['documents', 'metadatas', 'distances'];
145
-
146
- const translatedFilter = this.transformFilter(filter);
147
- const results = await collection.query({
148
- queryEmbeddings: [queryVector],
149
- nResults: topK,
150
- where: translatedFilter,
151
- whereDocument: documentFilter,
152
- include: includeVector ? [...defaultInclude, 'embeddings'] : defaultInclude,
153
- });
154
-
155
- // Transform ChromaDB results to QueryResult format
156
- return (results.ids[0] || []).map((id: string, index: number) => ({
157
- id,
158
- score: results.distances?.[0]?.[index] || 0,
159
- metadata: results.metadatas?.[0]?.[index] || {},
160
- document: results.documents?.[0]?.[index],
161
- ...(includeVector && { vector: results.embeddings?.[0]?.[index] || [] }),
162
- }));
163
+ async query({
164
+ indexName,
165
+ queryVector,
166
+ topK = 10,
167
+ filter,
168
+ includeVector = false,
169
+ documentFilter,
170
+ }: ChromaQueryVectorParams): Promise<QueryResult[]> {
171
+ try {
172
+ const collection = await this.getCollection(indexName, true);
173
+
174
+ const defaultInclude = ['documents', 'metadatas', 'distances'];
175
+
176
+ const translatedFilter = this.transformFilter(filter);
177
+ const results = await collection.query({
178
+ queryEmbeddings: [queryVector],
179
+ nResults: topK,
180
+ where: translatedFilter,
181
+ whereDocument: documentFilter,
182
+ include: includeVector ? [...defaultInclude, 'embeddings'] : defaultInclude,
183
+ });
184
+
185
+ return (results.ids[0] || []).map((id: string, index: number) => ({
186
+ id,
187
+ score: results.distances?.[0]?.[index] || 0,
188
+ metadata: results.metadatas?.[0]?.[index] || {},
189
+ document: results.documents?.[0]?.[index],
190
+ ...(includeVector && { vector: results.embeddings?.[0]?.[index] || [] }),
191
+ }));
192
+ } catch (error: any) {
193
+ if (error instanceof MastraError) throw error;
194
+ throw new MastraError(
195
+ {
196
+ id: 'CHROMA_VECTOR_QUERY_FAILED',
197
+ domain: ErrorDomain.MASTRA_VECTOR,
198
+ category: ErrorCategory.THIRD_PARTY,
199
+ details: { indexName },
200
+ },
201
+ error,
202
+ );
203
+ }
163
204
  }
164
205
 
165
206
  async listIndexes(): Promise<string[]> {
166
- const collections = await this.client.listCollections();
167
- return collections.map(collection => collection);
207
+ try {
208
+ const collections = await this.client.listCollections();
209
+ return collections.map(collection => collection);
210
+ } catch (error: any) {
211
+ throw new MastraError(
212
+ {
213
+ id: 'CHROMA_VECTOR_LIST_INDEXES_FAILED',
214
+ domain: ErrorDomain.MASTRA_VECTOR,
215
+ category: ErrorCategory.THIRD_PARTY,
216
+ },
217
+ error,
218
+ );
219
+ }
168
220
  }
169
221
 
170
- async describeIndex(indexName: string): Promise<IndexStats> {
171
- const collection = await this.getCollection(indexName);
172
- const count = await collection.count();
173
- const metadata = collection.metadata;
222
+ /**
223
+ * Retrieves statistics about a vector index.
224
+ *
225
+ * @param {string} indexName - The name of the index to describe
226
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
227
+ */
228
+ async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {
229
+ try {
230
+ const collection = await this.getCollection(indexName);
231
+ const count = await collection.count();
232
+ const metadata = collection.metadata;
174
233
 
175
- const hnswSpace = metadata?.['hnsw:space'] as 'cosine' | 'l2' | 'ip';
234
+ const hnswSpace = metadata?.['hnsw:space'] as 'cosine' | 'l2' | 'ip';
176
235
 
177
- return {
178
- dimension: metadata?.dimension || 0,
179
- count,
180
- metric: this.HnswSpaceMap[hnswSpace] as 'cosine' | 'euclidean' | 'dotproduct',
181
- };
236
+ return {
237
+ dimension: metadata?.dimension || 0,
238
+ count,
239
+ metric: this.HnswSpaceMap[hnswSpace] as 'cosine' | 'euclidean' | 'dotproduct',
240
+ };
241
+ } catch (error: any) {
242
+ if (error instanceof MastraError) throw error;
243
+ throw new MastraError(
244
+ {
245
+ id: 'CHROMA_VECTOR_DESCRIBE_INDEX_FAILED',
246
+ domain: ErrorDomain.MASTRA_VECTOR,
247
+ category: ErrorCategory.THIRD_PARTY,
248
+ details: { indexName },
249
+ },
250
+ error,
251
+ );
252
+ }
182
253
  }
183
254
 
184
- async deleteIndex(indexName: string): Promise<void> {
185
- await this.client.deleteCollection({ name: indexName });
186
- this.collections.delete(indexName);
255
+ async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {
256
+ try {
257
+ await this.client.deleteCollection({ name: indexName });
258
+ this.collections.delete(indexName);
259
+ } catch (error: any) {
260
+ throw new MastraError(
261
+ {
262
+ id: 'CHROMA_VECTOR_DELETE_INDEX_FAILED',
263
+ domain: ErrorDomain.MASTRA_VECTOR,
264
+ category: ErrorCategory.THIRD_PARTY,
265
+ details: { indexName },
266
+ },
267
+ error,
268
+ );
269
+ }
187
270
  }
188
271
 
189
- async updateIndexById(
190
- indexName: string,
191
- id: string,
192
- update: { vector?: number[]; metadata?: Record<string, any> },
193
- ): Promise<void> {
272
+ /**
273
+ * Updates a vector by its ID with the provided vector and/or metadata.
274
+ * @param indexName - The name of the index containing the vector.
275
+ * @param id - The ID of the vector to update.
276
+ * @param update - An object containing the vector and/or metadata to update.
277
+ * @param update.vector - An optional array of numbers representing the new vector.
278
+ * @param update.metadata - An optional record containing the new metadata.
279
+ * @returns A promise that resolves when the update is complete.
280
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
281
+ */
282
+ async updateVector({ indexName, id, update }: UpdateVectorParams): Promise<void> {
194
283
  if (!update.vector && !update.metadata) {
195
- throw new Error('No updates provided');
284
+ throw new MastraError({
285
+ id: 'CHROMA_VECTOR_UPDATE_NO_PAYLOAD',
286
+ text: 'No updates provided for vector',
287
+ domain: ErrorDomain.MASTRA_VECTOR,
288
+ category: ErrorCategory.USER,
289
+ details: { indexName, id },
290
+ });
196
291
  }
197
292
 
198
- const collection: Collection = await this.getCollection(indexName, true);
293
+ try {
294
+ const collection: Collection = await this.getCollection(indexName, true);
199
295
 
200
- const updateOptions: UpdateRecordsParams = { ids: [id] };
296
+ const updateOptions: UpdateRecordsParams = { ids: [id] };
201
297
 
202
- if (update?.vector) {
203
- updateOptions.embeddings = [update.vector];
204
- }
298
+ if (update?.vector) {
299
+ const stats = await this.describeIndex({ indexName });
300
+ this.validateVectorDimensions([update.vector], stats.dimension);
301
+ updateOptions.embeddings = [update.vector];
302
+ }
205
303
 
206
- if (update?.metadata) {
207
- updateOptions.metadatas = [update.metadata];
208
- }
304
+ if (update?.metadata) {
305
+ updateOptions.metadatas = [update.metadata];
306
+ }
209
307
 
210
- return await collection.update(updateOptions);
308
+ return await collection.update(updateOptions);
309
+ } catch (error: any) {
310
+ if (error instanceof MastraError) throw error;
311
+ throw new MastraError(
312
+ {
313
+ id: 'CHROMA_VECTOR_UPDATE_FAILED',
314
+ domain: ErrorDomain.MASTRA_VECTOR,
315
+ category: ErrorCategory.THIRD_PARTY,
316
+ details: { indexName, id },
317
+ },
318
+ error,
319
+ );
320
+ }
211
321
  }
212
322
 
213
- async deleteIndexById(indexName: string, id: string): Promise<void> {
323
+ async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {
214
324
  try {
215
325
  const collection: Collection = await this.getCollection(indexName, true);
216
326
  await collection.delete({ ids: [id] });
217
327
  } catch (error: any) {
218
- throw new Error(`Failed to delete index by id: ${id} for index name: ${indexName}: ${error.message}`);
328
+ if (error instanceof MastraError) throw error;
329
+ throw new MastraError(
330
+ {
331
+ id: 'CHROMA_VECTOR_DELETE_FAILED',
332
+ domain: ErrorDomain.MASTRA_VECTOR,
333
+ category: ErrorCategory.THIRD_PARTY,
334
+ details: { indexName, id },
335
+ },
336
+ error,
337
+ );
219
338
  }
220
339
  }
221
340
  }