@mastra/upstash 0.15.8-alpha.0 → 0.15.9-alpha.0

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/dist/index.js CHANGED
@@ -780,7 +780,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
780
780
  if (toDate) {
781
781
  messagesData = messagesData.filter((msg) => msg && new Date(msg.createdAt).getTime() <= toDate.getTime());
782
782
  }
783
- messagesData.sort((a, b) => allMessageIds.indexOf(a.id) - allMessageIds.indexOf(b.id));
783
+ messagesData.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
784
784
  const total = messagesData.length;
785
785
  const start = page * perPage;
786
786
  const end = start + perPage;
@@ -788,7 +788,8 @@ var StoreMemoryUpstash = class extends MemoryStorage {
788
788
  const paginatedMessages = messagesData.slice(start, end);
789
789
  messages.push(...paginatedMessages);
790
790
  const list = new MessageList().add(messages, "memory");
791
- const finalMessages = format === `v2` ? list.get.all.v2() : list.get.all.v1();
791
+ let finalMessages = format === `v2` ? list.get.all.v2() : list.get.all.v1();
792
+ finalMessages = finalMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
792
793
  return {
793
794
  messages: finalMessages,
794
795
  total,
@@ -1243,7 +1244,9 @@ var ScoresUpstash = class extends ScoresStorage {
1243
1244
  id: "STORAGE_UPSTASH_STORAGE_GET_SCORE_BY_ID_FAILED",
1244
1245
  domain: ErrorDomain.STORAGE,
1245
1246
  category: ErrorCategory.THIRD_PARTY,
1246
- details: { id }
1247
+ details: {
1248
+ ...id && { id }
1249
+ }
1247
1250
  },
1248
1251
  error
1249
1252
  );
@@ -2365,6 +2368,11 @@ var UpstashVector = class extends MastraVector {
2365
2368
  try {
2366
2369
  await this.client.deleteNamespace(namespace);
2367
2370
  } catch (error) {
2371
+ const errorMessage = error?.message || "";
2372
+ if (errorMessage.includes("does not exist") || errorMessage.includes("not found")) {
2373
+ this.logger.info(`Namespace ${namespace} does not exist, treating as already deleted`);
2374
+ return;
2375
+ }
2368
2376
  throw new MastraError(
2369
2377
  {
2370
2378
  id: "STORAGE_UPSTASH_VECTOR_DELETE_INDEX_FAILED",
@@ -2377,47 +2385,124 @@ var UpstashVector = class extends MastraVector {
2377
2385
  }
2378
2386
  }
2379
2387
  /**
2380
- * Updates a vector by its ID with the provided vector and/or metadata.
2381
- * @param indexName - The name of the namespace containing the vector.
2382
- * @param id - The ID of the vector to update.
2383
- * @param update - An object containing the vector and/or metadata to update.
2384
- * @param update.vector - An optional array of numbers representing the new vector.
2385
- * @param update.metadata - An optional record containing the new metadata.
2388
+ * Updates a vector by its ID or multiple vectors matching a filter.
2389
+ * @param params - Parameters containing the id or filter for targeting the vector(s) to update
2390
+ * @param params.indexName - The name of the namespace containing the vector.
2391
+ * @param params.id - The ID of the vector to update (mutually exclusive with filter).
2392
+ * @param params.filter - Filter to match multiple vectors to update (mutually exclusive with id).
2393
+ * @param params.update - An object containing the vector and/or metadata to update.
2386
2394
  * @returns A promise that resolves when the update is complete.
2387
2395
  * @throws Will throw an error if no updates are provided or if the update operation fails.
2388
2396
  */
2389
- async updateVector({ indexName: namespace, id, update }) {
2390
- if (!update.vector && !update.metadata && !update.sparseVector) {
2397
+ async updateVector(params) {
2398
+ const { indexName: namespace, update } = params;
2399
+ const upstashUpdate = update;
2400
+ const sparseVector = upstashUpdate.sparseVector;
2401
+ if ("id" in params && params.id && "filter" in params && params.filter) {
2391
2402
  throw new MastraError({
2392
- id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
2403
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_MUTUALLY_EXCLUSIVE",
2404
+ text: "Cannot specify both id and filter - they are mutually exclusive",
2393
2405
  domain: ErrorDomain.STORAGE,
2394
- category: ErrorCategory.THIRD_PARTY,
2395
- details: { namespace, id },
2396
- text: "No update data provided"
2406
+ category: ErrorCategory.USER,
2407
+ details: { namespace }
2397
2408
  });
2398
2409
  }
2399
- if (!update.vector && !update.sparseVector && update.metadata) {
2410
+ if (!("id" in params && params.id) && !("filter" in params && params.filter)) {
2400
2411
  throw new MastraError({
2401
- id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
2412
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_NO_TARGET",
2413
+ text: "Either id or filter must be provided",
2402
2414
  domain: ErrorDomain.STORAGE,
2403
- category: ErrorCategory.THIRD_PARTY,
2404
- details: { namespace, id },
2405
- text: "Both vector and metadata must be provided for an update"
2415
+ category: ErrorCategory.USER,
2416
+ details: { namespace }
2417
+ });
2418
+ }
2419
+ if (!update.vector && !update.metadata && !sparseVector) {
2420
+ throw new MastraError({
2421
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_NO_PAYLOAD",
2422
+ text: "No update data provided",
2423
+ domain: ErrorDomain.STORAGE,
2424
+ category: ErrorCategory.USER,
2425
+ details: { namespace }
2426
+ });
2427
+ }
2428
+ if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
2429
+ throw new MastraError({
2430
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_EMPTY_FILTER",
2431
+ text: "Filter cannot be an empty filter object",
2432
+ domain: ErrorDomain.STORAGE,
2433
+ category: ErrorCategory.USER,
2434
+ details: { namespace }
2406
2435
  });
2407
2436
  }
2408
2437
  try {
2409
- const points = { id };
2410
- if (update.vector) points.vector = update.vector;
2411
- if (update.metadata) points.metadata = update.metadata;
2412
- if (update.sparseVector) points.sparseVector = update.sparseVector;
2413
- await this.client.upsert(points, { namespace });
2438
+ const ns = this.client.namespace(namespace);
2439
+ if ("id" in params && params.id) {
2440
+ const points = { id: params.id };
2441
+ if (!update.vector || !update.metadata) {
2442
+ try {
2443
+ const existing = await ns.fetch([params.id], {
2444
+ includeVectors: true,
2445
+ includeMetadata: true
2446
+ });
2447
+ if (existing && existing.length > 0 && existing[0]) {
2448
+ if (!update.vector && existing[0]?.vector) {
2449
+ points.vector = existing[0].vector;
2450
+ }
2451
+ if (!update.metadata && existing[0]?.metadata) {
2452
+ points.metadata = existing[0].metadata;
2453
+ }
2454
+ }
2455
+ } catch (fetchError) {
2456
+ this.logger.warn(`Failed to fetch existing vector ${params.id} for partial update: ${fetchError}`);
2457
+ }
2458
+ }
2459
+ if (update.vector) points.vector = update.vector;
2460
+ if (update.metadata) points.metadata = update.metadata;
2461
+ if (sparseVector) points.sparseVector = sparseVector;
2462
+ await ns.upsert(points);
2463
+ } else if ("filter" in params && params.filter) {
2464
+ const filterString = this.transformFilter(params.filter);
2465
+ if (filterString) {
2466
+ const stats = await this.describeIndex({ indexName: namespace });
2467
+ const dummyVector = new Array(stats.dimension).fill(1 / Math.sqrt(stats.dimension));
2468
+ const needsVectors = !update.vector;
2469
+ const results = await ns.query({
2470
+ vector: dummyVector,
2471
+ topK: 1e3,
2472
+ // Upstash's max query limit
2473
+ filter: filterString,
2474
+ includeVectors: needsVectors,
2475
+ includeMetadata: needsVectors
2476
+ });
2477
+ for (const result of results) {
2478
+ const points = { id: `${result.id}` };
2479
+ if (update.vector) {
2480
+ points.vector = update.vector;
2481
+ } else if (result.vector) {
2482
+ points.vector = result.vector;
2483
+ }
2484
+ if (update.metadata) {
2485
+ points.metadata = update.metadata;
2486
+ } else if (result.metadata) {
2487
+ points.metadata = result.metadata;
2488
+ }
2489
+ if (sparseVector) points.sparseVector = sparseVector;
2490
+ await ns.upsert(points);
2491
+ }
2492
+ }
2493
+ }
2414
2494
  } catch (error) {
2495
+ if (error instanceof MastraError) throw error;
2415
2496
  throw new MastraError(
2416
2497
  {
2417
2498
  id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
2418
2499
  domain: ErrorDomain.STORAGE,
2419
2500
  category: ErrorCategory.THIRD_PARTY,
2420
- details: { namespace, id }
2501
+ details: {
2502
+ namespace,
2503
+ ..."id" in params && params.id && { id: params.id },
2504
+ ..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) }
2505
+ }
2421
2506
  },
2422
2507
  error
2423
2508
  );
@@ -2432,22 +2517,109 @@ var UpstashVector = class extends MastraVector {
2432
2517
  */
2433
2518
  async deleteVector({ indexName: namespace, id }) {
2434
2519
  try {
2435
- await this.client.delete(id, {
2436
- namespace
2437
- });
2520
+ const ns = this.client.namespace(namespace);
2521
+ await ns.delete(id);
2438
2522
  } catch (error) {
2439
2523
  const mastraError = new MastraError(
2440
2524
  {
2441
2525
  id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTOR_FAILED",
2442
2526
  domain: ErrorDomain.STORAGE,
2443
2527
  category: ErrorCategory.THIRD_PARTY,
2444
- details: { namespace, id }
2528
+ details: {
2529
+ namespace,
2530
+ ...id && { id }
2531
+ }
2445
2532
  },
2446
2533
  error
2447
2534
  );
2448
2535
  this.logger?.error(mastraError.toString());
2449
2536
  }
2450
2537
  }
2538
+ /**
2539
+ * Deletes multiple vectors by IDs or filter.
2540
+ * @param indexName - The name of the namespace containing the vectors.
2541
+ * @param ids - Array of vector IDs to delete (mutually exclusive with filter).
2542
+ * @param filter - Filter to match vectors to delete (mutually exclusive with ids).
2543
+ * @returns A promise that resolves when the deletion is complete.
2544
+ * @throws Will throw an error if both ids and filter are provided, or if neither is provided.
2545
+ */
2546
+ async deleteVectors({ indexName: namespace, filter, ids }) {
2547
+ if (ids && filter) {
2548
+ throw new MastraError({
2549
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_MUTUALLY_EXCLUSIVE",
2550
+ text: "Cannot specify both ids and filter - they are mutually exclusive",
2551
+ domain: ErrorDomain.STORAGE,
2552
+ category: ErrorCategory.USER,
2553
+ details: { namespace }
2554
+ });
2555
+ }
2556
+ if (!ids && !filter) {
2557
+ throw new MastraError({
2558
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_NO_TARGET",
2559
+ text: "Either filter or ids must be provided",
2560
+ domain: ErrorDomain.STORAGE,
2561
+ category: ErrorCategory.USER,
2562
+ details: { namespace }
2563
+ });
2564
+ }
2565
+ if (ids && ids.length === 0) {
2566
+ throw new MastraError({
2567
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_EMPTY_IDS",
2568
+ text: "Cannot delete with empty ids array",
2569
+ domain: ErrorDomain.STORAGE,
2570
+ category: ErrorCategory.USER,
2571
+ details: { namespace }
2572
+ });
2573
+ }
2574
+ if (filter && Object.keys(filter).length === 0) {
2575
+ throw new MastraError({
2576
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_EMPTY_FILTER",
2577
+ text: "Cannot delete with empty filter object",
2578
+ domain: ErrorDomain.STORAGE,
2579
+ category: ErrorCategory.USER,
2580
+ details: { namespace }
2581
+ });
2582
+ }
2583
+ try {
2584
+ const ns = this.client.namespace(namespace);
2585
+ if (ids) {
2586
+ await ns.delete(ids);
2587
+ } else if (filter) {
2588
+ const filterString = this.transformFilter(filter);
2589
+ if (filterString) {
2590
+ const stats = await this.describeIndex({ indexName: namespace });
2591
+ const dummyVector = new Array(stats.dimension).fill(1 / Math.sqrt(stats.dimension));
2592
+ const results = await ns.query({
2593
+ vector: dummyVector,
2594
+ topK: 1e3,
2595
+ // Upstash's max query limit
2596
+ filter: filterString,
2597
+ includeVectors: false,
2598
+ includeMetadata: false
2599
+ });
2600
+ const idsToDelete = results.map((r) => `${r.id}`);
2601
+ if (idsToDelete.length > 0) {
2602
+ await ns.delete(idsToDelete);
2603
+ }
2604
+ }
2605
+ }
2606
+ } catch (error) {
2607
+ if (error instanceof MastraError) throw error;
2608
+ throw new MastraError(
2609
+ {
2610
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_FAILED",
2611
+ domain: ErrorDomain.STORAGE,
2612
+ category: ErrorCategory.THIRD_PARTY,
2613
+ details: {
2614
+ namespace,
2615
+ ...filter && { filter: JSON.stringify(filter) },
2616
+ ...ids && { idsCount: ids.length }
2617
+ }
2618
+ },
2619
+ error
2620
+ );
2621
+ }
2622
+ }
2451
2623
  };
2452
2624
 
2453
2625
  // src/vector/prompt.ts