@mastra/upstash 0.11.1-alpha.0 → 0.11.1-alpha.2

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
@@ -1,5 +1,6 @@
1
1
  import { MessageList } from '@mastra/core/agent';
2
- import { MastraStorage, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT, TABLE_EVALS, TABLE_TRACES, TABLE_THREADS } from '@mastra/core/storage';
2
+ import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
3
+ import { MastraStorage, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT, TABLE_EVALS, TABLE_TRACES, TABLE_THREADS, TABLE_RESOURCES } from '@mastra/core/storage';
3
4
  import { Redis } from '@upstash/redis';
4
5
  import { MastraVector } from '@mastra/core/vector';
5
6
  import { Index } from '@upstash/vector';
@@ -17,7 +18,8 @@ var UpstashStore = class extends MastraStorage {
17
18
  }
18
19
  get supports() {
19
20
  return {
20
- selectByIncludeResourceScope: true
21
+ selectByIncludeResourceScope: true,
22
+ resourceWorkingMemory: true
21
23
  };
22
24
  }
23
25
  transformEvalRecord(record) {
@@ -197,7 +199,17 @@ var UpstashStore = class extends MastraStorage {
197
199
  }
198
200
  return filteredEvals.map((record) => this.transformEvalRecord(record));
199
201
  } catch (error) {
200
- console.error("Failed to get evals for the specified agent:", error);
202
+ const mastraError = new MastraError(
203
+ {
204
+ id: "STORAGE_UPSTASH_STORAGE_GET_EVALS_BY_AGENT_NAME_FAILED",
205
+ domain: ErrorDomain.STORAGE,
206
+ category: ErrorCategory.THIRD_PARTY,
207
+ details: { agentName }
208
+ },
209
+ error
210
+ );
211
+ this.logger?.trackException(mastraError);
212
+ this.logger.error(mastraError.toString());
201
213
  return [];
202
214
  }
203
215
  }
@@ -211,8 +223,19 @@ var UpstashStore = class extends MastraStorage {
211
223
  end: args.toDate
212
224
  };
213
225
  }
214
- const { traces } = await this.getTracesPaginated(args);
215
- return traces;
226
+ try {
227
+ const { traces } = await this.getTracesPaginated(args);
228
+ return traces;
229
+ } catch (error) {
230
+ throw new MastraError(
231
+ {
232
+ id: "STORAGE_UPSTASH_STORAGE_GET_TRACES_FAILED",
233
+ domain: ErrorDomain.STORAGE,
234
+ category: ErrorCategory.THIRD_PARTY
235
+ },
236
+ error
237
+ );
238
+ }
216
239
  }
