@mastra/turbopuffer 0.0.0-llamaindex-switch-core-20250424001624 → 0.0.0-main-test-20251105183450

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/LICENSE.md CHANGED
@@ -1,7 +1,15 @@
1
- Copyright 2025 Mastra AI, Inc.
1
+ # Apache License 2.0
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3
+ Copyright (c) 2025 Kepler Software, Inc.
4
4
 
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
6
8
 
7
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
package/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var error = require('@mastra/core/error');
3
4
  var vector = require('@mastra/core/vector');
4
5
  var turbopuffer = require('@turbopuffer/turbopuffer');
5
6
  var filter = require('@mastra/core/vector/filter');
@@ -177,39 +178,44 @@ var TurbopufferVector = class extends vector.MastraVector {
177
178
  super();
178
179
  this.filterTranslator = new TurbopufferFilterTranslator();
179
180
  this.opts = opts;
180
- const baseClient = new turbopuffer.Turbopuffer(opts);
181
- const telemetry = this.__getTelemetry();
182
- this.client = telemetry?.traceClass(baseClient, {
183
- spanNamePrefix: "turbopuffer-vector",
184
- attributes: {
185
- "vector.type": "turbopuffer"
186
- }
187
- }) ?? baseClient;
181
+ this.client = new turbopuffer.Turbopuffer(opts);
188
182
  }