217
240
  async getTracesPaginated(args) {
218
241
  const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
@@ -296,7 +319,20 @@ var UpstashStore = class extends MastraStorage {
296
319
  hasMore
297
320
  };
298
321
  } catch (error) {
299
- console.error("Failed to get traces:", error);
322
+ const mastraError = new MastraError(
323
+ {
324
+ id: "STORAGE_UPSTASH_STORAGE_GET_TRACES_PAGINATED_FAILED",
325
+ domain: ErrorDomain.STORAGE,
326
+ category: ErrorCategory.THIRD_PARTY,
327
+ details: {
328
+ name: args.name || "",
329
+ scope: args.scope || ""
330
+ }
331
+ },
332
+ error
333
+ );
334
+ this.logger?.trackException(mastraError);
335
+ this.logger.error(mastraError.toString());
300
336
  return {
301
337
  traces: [],
302
338
  total: 0,
@@ -310,7 +346,21 @@ var UpstashStore = class extends MastraStorage {
310
346
  tableName,
311
347
  schema
312
348
  }) {
313
- await this.redis.set(`schema:${tableName}`, schema);
349
+ try {
350
+ await this.redis.set(`schema:${tableName}`, schema);
351
+ } catch (error) {
352
+ throw new MastraError(
353
+ {
354
+ id: "STORAGE_UPSTASH_STORAGE_CREATE_TABLE_FAILED",
355
+ domain: ErrorDomain.STORAGE,
356
+ category: ErrorCategory.THIRD_PARTY,
357
+ details: {
358
+ tableName
359
+ }
360
+ },
361
+ error
362
+ );
363
+ }
314
364
  }
315
365
  /**
316
366
  * No-op: This backend is schemaless and does not require schema changes.
@@ -322,43 +372,113 @@ var UpstashStore = class extends MastraStorage {
322
372
  }
323
373
  async clearTable({ tableName }) {
324
374
  const pattern = `${tableName}:*`;
325
- await this.scanAndDelete(pattern);
375
+ try {
376
+ await this.scanAndDelete(pattern);
377
+ } catch (error) {
378
+ throw new MastraError(
379
+ {
380
+ id: "STORAGE_UPSTASH_STORAGE_CLEAR_TABLE_FAILED",
381
+ domain: ErrorDomain.STORAGE,
382
+ category: ErrorCategory.THIRD_PARTY,
383
+ details: {
384
+ tableName
385
+ }
386
+ },
387
+ error
388
+ );
389
+ }
326
390
  }
327
391
  async insert({ tableName, record }) {
328
392
  const { key, processedRecord } = this.processRecord(tableName, record);
329
- await this.redis.set(key, processedRecord);
393
+ try {
394
+ await this.redis.set(key, processedRecord);
395
+ } catch (error) {
396
+ throw new MastraError(
397
+ {
398
+ id: "STORAGE_UPSTASH_STORAGE_INSERT_FAILED",
399
+ domain: ErrorDomain.STORAGE,
400
+ category: ErrorCategory.THIRD_PARTY,
401
+ details: {
402
+ tableName
403
+ }
404
+ },
405
+ error
406
+ );
407
+ }
330
408
  }
331
409
  async batchInsert(input) {
332
410
  const { tableName, records } = input;
333
411
  if (!records.length) return;
334
412
  const batchSize = 1e3;
335
- for (let i = 0; i < records.length; i += batchSize) {
336
- const batch = records.slice(i, i + batchSize);
337
- const pipeline = this.redis.pipeline();
338
- for (const record of batch) {
339
- const { key, processedRecord } = this.processRecord(tableName, record);
340
- pipeline.set(key, processedRecord);
413
+ try {
414
+ for (let i = 0; i < records.length; i += batchSize) {
415
+ const batch = records.slice(i, i + batchSize);
416
+ const pipeline = this.redis.pipeline();
417
+ for (const record of batch) {
418
+ const { key, processedRecord } = this.processRecord(tableName, record);
419
+ pipeline.set(key, processedRecord);
420
+ }
421
+ await pipeline.exec();
341
422
  }
342
- await pipeline.exec();
423
+ } catch (error) {
424
+ throw new MastraError(
425
+ {
426
+ id: "STORAGE_UPSTASH_STORAGE_BATCH_INSERT_FAILED",
427
+ domain: ErrorDomain.STORAGE,
428
+ category: ErrorCategory.THIRD_PARTY,
429
+ details: {
430
+ tableName
431
+ }
432
+ },
433
+ error
434
+ );
343
435
  }
344
436
  }
345
437
  async load({ tableName, keys }) {
346
438
  const key = this.getKey(tableName, keys);
347
- const data = await this.redis.get(key);
348
- return data || null;
439
+ try {
440
+ const data = await this.redis.get(key);
441
+ return data || null;
442
+ } catch (error) {
443
+ throw new MastraError(
444
+ {
445
+ id: "STORAGE_UPSTASH_STORAGE_LOAD_FAILED",
446
+ domain: ErrorDomain.STORAGE,
447
+ category: ErrorCategory.THIRD_PARTY,
448
+ details: {
449
+ tableName
450
+ }
451
+ },
452
+ error
453
+ );
454
+ }
349
455
  }
350
456
  async getThreadById({ threadId }) {
351
- const thread = await this.load({
352
- tableName: TABLE_THREADS,
353
- keys: { id: threadId }
354
- });
355
- if (!thread) return null;
356
- return {
357
- ...thread,
358
- createdAt: this.ensureDate(thread.createdAt),
359
- updatedAt: this.ensureDate(thread.updatedAt),
360
- metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata
361
- };
457
+ try {
458
+ const thread = await this.load({
459
+ tableName: TABLE_THREADS,
460
+ keys: { id: threadId }
461
+ });
462
+ if (!thread) return null;
463
+ return {
464
+ ...thread,
465
+ createdAt: this.ensureDate(thread.createdAt),
466
+ updatedAt: this.ensureDate(thread.updatedAt),
467
+ metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata
468
+ };
469
+ } catch (error) {
470
+ throw new MastraError(
471
+ {
472
+ id: "STORAGE_UPSTASH_STORAGE_GET_THREAD_BY_ID_FAILED",
473
+ domain: ErrorDomain.STORAGE,
474
+ category: ErrorCategory.THIRD_PARTY,
475
+ details: {
476
+ threadId
477
+ }
478
+ },
479
+ error
480
+ );
481
+ }
362
482
  }
363
483
  /**
364
484
  * @deprecated use getThreadsByResourceIdPaginated instead
@@ -388,7 +508,19 @@ var UpstashStore = class extends MastraStorage {
388
508
  allThreads.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
389
509
  return allThreads;
390
510
  } catch (error) {
391
- console.error("Error in getThreadsByResourceId:", error);
511
+ const mastraError = new MastraError(
512
+ {
513
+ id: "STORAGE_UPSTASH_STORAGE_GET_THREADS_BY_RESOURCE_ID_FAILED",
514
+ domain: ErrorDomain.STORAGE,
515
+ category: ErrorCategory.THIRD_PARTY,
516
+ details: {
517
+ resourceId
518
+ }
519
+ },
520
+ error
521
+ );
522
+ this.logger?.trackException(mastraError);
523
+ this.logger.error(mastraError.toString());
392
524
  return [];
393
525
  }
394
526
  }
@@ -409,7 +541,21 @@ var UpstashStore = class extends MastraStorage {
409
541
  hasMore
410
542
  };
411
543
  } catch (error) {
412
- console.error("Error in getThreadsByResourceIdPaginated:", error);
544
+ const mastraError = new MastraError(
545
+ {
546
+ id: "STORAGE_UPSTASH_STORAGE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
547
+ domain: ErrorDomain.STORAGE,
548
+ category: ErrorCategory.THIRD_PARTY,
549
+ details: {
550
+ resourceId,
551
+ page,
552
+ perPage
553
+ }
554
+ },
555
+ error
556
+ );
557
+ this.logger?.trackException(mastraError);
558
+ this.logger.error(mastraError.toString());
413
559
  return {
414
560
  threads: [],
415
561
  total: 0,
@@ -420,11 +566,28 @@ var UpstashStore = class extends MastraStorage {
420
566
  }
421
567
  }
422
568
  async saveThread({ thread }) {
423
- await this.insert({
424
- tableName: TABLE_THREADS,
425
- record: thread
426
- });
427
- return thread;
569
+ try {
570
+ await this.insert({
571
+ tableName: TABLE_THREADS,
572
+ record: thread
573
+ });
574
+ return thread;
575
+ } catch (error) {
576
+ const mastraError = new MastraError(
577
+ {
578
+ id: "STORAGE_UPSTASH_STORAGE_SAVE_THREAD_FAILED",
579
+ domain: ErrorDomain.STORAGE,
580
+ category: ErrorCategory.THIRD_PARTY,
581
+ details: {
582
+ threadId: thread.id
583
+ }
584
+ },
585
+ error
586
+ );
587
+ this.logger?.trackException(mastraError);
588
+ this.logger.error(mastraError.toString());
589
+ throw mastraError;
590
+ }
428
591
  }
429
592
  async updateThread({
430
593
  id,
@@ -433,7 +596,15 @@ var UpstashStore = class extends MastraStorage {
433
596
  }) {
434
597
  const thread = await this.getThreadById({ threadId: id });
435
598
  if (!thread) {
436
- throw new Error(`Thread ${id} not found`);
599
+ throw new MastraError({
600
+ id: "STORAGE_UPSTASH_STORAGE_UPDATE_THREAD_FAILED",
601
+ domain: ErrorDomain.STORAGE,
602
+ category: ErrorCategory.USER,
603
+ text: `Thread ${id} not found`,
604
+ details: {
605
+ threadId: id
606
+ }
607
+ });
437
608
  }
438
609
  const updatedThread = {
439
610
  ...thread,
@@ -443,34 +614,73 @@ var UpstashStore = class extends MastraStorage {
443
614
  ...metadata
444
615
  }
445
616
  };
446
- await this.saveThread({ thread: updatedThread });
447
- return updatedThread;
617
+ try {
618
+ await this.saveThread({ thread: updatedThread });
619
+ return updatedThread;
620
+ } catch (error) {
621
+ throw new MastraError(
622
+ {
623
+ id: "STORAGE_UPSTASH_STORAGE_UPDATE_THREAD_FAILED",
624
+ domain: ErrorDomain.STORAGE,
625
+ category: ErrorCategory.THIRD_PARTY,
626
+ details: {
627
+ threadId: id
628
+ }
629
+ },
630
+ error
631
+ );
632
+ }
448
633
  }
449
634
  async deleteThread({ threadId }) {
450
635
  const threadKey = this.getKey(TABLE_THREADS, { id: threadId });
451
636
  const threadMessagesKey = this.getThreadMessagesKey(threadId);
452
- const messageIds = await this.redis.zrange(threadMessagesKey, 0, -1);
453
- const pipeline = this.redis.pipeline();
454
- pipeline.del(threadKey);
455
- pipeline.del(threadMessagesKey);
456
- for (let i = 0; i < messageIds.length; i++) {
457
- const messageId = messageIds[i];
458
- const messageKey = this.getMessageKey(threadId, messageId);
459
- pipeline.del(messageKey);
637
+ try {
638
+ const messageIds = await this.redis.zrange(threadMessagesKey, 0, -1);
639
+ const pipeline = this.redis.pipeline();
640
+ pipeline.del(threadKey);
641
+ pipeline.del(threadMessagesKey);
642
+ for (let i = 0; i < messageIds.length; i++) {
643
+ const messageId = messageIds[i];
644
+ const messageKey = this.getMessageKey(threadId, messageId);
645
+ pipeline.del(messageKey);
646
+ }
647
+ await pipeline.exec();
648
+ await this.scanAndDelete(this.getMessageKey(threadId, "*"));
649
+ } catch (error) {
650
+ throw new MastraError(
651
+ {
652
+ id: "STORAGE_UPSTASH_STORAGE_DELETE_THREAD_FAILED",
653
+ domain: ErrorDomain.STORAGE,
654
+ category: ErrorCategory.THIRD_PARTY,
655
+ details: {
656
+ threadId
657
+ }
658
+ },
659
+ error
660
+ );
460
661
  }
461
- await pipeline.exec();
462
- await this.scanAndDelete(this.getMessageKey(threadId, "*"));
463
662
  }
464
663
  async saveMessages(args) {
465
664
  const { messages, format = "v1" } = args;
466
665
  if (messages.length === 0) return [];
467
666
  const threadId = messages[0]?.threadId;
468
- if (!threadId) {
469
- throw new Error("Thread ID is required");
470
- }
471
- const thread = await this.getThreadById({ threadId });
472
- if (!thread) {
473
- throw new Error(`Thread ${threadId} not found`);
667
+ try {
668
+ if (!threadId) {
669
+ throw new Error("Thread ID is required");
670
+ }
671
+ const thread = await this.getThreadById({ threadId });
672
+ if (!thread) {
673
+ throw new Error(`Thread ${threadId} not found`);
674
+ }
675
+ } catch (error) {
676
+ throw new MastraError(
677
+ {
678
+ id: "STORAGE_UPSTASH_STORAGE_SAVE_MESSAGES_INVALID_ARGS",
679
+ domain: ErrorDomain.STORAGE,
680
+ category: ErrorCategory.USER
681
+ },
682
+ error
683
+ );
474
684
  }
475
685
  const messagesWithIndex = messages.map((message, index) => ({
476
686
  ...message,
@@ -478,32 +688,63 @@ var UpstashStore = class extends MastraStorage {
478
688
  }));
479
689
  const threadKey = this.getKey(TABLE_THREADS, { id: threadId });
480
690
  const existingThread = await this.redis.get(threadKey);
481
- const batchSize = 1e3;
482
- for (let i = 0; i < messagesWithIndex.length; i += batchSize) {
483
- const batch = messagesWithIndex.slice(i, i + batchSize);
484
- const pipeline = this.redis.pipeline();
485
- for (const message of batch) {
486
- const key = this.getMessageKey(message.threadId, message.id);
487
- const createdAtScore = new Date(message.createdAt).getTime();
488
- const score = message._index !== void 0 ? message._index : createdAtScore;
489
- pipeline.set(key, message);
490
- pipeline.zadd(this.getThreadMessagesKey(message.threadId), {
491
- score,
492
- member: message.id
493
- });
494
- }
495
- if (i === 0 && existingThread) {
496
- const updatedThread = {
497
- ...existingThread,
498
- updatedAt: /* @__PURE__ */ new Date()
499
- };
500
- pipeline.set(threadKey, this.processRecord(TABLE_THREADS, updatedThread).processedRecord);
691
+ try {
692
+ const batchSize = 1e3;
693
+ for (let i = 0; i < messagesWithIndex.length; i += batchSize) {
694
+ const batch = messagesWithIndex.slice(i, i + batchSize);
695
+ const pipeline = this.redis.pipeline();
696
+ for (const message of batch) {
697
+ const key = this.getMessageKey(message.threadId, message.id);
698
+ const createdAtScore = new Date(message.createdAt).getTime();
699
+ const score = message._index !== void 0 ? message._index : createdAtScore;
700
+ const existingKeyPattern = this.getMessageKey("*", message.id);
701
+ const keys = await this.scanKeys(existingKeyPattern);
702
+ if (keys.length > 0) {
703
+ const pipeline2 = this.redis.pipeline();
704
+ keys.forEach((key2) => pipeline2.get(key2));
705
+ const results = await pipeline2.exec();
706
+ const existingMessages = results.filter(
707
+ (msg) => msg !== null
708
+ );
709
+ for (const existingMessage of existingMessages) {
710
+ const existingMessageKey = this.getMessageKey(existingMessage.threadId, existingMessage.id);
711
+ if (existingMessage && existingMessage.threadId !== message.threadId) {
712
+ pipeline.del(existingMessageKey);
713
+ pipeline.zrem(this.getThreadMessagesKey(existingMessage.threadId), existingMessage.id);
714
+ }
715
+ }
716
+ }
717
+ pipeline.set(key, message);
718
+ pipeline.zadd(this.getThreadMessagesKey(message.threadId), {
719
+ score,
720
+ member: message.id
721
+ });
722
+ }
723
+ if (i === 0 && existingThread) {
724
+ const updatedThread = {
725
+ ...existingThread,
726
+ updatedAt: /* @__PURE__ */ new Date()
727
+ };
728
+ pipeline.set(threadKey, this.processRecord(TABLE_THREADS, updatedThread).processedRecord);
729
+ }
730
+ await pipeline.exec();
501
731
  }
502
- await pipeline.exec();
732
+ const list = new MessageList().add(messages, "memory");
733
+ if (format === `v2`) return list.get.all.v2();
734
+ return list.get.all.v1();
735
+ } catch (error) {
736
+ throw new MastraError(
737
+ {
738
+ id: "STORAGE_UPSTASH_STORAGE_SAVE_MESSAGES_FAILED",
739
+ domain: ErrorDomain.STORAGE,
740
+ category: ErrorCategory.THIRD_PARTY,
741
+ details: {
742
+ threadId
743
+ }
744
+ },
745
+ error
746
+ );
503
747
  }
504
- const list = new MessageList().add(messages, "memory");
505
- if (format === `v2`) return list.get.all.v2();
506
- return list.get.all.v1();
507
748
  }
508
749
  async _getIncludedMessages(threadId, selectBy) {
509
750
  const messageIds = /* @__PURE__ */ new Set();
@@ -548,63 +789,72 @@ var UpstashStore = class extends MastraStorage {
548
789
  format
549
790
  }) {
550
791
  const threadMessagesKey = this.getThreadMessagesKey(threadId);
551
- const allMessageIds = await this.redis.zrange(threadMessagesKey, 0, -1);
552
- let limit;
553
- if (typeof selectBy?.last === "number") {
554
- limit = Math.max(0, selectBy.last);
555
- } else if (selectBy?.last === false) {
556
- limit = 0;
557
- } else {
558
- limit = Number.MAX_SAFE_INTEGER;
559
- }
560
- const messageIds = /* @__PURE__ */ new Set();
561
- const messageIdToThreadIds = {};
562
- if (limit === 0 && !selectBy?.include) {
563
- return [];
564
- }
565
- if (limit === Number.MAX_SAFE_INTEGER) {
566
- const allIds = await this.redis.zrange(threadMessagesKey, 0, -1);
567
- allIds.forEach((id) => {
568
- messageIds.add(id);
569
- messageIdToThreadIds[id] = threadId;
792
+ try {
793
+ const allMessageIds = await this.redis.zrange(threadMessagesKey, 0, -1);
794
+ const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
795
+ const messageIds = /* @__PURE__ */ new Set();
796
+ const messageIdToThreadIds = {};
797
+ if (limit === 0 && !selectBy?.include) {
798
+ return [];
799
+ }
800
+ if (limit === Number.MAX_SAFE_INTEGER) {
801
+ const allIds = await this.redis.zrange(threadMessagesKey, 0, -1);
802
+ allIds.forEach((id) => {
803
+ messageIds.add(id);
804
+ messageIdToThreadIds[id] = threadId;
805
+ });
806
+ } else if (limit > 0) {
807
+ const latestIds = await this.redis.zrange(threadMessagesKey, -limit, -1);
808
+ latestIds.forEach((id) => {
809
+ messageIds.add(id);
810
+ messageIdToThreadIds[id] = threadId;
811
+ });
812
+ }
813
+ const includedMessages = await this._getIncludedMessages(threadId, selectBy);
814
+ const messages = [
815
+ ...includedMessages,
816
+ ...(await Promise.all(
817
+ Array.from(messageIds).map(async (id) => {
818
+ const tId = messageIdToThreadIds[id] || threadId;
819
+ const byThreadId = await this.redis.get(
820
+ this.getMessageKey(tId, id)
821
+ );
822
+ if (byThreadId) return byThreadId;
823
+ return null;
824
+ })
825
+ )).filter((msg) => msg !== null)
826
+ ];
827
+ messages.sort((a, b) => allMessageIds.indexOf(a.id) - allMessageIds.indexOf(b.id));
828
+ const seen = /* @__PURE__ */ new Set();
829
+ const dedupedMessages = messages.filter((row) => {
830
+ if (seen.has(row.id)) return false;
831
+ seen.add(row.id);
832
+ return true;
570
833
  });
571
- } else if (limit > 0) {
572
- const latestIds = await this.redis.zrange(threadMessagesKey, -limit, -1);
573
- latestIds.forEach((id) => {
574
- messageIds.add(id);
575
- messageIdToThreadIds[id] = threadId;
834
+ const prepared = dedupedMessages.filter((message) => message !== null && message !== void 0).map((message) => {
835
+ const { _index, ...messageWithoutIndex } = message;
836
+ return messageWithoutIndex;
576
837
  });
838
+ if (format === "v2") {
839
+ return prepared.map((msg) => ({
840
+ ...msg,
841
+ content: msg.content || { format: 2, parts: [{ type: "text", text: "" }] }
842
+ }));
843
+ }
844
+ return prepared;
845
+ } catch (error) {
846
+ throw new MastraError(
847
+ {
848
+ id: "STORAGE_UPSTASH_STORAGE_GET_MESSAGES_FAILED",
849
+ domain: ErrorDomain.STORAGE,
850
+ category: ErrorCategory.THIRD_PARTY,
851
+ details: {
852
+ threadId
853
+ }
854
+ },
855
+ error
856
+ );
577
857
  }
578
- const includedMessages = await this._getIncludedMessages(threadId, selectBy);
579
- const messages = [
580
- ...includedMessages,
581
- ...(await Promise.all(
582
- Array.from(messageIds).map(async (id) => {
583
- const tId = messageIdToThreadIds[id] || threadId;
584
- const byThreadId = await this.redis.get(this.getMessageKey(tId, id));
585
- if (byThreadId) return byThreadId;
586
- return null;
587
- })
588
- )).filter((msg) => msg !== null)
589
- ];
590
- messages.sort((a, b) => allMessageIds.indexOf(a.id) - allMessageIds.indexOf(b.id));
591
- const seen = /* @__PURE__ */ new Set();
592
- const dedupedMessages = messages.filter((row) => {
593
- if (seen.has(row.id)) return false;
594
- seen.add(row.id);
595
- return true;
596
- });
597
- const prepared = dedupedMessages.filter((message) => message !== null && message !== void 0).map((message) => {
598
- const { _index, ...messageWithoutIndex } = message;
599
- return messageWithoutIndex;
600
- });
601
- if (format === "v2") {
602
- return prepared.map((msg) => ({
603
- ...msg,
604
- content: msg.content || { format: 2, parts: [{ type: "text", text: "" }] }
605
- }));
606
- }
607
- return prepared;
608
858
  }
609
859
  async getMessagesPaginated(args) {
610
860
  const { threadId, selectBy, format } = args;
@@ -613,9 +863,9 @@ var UpstashStore = class extends MastraStorage {
613
863
  const toDate = dateRange?.end;
614
864
  const threadMessagesKey = this.getThreadMessagesKey(threadId);
615
865
  const messages = [];
616
- const includedMessages = await this._getIncludedMessages(threadId, selectBy);
617
- messages.push(...includedMessages);
618
866
  try {
867
+ const includedMessages = await this._getIncludedMessages(threadId, selectBy);
868
+ messages.push(...includedMessages);
619
869
  const allMessageIds = await this.redis.zrange(threadMessagesKey, 0, -1);
620
870
  if (allMessageIds.length === 0) {
621
871
  return {
@@ -653,7 +903,19 @@ var UpstashStore = class extends MastraStorage {
653
903
  hasMore
654
904
  };
655
905
  } catch (error) {
656
- console.error("Failed to get paginated messages:", error);
906
+ const mastraError = new MastraError(
907
+ {
908
+ id: "STORAGE_UPSTASH_STORAGE_GET_MESSAGES_PAGINATED_FAILED",
909
+ domain: ErrorDomain.STORAGE,
910
+ category: ErrorCategory.THIRD_PARTY,
911
+ details: {
912
+ threadId
913
+ }
914
+ },
915
+ error
916
+ );
917
+ this.logger.error(mastraError.toString());
918
+ this.logger?.trackException(mastraError);
657
919
  return {
658
920
  messages: [],
659
921
  total: 0,
@@ -665,17 +927,33 @@ var UpstashStore = class extends MastraStorage {
665
927
  }
666
928
  async persistWorkflowSnapshot(params) {
667
929
  const { namespace = "workflows", workflowName, runId, snapshot } = params;
668
- await this.insert({
669
- tableName: TABLE_WORKFLOW_SNAPSHOT,
670
- record: {
671
- namespace,
672
- workflow_name: workflowName,
673
- run_id: runId,
674
- snapshot,
675
- createdAt: /* @__PURE__ */ new Date(),
676
- updatedAt: /* @__PURE__ */ new Date()
677
- }
678
- });
930
+ try {
931
+ await this.insert({
932
+ tableName: TABLE_WORKFLOW_SNAPSHOT,
933
+ record: {
934
+ namespace,
935
+ workflow_name: workflowName,
936
+ run_id: runId,
937
+ snapshot,
938
+ createdAt: /* @__PURE__ */ new Date(),
939
+ updatedAt: /* @__PURE__ */ new Date()
940
+ }
941
+ });
942
+ } catch (error) {
943
+ throw new MastraError(
944
+ {
945
+ id: "STORAGE_UPSTASH_STORAGE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
946
+ domain: ErrorDomain.STORAGE,
947
+ category: ErrorCategory.THIRD_PARTY,
948
+ details: {
949
+ namespace,
950
+ workflowName,
951
+ runId
952
+ }
953
+ },
954
+ error
955
+ );
956
+ }
679
957
  }
680
958
  async loadWorkflowSnapshot(params) {
681
959
  const { namespace = "workflows", workflowName, runId } = params;
@@ -684,9 +962,25 @@ var UpstashStore = class extends MastraStorage {
684
962
  workflow_name: workflowName,
685
963
  run_id: runId
686
964
  });
687
- const data = await this.redis.get(key);
688
- if (!data) return null;
689
- return data.snapshot;
965
+ try {
966
+ const data = await this.redis.get(key);
967
+ if (!data) return null;
968
+ return data.snapshot;
969
+ } catch (error) {
970
+ throw new MastraError(
971
+ {
972
+ id: "STORAGE_UPSTASH_STORAGE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
973
+ domain: ErrorDomain.STORAGE,
974
+ category: ErrorCategory.THIRD_PARTY,
975
+ details: {
976
+ namespace,
977
+ workflowName,
978
+ runId
979
+ }
980
+ },
981
+ error
982
+ );
983
+ }
690
984
  }
691
985
  /**
692
986
  * Get all evaluations with pagination and total count
@@ -775,7 +1069,20 @@ var UpstashStore = class extends MastraStorage {
775
1069
  };
776
1070
  } catch (error) {
777
1071
  const { page = 0, perPage = 100 } = options || {};
778
- console.error("Failed to get evals:", error);
1072
+ const mastraError = new MastraError(
1073
+ {
1074
+ id: "STORAGE_UPSTASH_STORAGE_GET_EVALS_FAILED",
1075
+ domain: ErrorDomain.STORAGE,
1076
+ category: ErrorCategory.THIRD_PARTY,
1077
+ details: {
1078
+ page,
1079
+ perPage
1080
+ }
1081
+ },
1082
+ error
1083
+ );
1084
+ this.logger.error(mastraError.toString());
1085
+ this.logger?.trackException(mastraError);
779
1086
  return {
780
1087
  evals: [],
781
1088
  total: 0,
@@ -828,8 +1135,19 @@ var UpstashStore = class extends MastraStorage {
828
1135
  }
829
1136
  return { runs, total };
830
1137
  } catch (error) {
831
- console.error("Error getting workflow runs:", error);
832
- throw error;
1138
+ throw new MastraError(
1139
+ {
1140
+ id: "STORAGE_UPSTASH_STORAGE_GET_WORKFLOW_RUNS_FAILED",
1141
+ domain: ErrorDomain.STORAGE,
1142
+ category: ErrorCategory.THIRD_PARTY,
1143
+ details: {
1144
+ namespace,
1145
+ workflowName: workflowName || "",
1146
+ resourceId: resourceId || ""
1147
+ }
1148
+ },
1149
+ error
1150
+ );
833
1151
  }
834
1152
  }
835
1153
  async getWorkflowRunById({
@@ -850,8 +1168,19 @@ var UpstashStore = class extends MastraStorage {
850
1168
  if (!data) return null;
851
1169
  return this.parseWorkflowRun(data);
852
1170
  } catch (error) {
853
- console.error("Error getting workflow run by ID:", error);
854
- throw error;
1171
+ throw new MastraError(
1172
+ {
1173
+ id: "STORAGE_UPSTASH_STORAGE_GET_WORKFLOW_RUN_BY_ID_FAILED",
1174
+ domain: ErrorDomain.STORAGE,
1175
+ category: ErrorCategory.THIRD_PARTY,
1176
+ details: {
1177
+ namespace,
1178
+ runId,
1179
+ workflowName: workflowName || ""
1180
+ }
1181
+ },
1182
+ error
1183
+ );
855
1184
  }
856
1185
  }
857
1186
  async close() {
@@ -860,6 +1189,75 @@ var UpstashStore = class extends MastraStorage {
860
1189
  this.logger.error("updateMessages is not yet implemented in UpstashStore");
861
1190
  throw new Error("Method not implemented");
862
1191
  }
1192
+ async getResourceById({ resourceId }) {
1193
+ try {
1194
+ const key = `${TABLE_RESOURCES}:${resourceId}`;
1195
+ const data = await this.redis.get(key);
1196
+ if (!data) {
1197
+ return null;
1198
+ }
1199
+ return {
1200
+ ...data,
1201
+ createdAt: new Date(data.createdAt),
1202
+ updatedAt: new Date(data.updatedAt),
1203
+ // Ensure workingMemory is always returned as a string, regardless of automatic parsing
1204
+ workingMemory: typeof data.workingMemory === "object" ? JSON.stringify(data.workingMemory) : data.workingMemory,
1205
+ metadata: typeof data.metadata === "string" ? JSON.parse(data.metadata) : data.metadata
1206
+ };
1207
+ } catch (error) {
1208
+ this.logger.error("Error getting resource by ID:", error);
1209
+ throw error;
1210
+ }
1211
+ }
1212
+ async saveResource({ resource }) {
1213
+ try {
1214
+ const key = `${TABLE_RESOURCES}:${resource.id}`;
1215
+ const serializedResource = {
1216
+ ...resource,
1217
+ metadata: JSON.stringify(resource.metadata),
1218
+ createdAt: resource.createdAt.toISOString(),
1219
+ updatedAt: resource.updatedAt.toISOString()
1220
+ };
1221
+ await this.redis.set(key, serializedResource);
1222
+ return resource;
1223
+ } catch (error) {
1224
+ this.logger.error("Error saving resource:", error);
1225
+ throw error;
1226
+ }
1227
+ }
1228
+ async updateResource({
1229
+ resourceId,
1230
+ workingMemory,
1231
+ metadata
1232
+ }) {
1233
+ try {
1234
+ const existingResource = await this.getResourceById({ resourceId });
1235
+ if (!existingResource) {
1236
+ const newResource = {
1237
+ id: resourceId,
1238
+ workingMemory,
1239
+ metadata: metadata || {},
1240
+ createdAt: /* @__PURE__ */ new Date(),
1241
+ updatedAt: /* @__PURE__ */ new Date()
1242
+ };
1243
+ return this.saveResource({ resource: newResource });
1244
+ }
1245
+ const updatedResource = {
1246
+ ...existingResource,
1247
+ workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
1248
+ metadata: {
1249
+ ...existingResource.metadata,
1250
+ ...metadata
1251
+ },
1252
+ updatedAt: /* @__PURE__ */ new Date()
1253
+ };
1254
+ await this.saveResource({ resource: updatedResource });
1255
+ return updatedResource;
1256
+ } catch (error) {
1257
+ this.logger.error("Error updating resource:", error);
1258
+ throw error;
1259
+ }
1260
+ }
863
1261
  };
864
1262
  var UpstashFilterTranslator = class extends BaseFilterTranslator {
865
1263
  getSupportedOperators() {
@@ -1081,14 +1479,26 @@ var UpstashVector = class extends MastraVector {
1081
1479
  vector,
1082
1480
  metadata: metadata?.[index]
1083
1481
  }));
1084
- await this.client.upsert(points, {
1085
- namespace
1086
- });
1087
- return generatedIds;
1482
+ try {
1483
+ await this.client.upsert(points, {
1484
+ namespace
1485
+ });
1486
+ return generatedIds;
1487
+ } catch (error) {
1488
+ throw new MastraError(
1489
+ {
1490
+ id: "STORAGE_UPSTASH_VECTOR_UPSERT_FAILED",
1491
+ domain: ErrorDomain.STORAGE,
1492
+ category: ErrorCategory.THIRD_PARTY,
1493
+ details: { namespace, vectorCount: vectors.length }
1494
+ },
1495
+ error
1496
+ );
1497
+ }
1088
1498
  }
1089
1499
  /**
1090
1500
  * Transforms a Mastra vector filter into an Upstash-compatible filter string.
1091
- * @param {VectorFilter} [filter] - The filter to transform.
1501
+ * @param {UpstashVectorFilter} [filter] - The filter to transform.
1092
1502
  * @returns {string | undefined} The transformed filter string, or undefined if no filter is provided.
1093
1503
  */
1094
1504
  transformFilter(filter) {
@@ -1115,29 +1525,52 @@ var UpstashVector = class extends MastraVector {
1115
1525
  filter,
1116
1526
  includeVector = false
1117
1527
  }) {
1118
- const ns = this.client.namespace(namespace);
1119
- const filterString = this.transformFilter(filter);
1120
- const results = await ns.query({
1121
- topK,
1122
- vector: queryVector,
1123
- includeVectors: includeVector,
1124
- includeMetadata: true,
1125
- ...filterString ? { filter: filterString } : {}
1126
- });
1127
- return (results || []).map((result) => ({
1128
- id: `${result.id}`,
1129
- score: result.score,
1130
- metadata: result.metadata,
1131
- ...includeVector && { vector: result.vector || [] }
1132
- }));
1528
+ try {
1529
+ const ns = this.client.namespace(namespace);
1530
+ const filterString = this.transformFilter(filter);
1531
+ const results = await ns.query({
1532
+ topK,
1533
+ vector: queryVector,
1534
+ includeVectors: includeVector,
1535
+ includeMetadata: true,
1536
+ ...filterString ? { filter: filterString } : {}
1537
+ });
1538
+ return (results || []).map((result) => ({
1539
+ id: `${result.id}`,
1540
+ score: result.score,
1541
+ metadata: result.metadata,
1542
+ ...includeVector && { vector: result.vector || [] }
1543
+ }));
1544
+ } catch (error) {
1545
+ throw new MastraError(
1546
+ {
1547
+ id: "STORAGE_UPSTASH_VECTOR_QUERY_FAILED",
1548
+ domain: ErrorDomain.STORAGE,
1549
+ category: ErrorCategory.THIRD_PARTY,
1550
+ details: { namespace, topK }
1551
+ },
1552
+ error
1553
+ );
1554
+ }
1133
1555
  }
1134
1556
  /**
1135
1557
  * Lists all namespaces in the Upstash vector index, which correspond to indexes.
1136
1558
  * @returns {Promise<string[]>} A promise that resolves to a list of index names.
1137
1559
  */
1138
1560
  async listIndexes() {
1139
- const indexes = await this.client.listNamespaces();
1140
- return indexes.filter(Boolean);
1561
+ try {
1562
+ const indexes = await this.client.listNamespaces();
1563
+ return indexes.filter(Boolean);
1564
+ } catch (error) {
1565
+ throw new MastraError(
1566
+ {
1567
+ id: "STORAGE_UPSTASH_VECTOR_LIST_INDEXES_FAILED",
1568
+ domain: ErrorDomain.STORAGE,
1569
+ category: ErrorCategory.THIRD_PARTY
1570
+ },
1571
+ error
1572
+ );
1573
+ }
1141
1574
  }
1142
1575
  /**
1143
1576
  * Retrieves statistics about a vector index.
@@ -1146,12 +1579,24 @@ var UpstashVector = class extends MastraVector {
1146
1579
  * @returns A promise that resolves to the index statistics including dimension, count and metric
1147
1580
  */
1148
1581
  async describeIndex({ indexName: namespace }) {
1149
- const info = await this.client.info();
1150
- return {
1151
- dimension: info.dimension,
1152
- count: info.namespaces?.[namespace]?.vectorCount || 0,
1153
- metric: info?.similarityFunction?.toLowerCase()
1154
- };
1582
+ try {
1583
+ const info = await this.client.info();
1584
+ return {
1585
+ dimension: info.dimension,
1586
+ count: info.namespaces?.[namespace]?.vectorCount || 0,
1587
+ metric: info?.similarityFunction?.toLowerCase()
1588
+ };
1589
+ } catch (error) {
1590
+ throw new MastraError(
1591
+ {
1592
+ id: "STORAGE_UPSTASH_VECTOR_DESCRIBE_INDEX_FAILED",
1593
+ domain: ErrorDomain.STORAGE,
1594
+ category: ErrorCategory.THIRD_PARTY,
1595
+ details: { namespace }
1596
+ },
1597
+ error
1598
+ );
1599
+ }
1155
1600
  }
1156
1601
  /**
1157
1602
  * Deletes an index (namespace).
@@ -1162,7 +1607,15 @@ var UpstashVector = class extends MastraVector {
1162
1607
  try {
1163
1608
  await this.client.deleteNamespace(namespace);
1164
1609
  } catch (error) {
1165
- this.logger.error("Failed to delete namespace:", error);
1610
+ throw new MastraError(
1611
+ {
1612
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_INDEX_FAILED",
1613
+ domain: ErrorDomain.STORAGE,
1614
+ category: ErrorCategory.THIRD_PARTY,
1615
+ details: { namespace }
1616
+ },
1617
+ error
1618
+ );
1166
1619
  }
1167
1620
  }
1168
1621
  /**
@@ -1183,6 +1636,18 @@ var UpstashVector = class extends MastraVector {
1183
1636
  if (!update.vector && update.metadata) {
1184
1637
  throw new Error("Both vector and metadata must be provided for an update");
1185
1638
  }
1639
+ } catch (error) {
1640
+ throw new MastraError(
1641
+ {
1642
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
1643
+ domain: ErrorDomain.STORAGE,
1644
+ category: ErrorCategory.THIRD_PARTY,
1645
+ details: { namespace, id }
1646
+ },
1647
+ error
1648
+ );
1649
+ }
1650
+ try {
1186
1651
  const updatePayload = { id };
1187
1652
  if (update.vector) {
1188
1653
  updatePayload.vector = update.vector;
@@ -1199,7 +1664,15 @@ var UpstashVector = class extends MastraVector {
1199
1664
  namespace
1200
1665
  });
1201
1666
  } catch (error) {
1202
- throw new Error(`Failed to update vector by id: ${id} for index name: ${namespace}: ${error.message}`);
1667
+ throw new MastraError(
1668
+ {
1669
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
1670
+ domain: ErrorDomain.STORAGE,
1671
+ category: ErrorCategory.THIRD_PARTY,
1672
+ details: { namespace, id }
1673
+ },
1674
+ error
1675
+ );
1203
1676
  }
1204
1677
  }
1205
1678
  /**
@@ -1215,7 +1688,16 @@ var UpstashVector = class extends MastraVector {
1215
1688
  namespace
1216
1689
  });
1217
1690
  } catch (error) {
1218
- this.logger.error(`Failed to delete vector by id: ${id} for namespace: ${namespace}:`, error);
1691
+ const mastraError = new MastraError(
1692
+ {
1693
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTOR_FAILED",
1694
+ domain: ErrorDomain.STORAGE,
1695
+ category: ErrorCategory.THIRD_PARTY,
1696
+ details: { namespace, id }
1697
+ },
1698
+ error
1699
+ );
1700
+ this.logger?.error(mastraError.toString());
1219
1701
  }
1220
1702
  }
1221
1703
  };