189
183
  async createIndex({ indexName, dimension, metric }) {
190
184
  metric = metric ?? "cosine";
191
- if (this.createIndexCache.has(indexName)) {
192
- const expected = this.createIndexCache.get(indexName);
193
- if (dimension !== expected.dimension || metric !== expected.metric) {
194
- throw new Error(
195
- `createIndex() called more than once with inconsistent inputs. Index ${indexName} expected dimensions=${expected.dimension} and metric=${expected.metric} but got dimensions=${dimension} and metric=${metric}`
196
- );
197
- }
198
- return;
199
- }
200
- if (dimension <= 0) {
201
- throw new Error("Dimension must be a positive integer");
202
- }
203
185
  let distanceMetric = "cosine_distance";
204
- switch (metric) {
205
- case "cosine":
206
- distanceMetric = "cosine_distance";
207
- break;
208
- case "euclidean":
209
- distanceMetric = "euclidean_squared";
210
- break;
211
- case "dotproduct":
212
- throw new Error("dotproduct is not supported in Turbopuffer");
186
+ try {
187
+ if (this.createIndexCache.has(indexName)) {
188
+ const expected = this.createIndexCache.get(indexName);
189
+ if (dimension !== expected.dimension || metric !== expected.metric) {
190
+ throw new Error(
191
+ `createIndex() called more than once with inconsistent inputs. Index ${indexName} expected dimensions=${expected.dimension} and metric=${expected.metric} but got dimensions=${dimension} and metric=${metric}`
192
+ );
193
+ }
194
+ return;
195
+ }
196
+ if (dimension <= 0) {
197
+ throw new Error("Dimension must be a positive integer");
198
+ }
199
+ switch (metric) {
200
+ case "cosine":
201
+ distanceMetric = "cosine_distance";
202
+ break;
203
+ case "euclidean":
204
+ distanceMetric = "euclidean_squared";
205
+ break;
206
+ case "dotproduct":
207
+ throw new Error("dotproduct is not supported in Turbopuffer");
208
+ }
209
+ } catch (error$1) {
210
+ throw new error.MastraError(
211
+ {
212
+ id: "STORAGE_TURBOBUFFER_VECTOR_CREATE_INDEX_INVALID_ARGS",
213
+ domain: error.ErrorDomain.STORAGE,
214
+ category: error.ErrorCategory.USER,
215
+ details: { indexName, dimension, metric }
216
+ },
217
+ error$1
218
+ );
213
219
  }
214
220
  this.createIndexCache.set(indexName, {
215
221
  indexName,
@@ -219,15 +225,29 @@ var TurbopufferVector = class extends vector.MastraVector {
219
225
  });
220
226
  }
221
227
  async upsert({ indexName, vectors, metadata, ids }) {
228
+ let index;
229
+ let createIndex;
222
230
  try {
223
231
  if (vectors.length === 0) {
224
232
  throw new Error("upsert() called with empty vectors");
225
233
  }
226
- const index = this.client.namespace(indexName);
227
- const createIndex = this.createIndexCache.get(indexName);
234
+ index = this.client.namespace(indexName);
235
+ createIndex = this.createIndexCache.get(indexName);
228
236
  if (!createIndex) {
229
237
  throw new Error(`createIndex() not called for this index`);
230
238
  }
239
+ } catch (error$1) {
240
+ throw new error.MastraError(
241
+ {
242
+ id: "STORAGE_TURBOBUFFER_VECTOR_UPSERT_INVALID_ARGS",
243
+ domain: error.ErrorDomain.STORAGE,
244
+ category: error.ErrorCategory.USER,
245
+ details: { indexName }
246
+ },
247
+ error$1
248
+ );
249
+ }
250
+ try {
231
251
  const distanceMetric = createIndex.tpufDistanceMetric;
232
252
  const vectorIds = ids || vectors.map(() => crypto.randomUUID());
233
253
  const records = vectors.map((vector, i) => ({
@@ -254,22 +274,49 @@ var TurbopufferVector = class extends vector.MastraVector {
254
274
  await index.upsert(upsertOptions);
255
275
  }
256
276
  return vectorIds;
257
- } catch (error) {
258
- throw new Error(`Failed to upsert vectors into Turbopuffer namespace ${indexName}: ${error}`);
277
+ } catch (error$1) {
278
+ throw new error.MastraError(
279
+ {
280
+ id: "STORAGE_TURBOBUFFER_VECTOR_UPSERT_FAILED",
281
+ domain: error.ErrorDomain.STORAGE,
282
+ category: error.ErrorCategory.THIRD_PARTY,
283
+ details: { indexName }
284
+ },
285
+ error$1
286
+ );
259
287
  }
260
288
  }
261
- async query({ indexName, queryVector, topK, filter, includeVector }) {
262
- const schemaConfig = this.opts.schemaConfigForIndex?.(indexName);
263
- if (schemaConfig) {
264
- if (queryVector.length !== schemaConfig.dimensions) {
265
- throw new Error(
266
- `Turbopuffer index ${indexName} was configured with dimensions=${schemaConfig.dimensions} but attempting to query with queryVector.length=${queryVector.length}`
267
- );
289
+ async query({
290
+ indexName,
291
+ queryVector,
292
+ topK,
293
+ filter,
294
+ includeVector
295
+ }) {
296
+ let createIndex;
297
+ try {
298
+ const schemaConfig = this.opts.schemaConfigForIndex?.(indexName);
299
+ if (schemaConfig) {
300
+ if (queryVector.length !== schemaConfig.dimensions) {
301
+ throw new Error(
302
+ `Turbopuffer index ${indexName} was configured with dimensions=${schemaConfig.dimensions} but attempting to query with queryVector.length=${queryVector.length}`
303
+ );
304
+ }
268
305
  }
269
- }
270
- const createIndex = this.createIndexCache.get(indexName);
271
- if (!createIndex) {
272
- throw new Error(`createIndex() not called for this index`);
306
+ createIndex = this.createIndexCache.get(indexName);
307
+ if (!createIndex) {
308
+ throw new Error(`createIndex() not called for this index`);
309
+ }
310
+ } catch (error$1) {
311
+ throw new error.MastraError(
312
+ {
313
+ id: "STORAGE_TURBOBUFFER_VECTOR_QUERY_INVALID_ARGS",
314
+ domain: error.ErrorDomain.STORAGE,
315
+ category: error.ErrorCategory.USER,
316
+ details: { indexName }
317
+ },
318
+ error$1
319
+ );
273
320
  }
274
321
  const distanceMetric = createIndex.tpufDistanceMetric;
275
322
  try {
@@ -291,19 +338,40 @@ var TurbopufferVector = class extends vector.MastraVector {
291
338
  metadata: item.attributes || {},
292
339
  ...includeVector && item.vector ? { vector: item.vector } : {}
293
340
  }));
294
- } catch (error) {
295
- throw new Error(`Failed to query Turbopuffer namespace ${indexName}: ${error}`);
341
+ } catch (error$1) {
342
+ throw new error.MastraError(
343
+ {
344
+ id: "STORAGE_TURBOBUFFER_VECTOR_QUERY_FAILED",
345
+ domain: error.ErrorDomain.STORAGE,
346
+ category: error.ErrorCategory.THIRD_PARTY,
347
+ details: { indexName }
348
+ },
349
+ error$1
350
+ );
296
351
  }
297
352
  }
298
353
  async listIndexes() {
299
354
  try {
300
355
  const namespacesResult = await this.client.namespaces({});
301
356
  return namespacesResult.namespaces.map((namespace) => namespace.id);
302
- } catch (error) {
303
- throw new Error(`Failed to list Turbopuffer namespaces: ${error}`);
357
+ } catch (error$1) {
358
+ throw new error.MastraError(
359
+ {
360
+ id: "STORAGE_TURBOBUFFER_VECTOR_LIST_INDEXES_FAILED",
361
+ domain: error.ErrorDomain.STORAGE,
362
+ category: error.ErrorCategory.THIRD_PARTY
363
+ },
364
+ error$1
365
+ );
304
366
  }
305
367
  }
306
- async describeIndex(indexName) {
368
+ /**
369
+ * Retrieves statistics about a vector index.
370
+ *
371
+ * @param {string} indexName - The name of the index to describe
372
+ * @returns A promise that resolves to the index statistics including dimension, count and metric
373
+ */
374
+ async describeIndex({ indexName }) {
307
375
  try {
308
376
  const namespace = this.client.namespace(indexName);
309
377
  const metadata = await namespace.metadata();
@@ -318,19 +386,113 @@ var TurbopufferVector = class extends vector.MastraVector {
318
386
  count,
319
387
  metric: createIndex.metric
320
388
  };
321
- } catch (error) {
322
- throw new Error(`Failed to describe Turbopuffer namespace ${indexName}: ${error}`);
389
+ } catch (error$1) {
390
+ throw new error.MastraError(
391
+ {
392
+ id: "STORAGE_TURBOBUFFER_VECTOR_DESCRIBE_INDEX_FAILED",
393
+ domain: error.ErrorDomain.STORAGE,
394
+ category: error.ErrorCategory.THIRD_PARTY,
395
+ details: { indexName }
396
+ },
397
+ error$1
398
+ );
323
399
  }
324
400
  }
325
- async deleteIndex(indexName) {
401
+ async deleteIndex({ indexName }) {
326
402
  try {
327
403
  const namespace = this.client.namespace(indexName);
328
404
  await namespace.deleteAll();
329
405
  this.createIndexCache.delete(indexName);
330
- } catch (error) {
331
- throw new Error(`Failed to delete Turbopuffer namespace ${indexName}: ${error.message}`);
406
+ } catch (error$1) {
407
+ throw new error.MastraError(
408
+ {
409
+ id: "STORAGE_TURBOBUFFER_VECTOR_DELETE_INDEX_FAILED",
410
+ domain: error.ErrorDomain.STORAGE,
411
+ category: error.ErrorCategory.THIRD_PARTY,
412
+ details: { indexName }
413
+ },
414
+ error$1
415
+ );
416
+ }
417
+ }
418
+ /**
419
+ * Updates a vector by its ID with the provided vector and/or metadata.
420
+ * @param indexName - The name of the index containing the vector.
421
+ * @param id - The ID of the vector to update.
422
+ * @param update - An object containing the vector and/or metadata to update.
423
+ * @param update.vector - An optional array of numbers representing the new vector.
424
+ * @param update.metadata - An optional record containing the new metadata.
425
+ * @returns A promise that resolves when the update is complete.
426
+ * @throws Will throw an error if no updates are provided or if the update operation fails.
427
+ */
428
+ async updateVector({ indexName, id, update }) {
429
+ let namespace;
430
+ let createIndex;
431
+ let distanceMetric;
432
+ let record;
433
+ try {
434
+ namespace = this.client.namespace(indexName);
435
+ createIndex = this.createIndexCache.get(indexName);
436
+ if (!createIndex) {
437
+ throw new Error(`createIndex() not called for this index`);
438
+ }
439
+ distanceMetric = createIndex.tpufDistanceMetric;
440
+ record = { id };
441
+ if (update.vector) record.vector = update.vector;
442
+ if (update.metadata) record.attributes = update.metadata;
443
+ } catch (error$1) {
444
+ throw new error.MastraError(
445
+ {
446
+ id: "STORAGE_TURBOBUFFER_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
447
+ domain: error.ErrorDomain.STORAGE,
448
+ category: error.ErrorCategory.USER,
449
+ details: { indexName }
450
+ },
451
+ error$1
452
+ );
453
+ }
454
+ try {
455
+ await namespace.upsert({
456
+ vectors: [record],
457
+ distance_metric: distanceMetric
458
+ });
459
+ } catch (error$1) {
460
+ throw new error.MastraError(
461
+ {
462
+ id: "STORAGE_TURBOBUFFER_VECTOR_UPDATE_VECTOR_FAILED",
463
+ domain: error.ErrorDomain.STORAGE,
464
+ category: error.ErrorCategory.THIRD_PARTY,
465
+ details: { indexName }
466
+ },
467
+ error$1
468
+ );
469
+ }
470
+ }
471
+ /**
472
+ * Deletes a vector by its ID.
473
+ * @param indexName - The name of the index containing the vector.
474
+ * @param id - The ID of the vector to delete.
475
+ * @returns A promise that resolves when the deletion is complete.
476
+ * @throws Will throw an error if the deletion operation fails.
477
+ */
478
+ async deleteVector({ indexName, id }) {
479
+ try {
480
+ const namespace = this.client.namespace(indexName);
481
+ await namespace.delete({ ids: [id] });
482
+ } catch (error$1) {
483
+ throw new error.MastraError(
484
+ {
485
+ id: "STORAGE_TURBOBUFFER_VECTOR_DELETE_VECTOR_FAILED",
486
+ domain: error.ErrorDomain.STORAGE,
487
+ category: error.ErrorCategory.THIRD_PARTY,
488
+ details: { indexName }
489
+ },
490
+ error$1
491
+ );
332
492
  }
333
493
  }
334
494
  };
335
495
 
336
496
  exports.TurbopufferVector = TurbopufferVector;
497
+ //# sourceMappingURL=index.cjs.map
498
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vector/filter.ts","../src/vector/index.ts"],"names":["BaseFilterTranslator","op","MastraVector","Turbopuffer","error","MastraError","ErrorDomain","ErrorCategory"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n OperatorSupport,\n VectorFilter,\n OperatorValueMap,\n LogicalOperatorValueMap,\n BlacklistedRootOperators,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\nimport type { FilterCondition, FilterConnective, FilterOperator, Filters } from '@turbopuffer/turbopuffer';\n\ntype TurbopufferOperatorValueMap = Omit<OperatorValueMap, '$regex' | '$options' | '$elemMatch'>;\n\ntype TurbopufferLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor' | '$not'>;\n\ntype TurbopufferBlacklistedRootOperators = BlacklistedRootOperators | '$nor' | '$not';\n\nexport type TurbopufferVectorFilter = VectorFilter<\n keyof TurbopufferOperatorValueMap,\n TurbopufferOperatorValueMap,\n TurbopufferLogicalOperatorValueMap,\n TurbopufferBlacklistedRootOperators\n>;\n\n/**\n * Translator for converting Mastra filters to Turbopuffer format\n *\n * Mastra filters: { field: { $gt: 10 } }\n * Turbopuffer filters: [\"And\", [[\"field\", \"Gt\", 10]]]\n */\nexport class TurbopufferFilterTranslator extends BaseFilterTranslator<TurbopufferVectorFilter, Filters | undefined> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or'],\n array: ['$in', '$nin', '$all'],\n element: ['$exists'],\n regex: [], // No regex support in Turbopuffer\n custom: [], // No custom operators\n };\n }\n\n /**\n * Map Mastra operators to Turbopuffer operators\n */\n private operatorMap: Record<string, FilterOperator> = {\n $eq: 'Eq',\n $ne: 'NotEq',\n $gt: 'Gt',\n $gte: 'Gte',\n $lt: 'Lt',\n $lte: 'Lte',\n $in: 'In',\n $nin: 'NotIn',\n };\n\n /**\n * Convert the Mastra filter to Turbopuffer format\n */\n translate(filter?: TurbopufferVectorFilter): Filters | undefined {\n if (this.isEmpty(filter)) {\n return undefined;\n }\n\n // Validate the filter structure before translating\n this.validateFilter(filter);\n\n // Translate the filter\n const result = this.translateNode(filter);\n\n // If we have a single condition (not a logical operator at the top level),\n // wrap it in an implicit AND to match Turbopuffer's expected format\n if (!Array.isArray(result) || result.length !== 2 || (result[0] !== 'And' && result[0] !== 'Or')) {\n return ['And', [result as FilterCondition]];\n }\n\n return result as Filters;\n }\n\n /**\n * Recursively translate a filter node\n */\n private translateNode(node: TurbopufferVectorFilter): Filters | FilterCondition {\n // Handle empty or null nodes\n if (node === null || node === undefined || Object.keys(node).length === 0) {\n return ['And', []];\n }\n\n // Handle primitive values (direct equality comparison)\n if (this.isPrimitive(node)) {\n throw new Error('Direct primitive values not valid in this context for Turbopuffer');\n }\n\n // Handle direct array value (convert to $in)\n if (Array.isArray(node)) {\n throw new Error('Direct array values not valid in this context for Turbopuffer');\n }\n\n const entries = Object.entries(node);\n\n // Process the first operator or field\n if (entries.length === 0) {\n return ['And', []];\n }\n\n const [key, value] = entries[0] as [string, any];\n\n // Handle logical operators\n if (key && this.isLogicalOperator(key)) {\n return this.translateLogical(key, value);\n }\n\n // Multiple fields at top level - implicit AND\n if (entries.length > 1) {\n const conditions = entries.map(([field, fieldValue]) => this.translateFieldCondition(field, fieldValue));\n return ['And', conditions];\n }\n\n // Single field with condition(s)\n return this.translateFieldCondition(key, value);\n }\n\n /**\n * Translate a field condition\n */\n private translateFieldCondition(field: string, value: any): FilterCondition {\n // Handle Date object directly (convert to ISO string)\n if (value instanceof Date) {\n return [field, 'Eq', this.normalizeValue(value)];\n }\n\n // Handle primitive value (direct equality)\n if (this.isPrimitive(value)) {\n return [field, 'Eq', this.normalizeValue(value)];\n }\n\n // Handle array value (convert to $in)\n if (Array.isArray(value)) {\n return [field, 'In', this.normalizeArrayValues(value)];\n }\n\n // Handle object with operators\n if (typeof value === 'object' && value !== null) {\n const operators = Object.keys(value);\n\n // If multiple operators for the same field, create an AND condition\n if (operators.length > 1) {\n // Check if all keys are operators\n const allOperators = operators.every(op => this.isOperator(op));\n if (allOperators) {\n // For multiple comparison operators on one field\n const conditions = operators.map(op => this.translateOperator(field, op, value[op]));\n return ['And', conditions] as unknown as FilterCondition;\n } else {\n // For nested objects with multiple fields\n const conditions = operators.map(op => {\n const nestedField = `${field}.${op}`;\n return this.translateFieldCondition(nestedField, value[op]);\n });\n return ['And', conditions] as unknown as FilterCondition;\n }\n }\n\n // Single operator\n const op = operators[0];\n if (op && this.isOperator(op)) {\n return this.translateOperator(field, op, value[op]);\n }\n\n // Nested field path (use dot notation)\n if (op && !this.isOperator(op)) {\n const nestedField = `${field}.${op}`;\n return this.translateFieldCondition(nestedField, value[op]);\n }\n }\n\n throw new Error(`Unsupported filter format for field: ${field}`);\n }\n\n /**\n * Translate a logical operator\n */\n private translateLogical(operator: string, conditions: any[]): Filters {\n // Map Mastra logical operators to Turbopuffer\n const logicalOp: FilterConnective = operator === '$and' ? 'And' : 'Or';\n\n // Validate conditions\n if (!Array.isArray(conditions)) {\n throw new Error(`Logical operator ${operator} requires an array of conditions`);\n }\n\n // Translate each condition\n const translatedConditions = conditions.map(condition => {\n if (typeof condition !== 'object' || condition === null) {\n throw new Error(`Invalid condition for logical operator ${operator}`);\n }\n return this.translateNode(condition);\n });\n\n return [logicalOp, translatedConditions];\n }\n\n /**\n * Translate a specific operator\n */\n private translateOperator(field: string, operator: string, value: any): FilterCondition {\n // Handle comparison operators\n if (operator && this.operatorMap[operator]) {\n return [field, this.operatorMap[operator], this.normalizeValue(value)];\n }\n\n // Handle special cases\n switch (operator) {\n case '$exists':\n // $exists: true -> use NotEq with null (field exists if it's not null)\n // $exists: false -> use Eq with null (field doesn't exist if it is null)\n return value ? [field, 'NotEq', null] : [field, 'Eq', null];\n\n case '$all':\n // $all is not directly supported, simulate with AND + IN conditions\n if (!Array.isArray(value) || value.length === 0) {\n throw new Error('$all operator requires a non-empty array');\n }\n\n const allConditions = value.map(item => [field, 'In', [this.normalizeValue(item)]] as FilterCondition);\n\n // Return the array of conditions directly without nesting\n return ['And', allConditions] as unknown as FilterCondition;\n\n default:\n throw new Error(`Unsupported operator: ${operator || 'undefined'}`);\n }\n }\n\n /**\n * Normalize a value for comparison operations\n */\n protected normalizeValue(value: any): any {\n // Handle special value types\n if (value instanceof Date) {\n return value.toISOString();\n }\n return value;\n }\n\n /**\n * Normalize array values\n */\n protected normalizeArrayValues(values: any[]): any[] {\n return values.map(value => this.normalizeValue(value));\n }\n}\n","import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n} from '@mastra/core/vector';\nimport { MastraVector } from '@mastra/core/vector';\nimport { Turbopuffer } from '@turbopuffer/turbopuffer';\nimport type { DistanceMetric, QueryResults, Schema, Vector } from '@turbopuffer/turbopuffer';\nimport { TurbopufferFilterTranslator } from './filter';\nimport type { TurbopufferVectorFilter } from './filter';\n\ntype TurbopufferQueryVectorParams = QueryVectorParams<TurbopufferVectorFilter>;\n\nexport interface TurbopufferVectorOptions {\n /** The API key to authenticate with. */\n apiKey: string;\n /** The base URL. Default is https://api.turbopuffer.com. */\n baseUrl?: string;\n /** The timeout to establish a connection, in ms. Default is 10_000. Only applicable in Node and Deno.*/\n connectTimeout?: number;\n /** The socket idle timeout, in ms. Default is 60_000. Only applicable in Node and Deno.*/\n connectionIdleTimeout?: number;\n /** The number of connections to open initially when creating a new client. Default is 0. */\n warmConnections?: number;\n /** Whether to compress requests and accept compressed responses. Default is true. */\n compression?: boolean;\n /**\n * A callback function that takes an index name and returns a config object for that index.\n * This allows you to define explicit schemas per index.\n *\n * Example:\n * ```typescript\n * schemaConfigForIndex: (indexName: string) => {\n * // Mastra's default embedding model and index for memory messages:\n * if (indexName === \"memory_messages_384\") {\n * return {\n * dimensions: 384,\n * schema: {\n * thread_id: {\n * type: \"string\",\n * filterable: true,\n * },\n * },\n * };\n * } else {\n * throw new Error(`TODO: add schema for index: ${indexName}`);\n * }\n * },\n * ```\n */\n schemaConfigForIndex?: (indexName: string) => {\n dimensions: number;\n schema: Schema;\n };\n}\n\nexport class TurbopufferVector extends MastraVector<TurbopufferVectorFilter> {\n private client: Turbopuffer;\n private filterTranslator: TurbopufferFilterTranslator;\n // There is no explicit create index operation in Turbopuffer, so just register that\n // someone has called createIndex() and verify that subsequent upsert calls are consistent\n // with how the index was \"created\"\n private createIndexCache: Map<\n string,\n CreateIndexParams & {\n tpufDistanceMetric: DistanceMetric;\n }\n > = new Map();\n private opts: TurbopufferVectorOptions;\n\n constructor(opts: TurbopufferVectorOptions) {\n super();\n this.filterTranslator = new TurbopufferFilterTranslator();\n this.opts = opts;\n this.client = new Turbopuffer(opts);\n }\n\n async createIndex({ indexName, dimension, metric }: CreateIndexParams): Promise<void> {\n metric = metric ?? 'cosine'; // default to cosine distance\n let distanceMetric: DistanceMetric = 'cosine_distance';\n try {\n if (this.createIndexCache.has(indexName)) {\n // verify that the dimensions and distance metric match what we expect\n const expected = this.createIndexCache.get(indexName)!;\n if (dimension !== expected.dimension || metric !== expected.metric) {\n throw new Error(\n `createIndex() called more than once with inconsistent inputs. Index ${indexName} expected dimensions=${expected.dimension} and metric=${expected.metric} but got dimensions=${dimension} and metric=${metric}`,\n );\n }\n return;\n }\n if (dimension <= 0) {\n throw new Error('Dimension must be a positive integer');\n }\n switch (metric) {\n case 'cosine':\n distanceMetric = 'cosine_distance';\n break;\n case 'euclidean':\n distanceMetric = 'euclidean_squared';\n break;\n case 'dotproduct':\n throw new Error('dotproduct is not supported in Turbopuffer');\n }\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_CREATE_INDEX_INVALID_ARGS',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n\n this.createIndexCache.set(indexName, {\n indexName,\n dimension,\n metric,\n tpufDistanceMetric: distanceMetric,\n });\n }\n\n async upsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]> {\n let index;\n let createIndex;\n try {\n if (vectors.length === 0) {\n throw new Error('upsert() called with empty vectors');\n }\n\n index = this.client.namespace(indexName);\n createIndex = this.createIndexCache.get(indexName);\n if (!createIndex) {\n throw new Error(`createIndex() not called for this index`);\n }\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_UPSERT_INVALID_ARGS',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n },\n error,\n );\n }\n\n try {\n const distanceMetric = createIndex.tpufDistanceMetric;\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const records: Vector[] = vectors.map((vector, i) => ({\n id: vectorIds[i]!,\n vector: vector,\n attributes: metadata?.[i] || {},\n }));\n\n // limit is 256 MB per upsert request, so set a reasonable batch size here that will stay under that for most cases\n // https://turbopuffer.com/docs/limits\n const batchSize = 100;\n for (let i = 0; i < records.length; i += batchSize) {\n const batch = records.slice(i, i + batchSize);\n const upsertOptions: {\n vectors: Vector[];\n distance_metric: DistanceMetric;\n schema?: Schema;\n batchSize?: number;\n } = {\n vectors: batch,\n distance_metric: distanceMetric,\n };\n\n // Use the schemaForIndex callback if provided\n const schemaConfig = this.opts.schemaConfigForIndex?.(indexName);\n if (schemaConfig) {\n upsertOptions.schema = schemaConfig.schema;\n if (vectors[0]?.length !== schemaConfig.dimensions) {\n throw new Error(\n `Turbopuffer index ${indexName} was configured with dimensions=${schemaConfig.dimensions} but attempting to upsert vectors[0].length=${vectors[0]?.length}`,\n );\n }\n }\n\n await index.upsert(upsertOptions);\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_UPSERT_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n }\n }\n\n async query({\n indexName,\n queryVector,\n topK,\n filter,\n includeVector,\n }: TurbopufferQueryVectorParams): Promise<QueryResult[]> {\n let createIndex;\n try {\n const schemaConfig = this.opts.schemaConfigForIndex?.(indexName);\n if (schemaConfig) {\n if (queryVector.length !== schemaConfig.dimensions) {\n throw new Error(\n `Turbopuffer index ${indexName} was configured with dimensions=${schemaConfig.dimensions} but attempting to query with queryVector.length=${queryVector.length}`,\n );\n }\n }\n createIndex = this.createIndexCache.get(indexName);\n if (!createIndex) {\n throw new Error(`createIndex() not called for this index`);\n }\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_QUERY_INVALID_ARGS',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n },\n error,\n );\n }\n\n const distanceMetric = createIndex.tpufDistanceMetric;\n try {\n const index = this.client.namespace(indexName);\n const translatedFilter = this.filterTranslator.translate(filter);\n const results: QueryResults = await index.query({\n distance_metric: distanceMetric,\n vector: queryVector,\n top_k: topK,\n filters: translatedFilter,\n include_vectors: includeVector,\n include_attributes: true,\n consistency: { level: 'strong' }, // todo: make this configurable somehow?\n });\n return results.map(item => ({\n id: String(item.id),\n score: typeof item.dist === 'number' ? item.dist : 0,\n metadata: item.attributes || {},\n ...(includeVector && item.vector ? { vector: item.vector } : {}),\n }));\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_QUERY_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n }\n }\n\n async listIndexes(): Promise<string[]> {\n try {\n const namespacesResult = await this.client.namespaces({});\n return namespacesResult.namespaces.map(namespace => namespace.id);\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_LIST_INDEXES_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n try {\n const namespace = this.client.namespace(indexName);\n const metadata = await namespace.metadata();\n const createIndex = this.createIndexCache.get(indexName);\n if (!createIndex) {\n throw new Error(`createIndex() not called for this index`);\n }\n const dimension = metadata.dimensions;\n const count = metadata.approx_count;\n return {\n dimension,\n count,\n metric: createIndex.metric,\n };\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_DESCRIBE_INDEX_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n }\n }\n\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n const namespace = this.client.namespace(indexName);\n await namespace.deleteAll();\n this.createIndexCache.delete(indexName);\n } catch (error: any) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_DELETE_INDEX_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n }\n }\n\n /**\n * Updates a vector by its ID with the provided vector and/or metadata.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to update.\n * @param update - An object containing the vector and/or metadata to update.\n * @param update.vector - An optional array of numbers representing the new vector.\n * @param update.metadata - An optional record containing the new metadata.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector({ indexName, id, update }: UpdateVectorParams): Promise<void> {\n let namespace;\n let createIndex;\n let distanceMetric;\n let record;\n try {\n namespace = this.client.namespace(indexName);\n createIndex = this.createIndexCache.get(indexName);\n if (!createIndex) {\n throw new Error(`createIndex() not called for this index`);\n }\n distanceMetric = createIndex.tpufDistanceMetric;\n record = { id } as Vector;\n if (update.vector) record.vector = update.vector;\n if (update.metadata) record.attributes = update.metadata;\n } catch (error) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_UPDATE_VECTOR_INVALID_ARGS',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n },\n error,\n );\n }\n try {\n await namespace.upsert({\n vectors: [record],\n distance_metric: distanceMetric,\n });\n } catch (error: any) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_UPDATE_VECTOR_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n const namespace = this.client.namespace(indexName);\n await namespace.delete({ ids: [id] });\n } catch (error: any) {\n throw new MastraError(\n {\n id: 'STORAGE_TURBOBUFFER_VECTOR_DELETE_VECTOR_FAILED',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n }\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { TurbopufferVectorOptions } from './_tsup-dts-rollup.js';
2
- export { TurbopufferVector } from './_tsup-dts-rollup.js';
1
+ export * from './vector/index.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}