@mastra/dynamodb 0.0.0-working-memory-per-user-20250620163010 → 0.0.0-zod-v4-compat-part-2-20250822105954

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.
Files changed (54) hide show
  1. package/LICENSE.md +11 -42
  2. package/dist/entities/eval.d.ts +102 -0
  3. package/dist/entities/eval.d.ts.map +1 -0
  4. package/dist/entities/index.d.ts +732 -0
  5. package/dist/entities/index.d.ts.map +1 -0
  6. package/dist/entities/message.d.ts +100 -0
  7. package/dist/entities/message.d.ts.map +1 -0
  8. package/dist/entities/resource.d.ts +54 -0
  9. package/dist/entities/resource.d.ts.map +1 -0
  10. package/dist/entities/score.d.ts +215 -0
  11. package/dist/entities/score.d.ts.map +1 -0
  12. package/dist/entities/thread.d.ts +69 -0
  13. package/dist/entities/thread.d.ts.map +1 -0
  14. package/dist/entities/trace.d.ts +127 -0
  15. package/dist/entities/trace.d.ts.map +1 -0
  16. package/dist/entities/utils.d.ts +21 -0
  17. package/dist/entities/utils.d.ts.map +1 -0
  18. package/dist/entities/workflow-snapshot.d.ts +74 -0
  19. package/dist/entities/workflow-snapshot.d.ts.map +1 -0
  20. package/dist/index.cjs +2176 -516
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +2163 -503
  25. package/dist/index.js.map +1 -0
  26. package/dist/storage/domains/legacy-evals/index.d.ts +19 -0
  27. package/dist/storage/domains/legacy-evals/index.d.ts.map +1 -0
  28. package/dist/storage/domains/memory/index.d.ts +77 -0
  29. package/dist/storage/domains/memory/index.d.ts.map +1 -0
  30. package/dist/storage/domains/operations/index.d.ts +69 -0
  31. package/dist/storage/domains/operations/index.d.ts.map +1 -0
  32. package/dist/storage/domains/score/index.d.ts +42 -0
  33. package/dist/storage/domains/score/index.d.ts.map +1 -0
  34. package/dist/storage/domains/traces/index.d.ts +28 -0
  35. package/dist/storage/domains/traces/index.d.ts.map +1 -0
  36. package/dist/storage/domains/workflows/index.d.ts +32 -0
  37. package/dist/storage/domains/workflows/index.d.ts.map +1 -0
  38. package/dist/storage/index.d.ts +220 -0
  39. package/dist/storage/index.d.ts.map +1 -0
  40. package/package.json +12 -12
  41. package/src/entities/index.ts +5 -1
  42. package/src/entities/resource.ts +57 -0
  43. package/src/entities/score.ts +285 -0
  44. package/src/storage/domains/legacy-evals/index.ts +243 -0
  45. package/src/storage/domains/memory/index.ts +894 -0
  46. package/src/storage/domains/operations/index.ts +433 -0
  47. package/src/storage/domains/score/index.ts +285 -0
  48. package/src/storage/domains/traces/index.ts +286 -0
  49. package/src/storage/domains/workflows/index.ts +297 -0
  50. package/src/storage/index.test.ts +1347 -1216
  51. package/src/storage/index.ts +211 -881
  52. package/dist/_tsup-dts-rollup.d.cts +0 -1157
  53. package/dist/_tsup-dts-rollup.d.ts +0 -1157
  54. package/dist/index.d.cts +0 -2
package/dist/index.cjs CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  var clientDynamodb = require('@aws-sdk/client-dynamodb');
4
4
  var libDynamodb = require('@aws-sdk/lib-dynamodb');
5
- var agent = require('@mastra/core/agent');
5
+ var error = require('@mastra/core/error');
6
6
  var storage = require('@mastra/core/storage');
7
7
  var electrodb = require('electrodb');
8
+ var agent = require('@mastra/core/agent');
8
9
 
9
10
  // src/storage/index.ts
10
11
 
@@ -295,9 +296,9 @@ var messageEntity = new electrodb.Entity({
295
296
  }
296
297
  }
297
298
  });
298
- var threadEntity = new electrodb.Entity({
299
+ var resourceEntity = new electrodb.Entity({
299
300
  model: {
300
- entity: "thread",
301
+ entity: "resource",
301
302
  version: "1",
302
303
  service: "mastra"
303
304
  },
@@ -311,25 +312,21 @@ var threadEntity = new electrodb.Entity({
311
312
  type: "string",
312
313
  required: true
313
314
  },
314
- resourceId: {
315
- type: "string",
316
- required: true
317
- },
318
- title: {
315
+ workingMemory: {
319
316
  type: "string",
320
- required: true
317
+ required: false
321
318
  },
322
319
  metadata: {
323
320
  type: "string",
324
321
  required: false,
325
- // Stringify metadata object on set if it's not already a string
322
+ // Stringify content object on set if it's not already a string
326
323
  set: (value) => {
327
324
  if (value && typeof value !== "string") {
328
325
  return JSON.stringify(value);
329
326
  }
330
327
  return value;
331
328
  },
332
- // Parse JSON string to object on get
329
+ // Parse JSON string to object on get ONLY if it looks like JSON
333
330
  get: (value) => {
334
331
  if (value && typeof value === "string") {
335
332
  try {
@@ -347,18 +344,13 @@ var threadEntity = new electrodb.Entity({
347
344
  indexes: {
348
345
  primary: {
349
346
  pk: { field: "pk", composite: ["entity", "id"] },
350
- sk: { field: "sk", composite: ["id"] }
351
- },
352
- byResource: {
353
- index: "gsi1",
354
- pk: { field: "gsi1pk", composite: ["entity", "resourceId"] },
355
- sk: { field: "gsi1sk", composite: ["createdAt"] }
347
+ sk: { field: "sk", composite: ["entity"] }
356
348
  }
357
349
  }
358
350
  });
359
- var traceEntity = new electrodb.Entity({
351
+ var scoreEntity = new electrodb.Entity({
360
352
  model: {
361
- entity: "trace",
353
+ entity: "score",
362
354
  version: "1",
363
355
  service: "mastra"
364
356
  },
@@ -372,123 +364,275 @@ var traceEntity = new electrodb.Entity({
372
364
  type: "string",
373
365
  required: true
374
366
  },
375
- parentSpanId: {
367
+ scorerId: {
368
+ type: "string",
369
+ required: true
370
+ },
371
+ traceId: {
376
372
  type: "string",
377
373
  required: false
378
374
  },
379
- name: {
375
+ runId: {
380
376
  type: "string",
381
377
  required: true
382
378
  },
383
- traceId: {
379
+ scorer: {
384
380
  type: "string",
385
- required: true
381
+ required: true,
382
+ set: (value) => {
383
+ if (value && typeof value !== "string") {
384
+ return JSON.stringify(value);
385
+ }
386
+ return value;
387
+ },
388
+ get: (value) => {
389
+ if (value && typeof value === "string") {
390
+ try {
391
+ if (value.startsWith("{") || value.startsWith("[")) {
392
+ return JSON.parse(value);
393
+ }
394
+ } catch {
395
+ return value;
396
+ }
397
+ }
398
+ return value;
399
+ }
386
400
  },
387
- scope: {
401
+ extractStepResult: {
388
402
  type: "string",
389
- required: true
403
+ required: false,
404
+ set: (value) => {
405
+ if (value && typeof value !== "string") {
406
+ return JSON.stringify(value);
407
+ }
408
+ return value;
409
+ },
410
+ get: (value) => {
411
+ if (value && typeof value === "string") {
412
+ try {
413
+ if (value.startsWith("{") || value.startsWith("[")) {
414
+ return JSON.parse(value);
415
+ }
416
+ } catch {
417
+ return value;
418
+ }
419
+ }
420
+ return value;
421
+ }
390
422
  },
391
- kind: {
423
+ analyzeStepResult: {
424
+ type: "string",
425
+ required: false,
426
+ set: (value) => {
427
+ if (value && typeof value !== "string") {
428
+ return JSON.stringify(value);
429
+ }
430
+ return value;
431
+ },
432
+ get: (value) => {
433
+ if (value && typeof value === "string") {
434
+ try {
435
+ if (value.startsWith("{") || value.startsWith("[")) {
436
+ return JSON.parse(value);
437
+ }
438
+ } catch {
439
+ return value;
440
+ }
441
+ }
442
+ return value;
443
+ }
444
+ },
445
+ score: {
392
446
  type: "number",
393
447
  required: true
394
448
  },
395
- attributes: {
449
+ reason: {
396
450
  type: "string",
397
- // JSON stringified
398
- required: false,
399
- // Stringify object on set
451
+ required: false
452
+ },
453
+ extractPrompt: {
454
+ type: "string",
455
+ required: false
456
+ },
457
+ analyzePrompt: {
458
+ type: "string",
459
+ required: false
460
+ },
461
+ reasonPrompt: {
462
+ type: "string",
463
+ required: false
464
+ },
465
+ input: {
466
+ type: "string",
467
+ required: true,
400
468
  set: (value) => {
401
469
  if (value && typeof value !== "string") {
402
470
  return JSON.stringify(value);
403
471
  }
404
472
  return value;
405
473
  },
406
- // Parse JSON string to object on get
407
474
  get: (value) => {
408
- return value ? JSON.parse(value) : value;
475
+ if (value && typeof value === "string") {
476
+ try {
477
+ if (value.startsWith("{") || value.startsWith("[")) {
478
+ return JSON.parse(value);
479
+ }
480
+ } catch {
481
+ return value;
482
+ }
483
+ }
484
+ return value;
409
485
  }
410
486
  },
411
- status: {
487
+ output: {
488
+ type: "string",
489
+ required: true,
490
+ set: (value) => {
491
+ if (value && typeof value !== "string") {
492
+ return JSON.stringify(value);
493
+ }
494
+ return value;
495
+ },
496
+ get: (value) => {
497
+ if (value && typeof value === "string") {
498
+ try {
499
+ if (value.startsWith("{") || value.startsWith("[")) {
500
+ return JSON.parse(value);
501
+ }
502
+ } catch {
503
+ return value;
504
+ }
505
+ }
506
+ return value;
507
+ }
508
+ },
509
+ additionalContext: {
412
510
  type: "string",
413
- // JSON stringified
414
511
  required: false,
415
- // Stringify object on set
416
512
  set: (value) => {
417
513
  if (value && typeof value !== "string") {
418
514
  return JSON.stringify(value);
419
515
  }
420
516
  return value;
421
517
  },
422
- // Parse JSON string to object on get
423
518
  get: (value) => {
519
+ if (value && typeof value === "string") {
520
+ try {
521
+ if (value.startsWith("{") || value.startsWith("[")) {
522
+ return JSON.parse(value);
523
+ }
524
+ } catch {
525
+ return value;
526
+ }
527
+ }
424
528
  return value;
425
529
  }
426
530
  },
427
- events: {
531
+ runtimeContext: {
428
532
  type: "string",
429
- // JSON stringified
430
533
  required: false,
431
- // Stringify object on set
432
534
  set: (value) => {
433
535
  if (value && typeof value !== "string") {
434
536
  return JSON.stringify(value);
435
537
  }
436
538
  return value;
437
539
  },
438
- // Parse JSON string to object on get
439
540
  get: (value) => {
541
+ if (value && typeof value === "string") {
542
+ try {
543
+ if (value.startsWith("{") || value.startsWith("[")) {
544
+ return JSON.parse(value);
545
+ }
546
+ } catch {
547
+ return value;
548
+ }
549
+ }
440
550
  return value;
441
551
  }
442
552
  },
443
- links: {
553
+ entityType: {
554
+ type: "string",
555
+ required: false
556
+ },
557
+ entityData: {
444
558
  type: "string",
445
- // JSON stringified
446
559
  required: false,
447
- // Stringify object on set
448
560
  set: (value) => {
449
561
  if (value && typeof value !== "string") {
450
562
  return JSON.stringify(value);
451
563
  }
452
564
  return value;
453
565
  },
454
- // Parse JSON string to object on get
455
566
  get: (value) => {
567
+ if (value && typeof value === "string") {
568
+ try {
569
+ if (value.startsWith("{") || value.startsWith("[")) {
570
+ return JSON.parse(value);
571
+ }
572
+ } catch {
573
+ return value;
574
+ }
575
+ }
456
576
  return value;
457
577
  }
458
578
  },
459
- other: {
579
+ entityId: {
460
580
  type: "string",
461
581
  required: false
462
582
  },
463
- startTime: {
464
- type: "number",
583
+ source: {
584
+ type: "string",
465
585
  required: true
466
586
  },
467
- endTime: {
468
- type: "number",
469
- required: true
587
+ resourceId: {
588
+ type: "string",
589
+ required: false
590
+ },
591
+ threadId: {
592
+ type: "string",
593
+ required: false
470
594
  }
471
595
  },
472
596
  indexes: {
473
597
  primary: {
474
598
  pk: { field: "pk", composite: ["entity", "id"] },
475
- sk: { field: "sk", composite: [] }
599
+ sk: { field: "sk", composite: ["entity"] }
476
600
  },
477
- byName: {
601
+ byScorer: {
478
602
  index: "gsi1",
479
- pk: { field: "gsi1pk", composite: ["entity", "name"] },
480
- sk: { field: "gsi1sk", composite: ["startTime"] }
603
+ pk: { field: "gsi1pk", composite: ["entity", "scorerId"] },
604
+ sk: { field: "gsi1sk", composite: ["createdAt"] }
481
605
  },
482
- byScope: {
606
+ byRun: {
483
607
  index: "gsi2",
484
- pk: { field: "gsi2pk", composite: ["entity", "scope"] },
485
- sk: { field: "gsi2sk", composite: ["startTime"] }
608
+ pk: { field: "gsi2pk", composite: ["entity", "runId"] },
609
+ sk: { field: "gsi2sk", composite: ["createdAt"] }
610
+ },
611
+ byTrace: {
612
+ index: "gsi3",
613
+ pk: { field: "gsi3pk", composite: ["entity", "traceId"] },
614
+ sk: { field: "gsi3sk", composite: ["createdAt"] }
615
+ },
616
+ byEntityData: {
617
+ index: "gsi4",
618
+ pk: { field: "gsi4pk", composite: ["entity", "entityId"] },
619
+ sk: { field: "gsi4sk", composite: ["createdAt"] }
620
+ },
621
+ byResource: {
622
+ index: "gsi5",
623
+ pk: { field: "gsi5pk", composite: ["entity", "resourceId"] },
624
+ sk: { field: "gsi5sk", composite: ["createdAt"] }
625
+ },
626
+ byThread: {
627
+ index: "gsi6",
628
+ pk: { field: "gsi6pk", composite: ["entity", "threadId"] },
629
+ sk: { field: "gsi6sk", composite: ["createdAt"] }
486
630
  }
487
631
  }
488
632
  });
489
- var workflowSnapshotEntity = new electrodb.Entity({
633
+ var threadEntity = new electrodb.Entity({
490
634
  model: {
491
- entity: "workflow_snapshot",
635
+ entity: "thread",
492
636
  version: "1",
493
637
  service: "mastra"
494
638
  },
@@ -498,19 +642,22 @@ var workflowSnapshotEntity = new electrodb.Entity({
498
642
  required: true
499
643
  },
500
644
  ...baseAttributes,
501
- workflow_name: {
645
+ id: {
502
646
  type: "string",
503
647
  required: true
504
648
  },
505
- run_id: {
649
+ resourceId: {
506
650
  type: "string",
507
651
  required: true
508
652
  },
509
- snapshot: {
653
+ title: {
510
654
  type: "string",
511
- // JSON stringified
512
- required: true,
513
- // Stringify snapshot object on set
655
+ required: true
656
+ },
657
+ metadata: {
658
+ type: "string",
659
+ required: false,
660
+ // Stringify metadata object on set if it's not already a string
514
661
  set: (value) => {
515
662
  if (value && typeof value !== "string") {
516
663
  return JSON.stringify(value);
@@ -519,94 +666,1145 @@ var workflowSnapshotEntity = new electrodb.Entity({
519
666
  },
520
667
  // Parse JSON string to object on get
521
668
  get: (value) => {
522
- return value ? JSON.parse(value) : value;
669
+ if (value && typeof value === "string") {
670
+ try {
671
+ if (value.startsWith("{") || value.startsWith("[")) {
672
+ return JSON.parse(value);
673
+ }
674
+ } catch {
675
+ return value;
676
+ }
677
+ }
678
+ return value;
523
679
  }
524
- },
525
- resourceId: {
526
- type: "string",
527
- required: false
528
680
  }
529
681
  },
530
682
  indexes: {
531
683
  primary: {
532
- pk: { field: "pk", composite: ["entity", "workflow_name"] },
533
- sk: { field: "sk", composite: ["run_id"] }
684
+ pk: { field: "pk", composite: ["entity", "id"] },
685
+ sk: { field: "sk", composite: ["id"] }
534
686
  },
535
- // GSI to allow querying by run_id efficiently without knowing the workflow_name
687
+ byResource: {
688
+ index: "gsi1",
689
+ pk: { field: "gsi1pk", composite: ["entity", "resourceId"] },
690
+ sk: { field: "gsi1sk", composite: ["createdAt"] }
691
+ }
692
+ }
693
+ });
694
+ var traceEntity = new electrodb.Entity({
695
+ model: {
696
+ entity: "trace",
697
+ version: "1",
698
+ service: "mastra"
699
+ },
700
+ attributes: {
701
+ entity: {
702
+ type: "string",
703
+ required: true
704
+ },
705
+ ...baseAttributes,
706
+ id: {
707
+ type: "string",
708
+ required: true
709
+ },
710
+ parentSpanId: {
711
+ type: "string",
712
+ required: false
713
+ },
714
+ name: {
715
+ type: "string",
716
+ required: true
717
+ },
718
+ traceId: {
719
+ type: "string",
720
+ required: true
721
+ },
722
+ scope: {
723
+ type: "string",
724
+ required: true
725
+ },
726
+ kind: {
727
+ type: "number",
728
+ required: true
729
+ },
730
+ attributes: {
731
+ type: "string",
732
+ // JSON stringified
733
+ required: false,
734
+ // Stringify object on set
735
+ set: (value) => {
736
+ if (value && typeof value !== "string") {
737
+ return JSON.stringify(value);
738
+ }
739
+ return value;
740
+ },
741
+ // Parse JSON string to object on get
742
+ get: (value) => {
743
+ return value ? JSON.parse(value) : value;
744
+ }
745
+ },
746
+ status: {
747
+ type: "string",
748
+ // JSON stringified
749
+ required: false,
750
+ // Stringify object on set
751
+ set: (value) => {
752
+ if (value && typeof value !== "string") {
753
+ return JSON.stringify(value);
754
+ }
755
+ return value;
756
+ },
757
+ // Parse JSON string to object on get
758
+ get: (value) => {
759
+ return value;
760
+ }
761
+ },
762
+ events: {
763
+ type: "string",
764
+ // JSON stringified
765
+ required: false,
766
+ // Stringify object on set
767
+ set: (value) => {
768
+ if (value && typeof value !== "string") {
769
+ return JSON.stringify(value);
770
+ }
771
+ return value;
772
+ },
773
+ // Parse JSON string to object on get
774
+ get: (value) => {
775
+ return value;
776
+ }
777
+ },
778
+ links: {
779
+ type: "string",
780
+ // JSON stringified
781
+ required: false,
782
+ // Stringify object on set
783
+ set: (value) => {
784
+ if (value && typeof value !== "string") {
785
+ return JSON.stringify(value);
786
+ }
787
+ return value;
788
+ },
789
+ // Parse JSON string to object on get
790
+ get: (value) => {
791
+ return value;
792
+ }
793
+ },
794
+ other: {
795
+ type: "string",
796
+ required: false
797
+ },
798
+ startTime: {
799
+ type: "number",
800
+ required: true
801
+ },
802
+ endTime: {
803
+ type: "number",
804
+ required: true
805
+ }
806
+ },
807
+ indexes: {
808
+ primary: {
809
+ pk: { field: "pk", composite: ["entity", "id"] },
810
+ sk: { field: "sk", composite: [] }
811
+ },
812
+ byName: {
813
+ index: "gsi1",
814
+ pk: { field: "gsi1pk", composite: ["entity", "name"] },
815
+ sk: { field: "gsi1sk", composite: ["startTime"] }
816
+ },
817
+ byScope: {
818
+ index: "gsi2",
819
+ pk: { field: "gsi2pk", composite: ["entity", "scope"] },
820
+ sk: { field: "gsi2sk", composite: ["startTime"] }
821
+ }
822
+ }
823
+ });
824
+ var workflowSnapshotEntity = new electrodb.Entity({
825
+ model: {
826
+ entity: "workflow_snapshot",
827
+ version: "1",
828
+ service: "mastra"
829
+ },
830
+ attributes: {
831
+ entity: {
832
+ type: "string",
833
+ required: true
834
+ },
835
+ ...baseAttributes,
836
+ workflow_name: {
837
+ type: "string",
838
+ required: true
839
+ },
840
+ run_id: {
841
+ type: "string",
842
+ required: true
843
+ },
844
+ snapshot: {
845
+ type: "string",
846
+ // JSON stringified
847
+ required: true,
848
+ // Stringify snapshot object on set
849
+ set: (value) => {
850
+ if (value && typeof value !== "string") {
851
+ return JSON.stringify(value);
852
+ }
853
+ return value;
854
+ },
855
+ // Parse JSON string to object on get
856
+ get: (value) => {
857
+ return value ? JSON.parse(value) : value;
858
+ }
859
+ },
860
+ resourceId: {
861
+ type: "string",
862
+ required: false
863
+ }
864
+ },
865
+ indexes: {
866
+ primary: {
867
+ pk: { field: "pk", composite: ["entity", "workflow_name"] },
868
+ sk: { field: "sk", composite: ["run_id"] }
869
+ },
870
+ // GSI to allow querying by run_id efficiently without knowing the workflow_name
536
871
  gsi2: {
537
872
  index: "gsi2",
538
873
  pk: { field: "gsi2pk", composite: ["entity", "run_id"] },
539
874
  sk: { field: "gsi2sk", composite: ["workflow_name"] }
540
875
  }
541
876
  }
542
- });
543
-
544
- // src/entities/index.ts
545
- function getElectroDbService(client, tableName) {
546
- return new electrodb.Service(
547
- {
548
- thread: threadEntity,
549
- message: messageEntity,
550
- eval: evalEntity,
551
- trace: traceEntity,
552
- workflowSnapshot: workflowSnapshotEntity
553
- },
554
- {
555
- client,
556
- table: tableName
877
+ });
878
+
879
+ // src/entities/index.ts
880
+ function getElectroDbService(client, tableName) {
881
+ return new electrodb.Service(
882
+ {
883
+ thread: threadEntity,
884
+ message: messageEntity,
885
+ eval: evalEntity,
886
+ trace: traceEntity,
887
+ workflow_snapshot: workflowSnapshotEntity,
888
+ resource: resourceEntity,
889
+ score: scoreEntity
890
+ },
891
+ {
892
+ client,
893
+ table: tableName
894
+ }
895
+ );
896
+ }
897
+ var LegacyEvalsDynamoDB = class extends storage.LegacyEvalsStorage {
898
+ service;
899
+ tableName;
900
+ constructor({ service, tableName }) {
901
+ super();
902
+ this.service = service;
903
+ this.tableName = tableName;
904
+ }
905
+ // Eval operations
906
+ async getEvalsByAgentName(agentName, type) {
907
+ this.logger.debug("Getting evals for agent", { agentName, type });
908
+ try {
909
+ const query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
910
+ const results = await query.go({ order: "desc", limit: 100 });
911
+ if (!results.data.length) {
912
+ return [];
913
+ }
914
+ let filteredData = results.data;
915
+ if (type) {
916
+ filteredData = filteredData.filter((evalRecord) => {
917
+ try {
918
+ const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
919
+ if (type === "test" && !testInfo) {
920
+ return false;
921
+ }
922
+ if (type === "live" && testInfo) {
923
+ return false;
924
+ }
925
+ } catch (e) {
926
+ this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
927
+ }
928
+ return true;
929
+ });
930
+ }
931
+ return filteredData.map((evalRecord) => {
932
+ try {
933
+ return {
934
+ input: evalRecord.input,
935
+ output: evalRecord.output,
936
+ // Safely parse result and test_info
937
+ result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
938
+ agentName: evalRecord.agent_name,
939
+ createdAt: evalRecord.created_at,
940
+ // Keep as string from DDB?
941
+ metricName: evalRecord.metric_name,
942
+ instructions: evalRecord.instructions,
943
+ runId: evalRecord.run_id,
944
+ globalRunId: evalRecord.global_run_id,
945
+ testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
946
+ };
947
+ } catch (parseError) {
948
+ this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
949
+ return {
950
+ agentName: evalRecord.agent_name,
951
+ createdAt: evalRecord.created_at,
952
+ runId: evalRecord.run_id,
953
+ globalRunId: evalRecord.global_run_id
954
+ };
955
+ }
956
+ });
957
+ } catch (error$1) {
958
+ throw new error.MastraError(
959
+ {
960
+ id: "STORAGE_DYNAMODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
961
+ domain: error.ErrorDomain.STORAGE,
962
+ category: error.ErrorCategory.THIRD_PARTY,
963
+ details: { agentName }
964
+ },
965
+ error$1
966
+ );
967
+ }
968
+ }
969
+ async getEvals(options = {}) {
970
+ const { agentName, type, page = 0, perPage = 100, dateRange } = options;
971
+ this.logger.debug("Getting evals with pagination", { agentName, type, page, perPage, dateRange });
972
+ try {
973
+ let query;
974
+ if (agentName) {
975
+ query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
976
+ } else {
977
+ query = this.service.entities.eval.query.byEntity({ entity: "eval" });
978
+ }
979
+ const results = await query.go({
980
+ order: "desc",
981
+ pages: "all"
982
+ // Get all pages to apply filtering and pagination
983
+ });
984
+ if (!results.data.length) {
985
+ return {
986
+ evals: [],
987
+ total: 0,
988
+ page,
989
+ perPage,
990
+ hasMore: false
991
+ };
992
+ }
993
+ let filteredData = results.data;
994
+ if (type) {
995
+ filteredData = filteredData.filter((evalRecord) => {
996
+ try {
997
+ const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
998
+ if (type === "test" && !testInfo) {
999
+ return false;
1000
+ }
1001
+ if (type === "live" && testInfo) {
1002
+ return false;
1003
+ }
1004
+ } catch (e) {
1005
+ this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
1006
+ }
1007
+ return true;
1008
+ });
1009
+ }
1010
+ if (dateRange) {
1011
+ const fromDate = dateRange.start;
1012
+ const toDate = dateRange.end;
1013
+ filteredData = filteredData.filter((evalRecord) => {
1014
+ const recordDate = new Date(evalRecord.created_at);
1015
+ if (fromDate && recordDate < fromDate) {
1016
+ return false;
1017
+ }
1018
+ if (toDate && recordDate > toDate) {
1019
+ return false;
1020
+ }
1021
+ return true;
1022
+ });
1023
+ }
1024
+ const total = filteredData.length;
1025
+ const start = page * perPage;
1026
+ const end = start + perPage;
1027
+ const paginatedData = filteredData.slice(start, end);
1028
+ const evals = paginatedData.map((evalRecord) => {
1029
+ try {
1030
+ return {
1031
+ input: evalRecord.input,
1032
+ output: evalRecord.output,
1033
+ result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
1034
+ agentName: evalRecord.agent_name,
1035
+ createdAt: evalRecord.created_at,
1036
+ metricName: evalRecord.metric_name,
1037
+ instructions: evalRecord.instructions,
1038
+ runId: evalRecord.run_id,
1039
+ globalRunId: evalRecord.global_run_id,
1040
+ testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
1041
+ };
1042
+ } catch (parseError) {
1043
+ this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
1044
+ return {
1045
+ agentName: evalRecord.agent_name,
1046
+ createdAt: evalRecord.created_at,
1047
+ runId: evalRecord.run_id,
1048
+ globalRunId: evalRecord.global_run_id
1049
+ };
1050
+ }
1051
+ });
1052
+ const hasMore = end < total;
1053
+ return {
1054
+ evals,
1055
+ total,
1056
+ page,
1057
+ perPage,
1058
+ hasMore
1059
+ };
1060
+ } catch (error$1) {
1061
+ throw new error.MastraError(
1062
+ {
1063
+ id: "STORAGE_DYNAMODB_STORE_GET_EVALS_FAILED",
1064
+ domain: error.ErrorDomain.STORAGE,
1065
+ category: error.ErrorCategory.THIRD_PARTY,
1066
+ details: {
1067
+ agentName: agentName || "all",
1068
+ type: type || "all",
1069
+ page,
1070
+ perPage
1071
+ }
1072
+ },
1073
+ error$1
1074
+ );
1075
+ }
1076
+ }
1077
+ };
1078
+ var MemoryStorageDynamoDB = class extends storage.MemoryStorage {
1079
+ service;
1080
+ constructor({ service }) {
1081
+ super();
1082
+ this.service = service;
1083
+ }
1084
+ // Helper function to parse message data (handle JSON fields)
1085
+ parseMessageData(data) {
1086
+ return {
1087
+ ...data,
1088
+ // Ensure dates are Date objects if needed (ElectroDB might return strings)
1089
+ createdAt: data.createdAt ? new Date(data.createdAt) : void 0,
1090
+ updatedAt: data.updatedAt ? new Date(data.updatedAt) : void 0
1091
+ // Other fields like content, toolCallArgs etc. are assumed to be correctly
1092
+ // transformed by the ElectroDB entity getters.
1093
+ };
1094
+ }
1095
+ async getThreadById({ threadId }) {
1096
+ this.logger.debug("Getting thread by ID", { threadId });
1097
+ try {
1098
+ const result = await this.service.entities.thread.get({ entity: "thread", id: threadId }).go();
1099
+ if (!result.data) {
1100
+ return null;
1101
+ }
1102
+ const data = result.data;
1103
+ return {
1104
+ ...data,
1105
+ // Convert date strings back to Date objects for consistency
1106
+ createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
1107
+ updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
1108
+ // metadata: data.metadata ? JSON.parse(data.metadata) : undefined, // REMOVED by AI
1109
+ // metadata is already transformed by the entity's getter
1110
+ };
1111
+ } catch (error$1) {
1112
+ throw new error.MastraError(
1113
+ {
1114
+ id: "STORAGE_DYNAMODB_STORE_GET_THREAD_BY_ID_FAILED",
1115
+ domain: error.ErrorDomain.STORAGE,
1116
+ category: error.ErrorCategory.THIRD_PARTY,
1117
+ details: { threadId }
1118
+ },
1119
+ error$1
1120
+ );
1121
+ }
1122
+ }
1123
+ async getThreadsByResourceId({ resourceId }) {
1124
+ this.logger.debug("Getting threads by resource ID", { resourceId });
1125
+ try {
1126
+ const result = await this.service.entities.thread.query.byResource({ entity: "thread", resourceId }).go();
1127
+ if (!result.data.length) {
1128
+ return [];
1129
+ }
1130
+ return result.data.map((data) => ({
1131
+ ...data,
1132
+ // Convert date strings back to Date objects for consistency
1133
+ createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
1134
+ updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
1135
+ // metadata: data.metadata ? JSON.parse(data.metadata) : undefined, // REMOVED by AI
1136
+ // metadata is already transformed by the entity's getter
1137
+ }));
1138
+ } catch (error$1) {
1139
+ throw new error.MastraError(
1140
+ {
1141
+ id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
1142
+ domain: error.ErrorDomain.STORAGE,
1143
+ category: error.ErrorCategory.THIRD_PARTY,
1144
+ details: { resourceId }
1145
+ },
1146
+ error$1
1147
+ );
1148
+ }
1149
+ }
1150
+ async saveThread({ thread }) {
1151
+ this.logger.debug("Saving thread", { threadId: thread.id });
1152
+ const now = /* @__PURE__ */ new Date();
1153
+ const threadData = {
1154
+ entity: "thread",
1155
+ id: thread.id,
1156
+ resourceId: thread.resourceId,
1157
+ title: thread.title || `Thread ${thread.id}`,
1158
+ createdAt: thread.createdAt?.toISOString() || now.toISOString(),
1159
+ updatedAt: now.toISOString(),
1160
+ metadata: thread.metadata ? JSON.stringify(thread.metadata) : void 0
1161
+ };
1162
+ try {
1163
+ await this.service.entities.thread.upsert(threadData).go();
1164
+ return {
1165
+ id: thread.id,
1166
+ resourceId: thread.resourceId,
1167
+ title: threadData.title,
1168
+ createdAt: thread.createdAt || now,
1169
+ updatedAt: now,
1170
+ metadata: thread.metadata
1171
+ };
1172
+ } catch (error$1) {
1173
+ throw new error.MastraError(
1174
+ {
1175
+ id: "STORAGE_DYNAMODB_STORE_SAVE_THREAD_FAILED",
1176
+ domain: error.ErrorDomain.STORAGE,
1177
+ category: error.ErrorCategory.THIRD_PARTY,
1178
+ details: { threadId: thread.id }
1179
+ },
1180
+ error$1
1181
+ );
1182
+ }
1183
+ }
1184
+ async updateThread({
1185
+ id,
1186
+ title,
1187
+ metadata
1188
+ }) {
1189
+ this.logger.debug("Updating thread", { threadId: id });
1190
+ try {
1191
+ const existingThread = await this.getThreadById({ threadId: id });
1192
+ if (!existingThread) {
1193
+ throw new Error(`Thread not found: ${id}`);
1194
+ }
1195
+ const now = /* @__PURE__ */ new Date();
1196
+ const updateData = {
1197
+ updatedAt: now.toISOString()
1198
+ };
1199
+ if (title) {
1200
+ updateData.title = title;
1201
+ }
1202
+ if (metadata) {
1203
+ const existingMetadata = existingThread.metadata ? typeof existingThread.metadata === "string" ? JSON.parse(existingThread.metadata) : existingThread.metadata : {};
1204
+ const mergedMetadata = { ...existingMetadata, ...metadata };
1205
+ updateData.metadata = JSON.stringify(mergedMetadata);
1206
+ }
1207
+ await this.service.entities.thread.update({ entity: "thread", id }).set(updateData).go();
1208
+ return {
1209
+ ...existingThread,
1210
+ title: title || existingThread.title,
1211
+ metadata: metadata ? { ...existingThread.metadata, ...metadata } : existingThread.metadata,
1212
+ updatedAt: now
1213
+ };
1214
+ } catch (error$1) {
1215
+ throw new error.MastraError(
1216
+ {
1217
+ id: "STORAGE_DYNAMODB_STORE_UPDATE_THREAD_FAILED",
1218
+ domain: error.ErrorDomain.STORAGE,
1219
+ category: error.ErrorCategory.THIRD_PARTY,
1220
+ details: { threadId: id }
1221
+ },
1222
+ error$1
1223
+ );
1224
+ }
1225
+ }
1226
+ async deleteThread({ threadId }) {
1227
+ this.logger.debug("Deleting thread", { threadId });
1228
+ try {
1229
+ const messages = await this.getMessages({ threadId });
1230
+ if (messages.length > 0) {
1231
+ const batchSize = 25;
1232
+ for (let i = 0; i < messages.length; i += batchSize) {
1233
+ const batch = messages.slice(i, i + batchSize);
1234
+ await Promise.all(
1235
+ batch.map(
1236
+ (message) => this.service.entities.message.delete({
1237
+ entity: "message",
1238
+ id: message.id,
1239
+ threadId: message.threadId
1240
+ }).go()
1241
+ )
1242
+ );
1243
+ }
1244
+ }
1245
+ await this.service.entities.thread.delete({ entity: "thread", id: threadId }).go();
1246
+ } catch (error$1) {
1247
+ throw new error.MastraError(
1248
+ {
1249
+ id: "STORAGE_DYNAMODB_STORE_DELETE_THREAD_FAILED",
1250
+ domain: error.ErrorDomain.STORAGE,
1251
+ category: error.ErrorCategory.THIRD_PARTY,
1252
+ details: { threadId }
1253
+ },
1254
+ error$1
1255
+ );
1256
+ }
1257
+ }
1258
+ async getMessages({
1259
+ threadId,
1260
+ resourceId,
1261
+ selectBy,
1262
+ format
1263
+ }) {
1264
+ this.logger.debug("Getting messages", { threadId, selectBy });
1265
+ try {
1266
+ const messages = [];
1267
+ const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1268
+ if (selectBy?.include?.length) {
1269
+ const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1270
+ if (includeMessages) {
1271
+ messages.push(...includeMessages);
1272
+ }
1273
+ }
1274
+ if (limit !== 0) {
1275
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1276
+ let results;
1277
+ if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1278
+ results = await query.go({ limit, order: "desc" });
1279
+ results.data = results.data.reverse();
1280
+ } else {
1281
+ results = await query.go();
1282
+ }
1283
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1284
+ allThreadMessages.sort((a, b) => {
1285
+ const timeA = a.createdAt.getTime();
1286
+ const timeB = b.createdAt.getTime();
1287
+ if (timeA === timeB) {
1288
+ return a.id.localeCompare(b.id);
1289
+ }
1290
+ return timeA - timeB;
1291
+ });
1292
+ messages.push(...allThreadMessages);
1293
+ }
1294
+ messages.sort((a, b) => {
1295
+ const timeA = a.createdAt.getTime();
1296
+ const timeB = b.createdAt.getTime();
1297
+ if (timeA === timeB) {
1298
+ return a.id.localeCompare(b.id);
1299
+ }
1300
+ return timeA - timeB;
1301
+ });
1302
+ const uniqueMessages = messages.filter(
1303
+ (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1304
+ );
1305
+ const list = new agent.MessageList({ threadId, resourceId }).add(uniqueMessages, "memory");
1306
+ if (format === `v2`) return list.get.all.v2();
1307
+ return list.get.all.v1();
1308
+ } catch (error$1) {
1309
+ throw new error.MastraError(
1310
+ {
1311
+ id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_FAILED",
1312
+ domain: error.ErrorDomain.STORAGE,
1313
+ category: error.ErrorCategory.THIRD_PARTY,
1314
+ details: { threadId }
1315
+ },
1316
+ error$1
1317
+ );
1318
+ }
1319
+ }
1320
+ async saveMessages(args) {
1321
+ const { messages, format = "v1" } = args;
1322
+ this.logger.debug("Saving messages", { count: messages.length });
1323
+ if (!messages.length) {
1324
+ return [];
557
1325
  }
558
- );
559
- }
560
-
561
- // src/storage/index.ts
562
- var DynamoDBStore = class extends storage.MastraStorage {
563
- tableName;
564
- client;
565
- service;
566
- hasInitialized = null;
567
- constructor({ name, config }) {
568
- super({ name });
569
- if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
570
- throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
1326
+ const threadId = messages[0]?.threadId;
1327
+ if (!threadId) {
1328
+ throw new Error("Thread ID is required");
1329
+ }
1330
+ const messagesToSave = messages.map((msg) => {
1331
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1332
+ return {
1333
+ entity: "message",
1334
+ // Add entity type
1335
+ id: msg.id,
1336
+ threadId: msg.threadId,
1337
+ role: msg.role,
1338
+ type: msg.type,
1339
+ resourceId: msg.resourceId,
1340
+ // Ensure complex fields are stringified if not handled by attribute setters
1341
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
1342
+ toolCallArgs: `toolCallArgs` in msg && msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
1343
+ toolCallIds: `toolCallIds` in msg && msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
1344
+ toolNames: `toolNames` in msg && msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
1345
+ createdAt: msg.createdAt instanceof Date ? msg.createdAt.toISOString() : msg.createdAt || now,
1346
+ updatedAt: now
1347
+ // Add updatedAt
1348
+ };
1349
+ });
1350
+ try {
1351
+ const savedMessageIds = [];
1352
+ for (const messageData of messagesToSave) {
1353
+ if (!messageData.entity) {
1354
+ this.logger.error("Missing entity property in message data for create", { messageData });
1355
+ throw new Error("Internal error: Missing entity property during saveMessages");
1356
+ }
1357
+ try {
1358
+ await this.service.entities.message.put(messageData).go();
1359
+ savedMessageIds.push(messageData.id);
1360
+ } catch (error) {
1361
+ for (const savedId of savedMessageIds) {
1362
+ try {
1363
+ await this.service.entities.message.delete({ entity: "message", id: savedId }).go();
1364
+ } catch (rollbackError) {
1365
+ this.logger.error("Failed to rollback message during save error", {
1366
+ messageId: savedId,
1367
+ error: rollbackError
1368
+ });
1369
+ }
1370
+ }
1371
+ throw error;
1372
+ }
1373
+ }
1374
+ await this.service.entities.thread.update({ entity: "thread", id: threadId }).set({
1375
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1376
+ }).go();
1377
+ const list = new agent.MessageList().add(messages, "memory");
1378
+ if (format === `v1`) return list.get.all.v1();
1379
+ return list.get.all.v2();
1380
+ } catch (error$1) {
1381
+ throw new error.MastraError(
1382
+ {
1383
+ id: "STORAGE_DYNAMODB_STORE_SAVE_MESSAGES_FAILED",
1384
+ domain: error.ErrorDomain.STORAGE,
1385
+ category: error.ErrorCategory.THIRD_PARTY,
1386
+ details: { count: messages.length }
1387
+ },
1388
+ error$1
1389
+ );
571
1390
  }
572
- if (!/^[a-zA-Z0-9_.-]{3,255}$/.test(config.tableName)) {
573
- throw new Error(
574
- `DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`
1391
+ }
1392
+ async getThreadsByResourceIdPaginated(args) {
1393
+ const { resourceId, page = 0, perPage = 100 } = args;
1394
+ this.logger.debug("Getting threads by resource ID with pagination", { resourceId, page, perPage });
1395
+ try {
1396
+ const query = this.service.entities.thread.query.byResource({ entity: "thread", resourceId });
1397
+ const results = await query.go();
1398
+ const allThreads = results.data;
1399
+ const startIndex = page * perPage;
1400
+ const endIndex = startIndex + perPage;
1401
+ const paginatedThreads = allThreads.slice(startIndex, endIndex);
1402
+ const total = allThreads.length;
1403
+ const hasMore = endIndex < total;
1404
+ return {
1405
+ threads: paginatedThreads,
1406
+ total,
1407
+ page,
1408
+ perPage,
1409
+ hasMore
1410
+ };
1411
+ } catch (error$1) {
1412
+ throw new error.MastraError(
1413
+ {
1414
+ id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1415
+ domain: error.ErrorDomain.STORAGE,
1416
+ category: error.ErrorCategory.THIRD_PARTY,
1417
+ details: { resourceId, page, perPage }
1418
+ },
1419
+ error$1
1420
+ );
1421
+ }
1422
+ }
1423
+ async getMessagesPaginated(args) {
1424
+ const { threadId, resourceId, selectBy, format = "v1" } = args;
1425
+ const { page = 0, perPage = 40, dateRange } = selectBy?.pagination || {};
1426
+ const fromDate = dateRange?.start;
1427
+ const toDate = dateRange?.end;
1428
+ const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1429
+ this.logger.debug("Getting messages with pagination", { threadId, page, perPage, fromDate, toDate, limit });
1430
+ try {
1431
+ let messages = [];
1432
+ if (selectBy?.include?.length) {
1433
+ const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1434
+ if (includeMessages) {
1435
+ messages.push(...includeMessages);
1436
+ }
1437
+ }
1438
+ if (limit !== 0) {
1439
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1440
+ let results;
1441
+ if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1442
+ results = await query.go({ limit, order: "desc" });
1443
+ results.data = results.data.reverse();
1444
+ } else {
1445
+ results = await query.go();
1446
+ }
1447
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1448
+ allThreadMessages.sort((a, b) => {
1449
+ const timeA = a.createdAt.getTime();
1450
+ const timeB = b.createdAt.getTime();
1451
+ if (timeA === timeB) {
1452
+ return a.id.localeCompare(b.id);
1453
+ }
1454
+ return timeA - timeB;
1455
+ });
1456
+ const excludeIds = messages.map((m) => m.id);
1457
+ if (excludeIds.length > 0) {
1458
+ allThreadMessages = allThreadMessages.filter((msg) => !excludeIds.includes(msg.id));
1459
+ }
1460
+ messages.push(...allThreadMessages);
1461
+ }
1462
+ messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
1463
+ if (fromDate || toDate) {
1464
+ messages = messages.filter((msg) => {
1465
+ const createdAt = new Date(msg.createdAt).getTime();
1466
+ if (fromDate && createdAt < new Date(fromDate).getTime()) return false;
1467
+ if (toDate && createdAt > new Date(toDate).getTime()) return false;
1468
+ return true;
1469
+ });
1470
+ }
1471
+ const total = messages.length;
1472
+ const start = page * perPage;
1473
+ const end = start + perPage;
1474
+ const paginatedMessages = messages.slice(start, end);
1475
+ const hasMore = end < total;
1476
+ const list = new agent.MessageList({ threadId, resourceId }).add(paginatedMessages, "memory");
1477
+ const finalMessages = format === "v2" ? list.get.all.v2() : list.get.all.v1();
1478
+ return {
1479
+ messages: finalMessages,
1480
+ total,
1481
+ page,
1482
+ perPage,
1483
+ hasMore
1484
+ };
1485
+ } catch (error$1) {
1486
+ throw new error.MastraError(
1487
+ {
1488
+ id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
1489
+ domain: error.ErrorDomain.STORAGE,
1490
+ category: error.ErrorCategory.THIRD_PARTY,
1491
+ details: { threadId }
1492
+ },
1493
+ error$1
575
1494
  );
576
1495
  }
577
- const dynamoClient = new clientDynamodb.DynamoDBClient({
578
- region: config.region || "us-east-1",
579
- endpoint: config.endpoint,
580
- credentials: config.credentials
1496
+ }
1497
+ // Helper method to get included messages with context
1498
+ async _getIncludedMessages(threadId, selectBy) {
1499
+ if (!selectBy?.include?.length) {
1500
+ return [];
1501
+ }
1502
+ const includeMessages = [];
1503
+ for (const includeItem of selectBy.include) {
1504
+ try {
1505
+ const { id, threadId: targetThreadId, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
1506
+ const searchThreadId = targetThreadId || threadId;
1507
+ this.logger.debug("Getting included messages for", {
1508
+ id,
1509
+ targetThreadId,
1510
+ searchThreadId,
1511
+ withPreviousMessages,
1512
+ withNextMessages
1513
+ });
1514
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId: searchThreadId });
1515
+ const results = await query.go();
1516
+ const allMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
1517
+ this.logger.debug("Found messages in thread", {
1518
+ threadId: searchThreadId,
1519
+ messageCount: allMessages.length,
1520
+ messageIds: allMessages.map((m) => m.id)
1521
+ });
1522
+ allMessages.sort((a, b) => {
1523
+ const timeA = a.createdAt.getTime();
1524
+ const timeB = b.createdAt.getTime();
1525
+ if (timeA === timeB) {
1526
+ return a.id.localeCompare(b.id);
1527
+ }
1528
+ return timeA - timeB;
1529
+ });
1530
+ const targetIndex = allMessages.findIndex((msg) => msg.id === id);
1531
+ if (targetIndex === -1) {
1532
+ this.logger.warn("Target message not found", { id, threadId: searchThreadId });
1533
+ continue;
1534
+ }
1535
+ this.logger.debug("Found target message at index", { id, targetIndex, totalMessages: allMessages.length });
1536
+ const startIndex = Math.max(0, targetIndex - withPreviousMessages);
1537
+ const endIndex = Math.min(allMessages.length, targetIndex + withNextMessages + 1);
1538
+ const contextMessages = allMessages.slice(startIndex, endIndex);
1539
+ this.logger.debug("Context messages", {
1540
+ startIndex,
1541
+ endIndex,
1542
+ contextCount: contextMessages.length,
1543
+ contextIds: contextMessages.map((m) => m.id)
1544
+ });
1545
+ includeMessages.push(...contextMessages);
1546
+ } catch (error) {
1547
+ this.logger.warn("Failed to get included message", { messageId: includeItem.id, error });
1548
+ }
1549
+ }
1550
+ this.logger.debug("Total included messages", {
1551
+ count: includeMessages.length,
1552
+ ids: includeMessages.map((m) => m.id)
581
1553
  });
582
- this.tableName = config.tableName;
583
- this.client = libDynamodb.DynamoDBDocumentClient.from(dynamoClient);
584
- this.service = getElectroDbService(this.client, this.tableName);
1554
+ return includeMessages;
585
1555
  }
586
- /**
587
- * This method is modified for DynamoDB with ElectroDB single-table design.
588
- * It assumes the table is created and managed externally via CDK/CloudFormation.
589
- *
590
- * This implementation only validates that the required table exists and is accessible.
591
- * No table creation is attempted - we simply check if we can access the table.
592
- */
593
- async createTable({ tableName }) {
594
- this.logger.debug("Validating access to externally managed table", { tableName, physicalTable: this.tableName });
1556
+ async updateMessages(args) {
1557
+ const { messages } = args;
1558
+ this.logger.debug("Updating messages", { count: messages.length });
1559
+ if (!messages.length) {
1560
+ return [];
1561
+ }
1562
+ const updatedMessages = [];
1563
+ const affectedThreadIds = /* @__PURE__ */ new Set();
595
1564
  try {
596
- const tableExists = await this.validateTableExists();
597
- if (!tableExists) {
598
- this.logger.error(
599
- `Table ${this.tableName} does not exist or is not accessible. It should be created via CDK/CloudFormation.`
600
- );
601
- throw new Error(
602
- `Table ${this.tableName} does not exist or is not accessible. Ensure it's created via CDK/CloudFormation before using this store.`
603
- );
1565
+ for (const updateData of messages) {
1566
+ const { id, ...updates } = updateData;
1567
+ const existingMessage = await this.service.entities.message.get({ entity: "message", id }).go();
1568
+ if (!existingMessage.data) {
1569
+ this.logger.warn("Message not found for update", { id });
1570
+ continue;
1571
+ }
1572
+ const existingMsg = this.parseMessageData(existingMessage.data);
1573
+ const originalThreadId = existingMsg.threadId;
1574
+ affectedThreadIds.add(originalThreadId);
1575
+ const updatePayload = {
1576
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1577
+ };
1578
+ if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
1579
+ if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
1580
+ if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
1581
+ if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
1582
+ updatePayload.threadId = updates.threadId;
1583
+ affectedThreadIds.add(updates.threadId);
1584
+ }
1585
+ if (updates.content) {
1586
+ const existingContent = existingMsg.content;
1587
+ let newContent = { ...existingContent };
1588
+ if (updates.content.metadata !== void 0) {
1589
+ newContent.metadata = {
1590
+ ...existingContent.metadata || {},
1591
+ ...updates.content.metadata || {}
1592
+ };
1593
+ }
1594
+ if (updates.content.content !== void 0) {
1595
+ newContent.content = updates.content.content;
1596
+ }
1597
+ if ("parts" in updates.content && updates.content.parts !== void 0) {
1598
+ newContent.parts = updates.content.parts;
1599
+ }
1600
+ updatePayload.content = JSON.stringify(newContent);
1601
+ }
1602
+ await this.service.entities.message.update({ entity: "message", id }).set(updatePayload).go();
1603
+ const updatedMessage = await this.service.entities.message.get({ entity: "message", id }).go();
1604
+ if (updatedMessage.data) {
1605
+ updatedMessages.push(this.parseMessageData(updatedMessage.data));
1606
+ }
604
1607
  }
605
- this.logger.debug(`Table ${this.tableName} exists and is accessible`);
606
- } catch (error) {
607
- this.logger.error("Error validating table access", { tableName: this.tableName, error });
608
- throw error;
1608
+ for (const threadId of affectedThreadIds) {
1609
+ await this.service.entities.thread.update({ entity: "thread", id: threadId }).set({
1610
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1611
+ }).go();
1612
+ }
1613
+ return updatedMessages;
1614
+ } catch (error$1) {
1615
+ throw new error.MastraError(
1616
+ {
1617
+ id: "STORAGE_DYNAMODB_STORE_UPDATE_MESSAGES_FAILED",
1618
+ domain: error.ErrorDomain.STORAGE,
1619
+ category: error.ErrorCategory.THIRD_PARTY,
1620
+ details: { count: messages.length }
1621
+ },
1622
+ error$1
1623
+ );
1624
+ }
1625
+ }
1626
+ async getResourceById({ resourceId }) {
1627
+ this.logger.debug("Getting resource by ID", { resourceId });
1628
+ try {
1629
+ const result = await this.service.entities.resource.get({ entity: "resource", id: resourceId }).go();
1630
+ if (!result.data) {
1631
+ return null;
1632
+ }
1633
+ const data = result.data;
1634
+ return {
1635
+ ...data,
1636
+ // Convert date strings back to Date objects for consistency
1637
+ createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
1638
+ updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt,
1639
+ // Ensure workingMemory is always returned as a string, regardless of automatic parsing
1640
+ workingMemory: typeof data.workingMemory === "object" ? JSON.stringify(data.workingMemory) : data.workingMemory
1641
+ // metadata is already transformed by the entity's getter
1642
+ };
1643
+ } catch (error$1) {
1644
+ throw new error.MastraError(
1645
+ {
1646
+ id: "STORAGE_DYNAMODB_STORE_GET_RESOURCE_BY_ID_FAILED",
1647
+ domain: error.ErrorDomain.STORAGE,
1648
+ category: error.ErrorCategory.THIRD_PARTY,
1649
+ details: { resourceId }
1650
+ },
1651
+ error$1
1652
+ );
1653
+ }
1654
+ }
1655
+ async saveResource({ resource }) {
1656
+ this.logger.debug("Saving resource", { resourceId: resource.id });
1657
+ const now = /* @__PURE__ */ new Date();
1658
+ const resourceData = {
1659
+ entity: "resource",
1660
+ id: resource.id,
1661
+ workingMemory: resource.workingMemory,
1662
+ metadata: resource.metadata ? JSON.stringify(resource.metadata) : void 0,
1663
+ createdAt: resource.createdAt?.toISOString() || now.toISOString(),
1664
+ updatedAt: now.toISOString()
1665
+ };
1666
+ try {
1667
+ await this.service.entities.resource.upsert(resourceData).go();
1668
+ return {
1669
+ id: resource.id,
1670
+ workingMemory: resource.workingMemory,
1671
+ metadata: resource.metadata,
1672
+ createdAt: resource.createdAt || now,
1673
+ updatedAt: now
1674
+ };
1675
+ } catch (error$1) {
1676
+ throw new error.MastraError(
1677
+ {
1678
+ id: "STORAGE_DYNAMODB_STORE_SAVE_RESOURCE_FAILED",
1679
+ domain: error.ErrorDomain.STORAGE,
1680
+ category: error.ErrorCategory.THIRD_PARTY,
1681
+ details: { resourceId: resource.id }
1682
+ },
1683
+ error$1
1684
+ );
1685
+ }
1686
+ }
1687
+ async updateResource({
1688
+ resourceId,
1689
+ workingMemory,
1690
+ metadata
1691
+ }) {
1692
+ this.logger.debug("Updating resource", { resourceId });
1693
+ try {
1694
+ const existingResource = await this.getResourceById({ resourceId });
1695
+ if (!existingResource) {
1696
+ const newResource = {
1697
+ id: resourceId,
1698
+ workingMemory,
1699
+ metadata: metadata || {},
1700
+ createdAt: /* @__PURE__ */ new Date(),
1701
+ updatedAt: /* @__PURE__ */ new Date()
1702
+ };
1703
+ return this.saveResource({ resource: newResource });
1704
+ }
1705
+ const now = /* @__PURE__ */ new Date();
1706
+ const updateData = {
1707
+ updatedAt: now.toISOString()
1708
+ };
1709
+ if (workingMemory !== void 0) {
1710
+ updateData.workingMemory = workingMemory;
1711
+ }
1712
+ if (metadata) {
1713
+ const existingMetadata = existingResource.metadata || {};
1714
+ const mergedMetadata = { ...existingMetadata, ...metadata };
1715
+ updateData.metadata = JSON.stringify(mergedMetadata);
1716
+ }
1717
+ await this.service.entities.resource.update({ entity: "resource", id: resourceId }).set(updateData).go();
1718
+ return {
1719
+ ...existingResource,
1720
+ workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
1721
+ metadata: metadata ? { ...existingResource.metadata, ...metadata } : existingResource.metadata,
1722
+ updatedAt: now
1723
+ };
1724
+ } catch (error$1) {
1725
+ throw new error.MastraError(
1726
+ {
1727
+ id: "STORAGE_DYNAMODB_STORE_UPDATE_RESOURCE_FAILED",
1728
+ domain: error.ErrorDomain.STORAGE,
1729
+ category: error.ErrorCategory.THIRD_PARTY,
1730
+ details: { resourceId }
1731
+ },
1732
+ error$1
1733
+ );
1734
+ }
1735
+ }
1736
+ };
1737
+ var StoreOperationsDynamoDB = class extends storage.StoreOperations {
1738
+ client;
1739
+ tableName;
1740
+ service;
1741
+ constructor({
1742
+ service,
1743
+ tableName,
1744
+ client
1745
+ }) {
1746
+ super();
1747
+ this.service = service;
1748
+ this.client = client;
1749
+ this.tableName = tableName;
1750
+ }
1751
+ async hasColumn() {
1752
+ return true;
1753
+ }
1754
+ async dropTable() {
1755
+ }
1756
+ // Helper methods for entity/table mapping
1757
+ getEntityNameForTable(tableName) {
1758
+ const mapping = {
1759
+ [storage.TABLE_THREADS]: "thread",
1760
+ [storage.TABLE_MESSAGES]: "message",
1761
+ [storage.TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1762
+ [storage.TABLE_EVALS]: "eval",
1763
+ [storage.TABLE_SCORERS]: "score",
1764
+ [storage.TABLE_TRACES]: "trace",
1765
+ [storage.TABLE_RESOURCES]: "resource"
1766
+ };
1767
+ return mapping[tableName] || null;
1768
+ }
1769
+ /**
1770
+ * Pre-processes a record to ensure Date objects are converted to ISO strings
1771
+ * This is necessary because ElectroDB validation happens before setters are applied
1772
+ */
1773
+ preprocessRecord(record) {
1774
+ const processed = { ...record };
1775
+ if (processed.createdAt instanceof Date) {
1776
+ processed.createdAt = processed.createdAt.toISOString();
1777
+ }
1778
+ if (processed.updatedAt instanceof Date) {
1779
+ processed.updatedAt = processed.updatedAt.toISOString();
1780
+ }
1781
+ if (processed.created_at instanceof Date) {
1782
+ processed.created_at = processed.created_at.toISOString();
1783
+ }
1784
+ if (processed.result && typeof processed.result === "object") {
1785
+ processed.result = JSON.stringify(processed.result);
609
1786
  }
1787
+ if (processed.test_info && typeof processed.test_info === "object") {
1788
+ processed.test_info = JSON.stringify(processed.test_info);
1789
+ } else if (processed.test_info === void 0 || processed.test_info === null) {
1790
+ delete processed.test_info;
1791
+ }
1792
+ if (processed.snapshot && typeof processed.snapshot === "object") {
1793
+ processed.snapshot = JSON.stringify(processed.snapshot);
1794
+ }
1795
+ if (processed.attributes && typeof processed.attributes === "object") {
1796
+ processed.attributes = JSON.stringify(processed.attributes);
1797
+ }
1798
+ if (processed.status && typeof processed.status === "object") {
1799
+ processed.status = JSON.stringify(processed.status);
1800
+ }
1801
+ if (processed.events && typeof processed.events === "object") {
1802
+ processed.events = JSON.stringify(processed.events);
1803
+ }
1804
+ if (processed.links && typeof processed.links === "object") {
1805
+ processed.links = JSON.stringify(processed.links);
1806
+ }
1807
+ return processed;
610
1808
  }
611
1809
  /**
612
1810
  * Validates that the required DynamoDB table exists and is accessible.
@@ -620,61 +1818,80 @@ var DynamoDBStore = class extends storage.MastraStorage {
620
1818
  });
621
1819
  await this.client.send(command);
622
1820
  return true;
623
- } catch (error) {
624
- if (error.name === "ResourceNotFoundException") {
1821
+ } catch (error$1) {
1822
+ if (error$1.name === "ResourceNotFoundException") {
625
1823
  return false;
626
1824
  }
627
- throw error;
628
- }
629
- }
630
- /**
631
- * Initialize storage, validating the externally managed table is accessible.
632
- * For the single-table design, we only validate once that we can access
633
- * the table that was created via CDK/CloudFormation.
634
- */
635
- async init() {
636
- if (this.hasInitialized === null) {
637
- this.hasInitialized = this._performInitializationAndStore();
638
- }
639
- try {
640
- await this.hasInitialized;
641
- } catch (error) {
642
- throw error;
1825
+ throw new error.MastraError(
1826
+ {
1827
+ id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
1828
+ domain: error.ErrorDomain.STORAGE,
1829
+ category: error.ErrorCategory.THIRD_PARTY,
1830
+ details: { tableName: this.tableName }
1831
+ },
1832
+ error$1
1833
+ );
643
1834
  }
644
1835
  }
645
1836
  /**
646
- * Performs the actual table validation and stores the promise.
647
- * Handles resetting the stored promise on failure to allow retries.
1837
+ * This method is modified for DynamoDB with ElectroDB single-table design.
1838
+ * It assumes the table is created and managed externally via CDK/CloudFormation.
1839
+ *
1840
+ * This implementation only validates that the required table exists and is accessible.
1841
+ * No table creation is attempted - we simply check if we can access the table.
648
1842
  */
649
- _performInitializationAndStore() {
650
- return this.validateTableExists().then((exists) => {
651
- if (!exists) {
1843
+ async createTable({ tableName }) {
1844
+ this.logger.debug("Validating access to externally managed table", { tableName, physicalTable: this.tableName });
1845
+ try {
1846
+ const tableExists = await this.validateTableExists();
1847
+ if (!tableExists) {
1848
+ this.logger.error(
1849
+ `Table ${this.tableName} does not exist or is not accessible. It should be created via CDK/CloudFormation.`
1850
+ );
652
1851
  throw new Error(
653
1852
  `Table ${this.tableName} does not exist or is not accessible. Ensure it's created via CDK/CloudFormation before using this store.`
654
1853
  );
655
1854
  }
656
- return true;
657
- }).catch((err) => {
658
- this.hasInitialized = null;
659
- throw err;
660
- });
661
- }
662
- /**
663
- * Pre-processes a record to ensure Date objects are converted to ISO strings
664
- * This is necessary because ElectroDB validation happens before setters are applied
665
- */
666
- preprocessRecord(record) {
667
- const processed = { ...record };
668
- if (processed.createdAt instanceof Date) {
669
- processed.createdAt = processed.createdAt.toISOString();
1855
+ this.logger.debug(`Table ${this.tableName} exists and is accessible`);
1856
+ } catch (error$1) {
1857
+ this.logger.error("Error validating table access", { tableName: this.tableName, error: error$1 });
1858
+ throw new error.MastraError(
1859
+ {
1860
+ id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_ACCESS_FAILED",
1861
+ domain: error.ErrorDomain.STORAGE,
1862
+ category: error.ErrorCategory.THIRD_PARTY,
1863
+ details: { tableName: this.tableName }
1864
+ },
1865
+ error$1
1866
+ );
670
1867
  }
671
- if (processed.updatedAt instanceof Date) {
672
- processed.updatedAt = processed.updatedAt.toISOString();
1868
+ }
1869
+ async insert({ tableName, record }) {
1870
+ this.logger.debug("DynamoDB insert called", { tableName });
1871
+ const entityName = this.getEntityNameForTable(tableName);
1872
+ if (!entityName || !this.service.entities[entityName]) {
1873
+ throw new error.MastraError({
1874
+ id: "STORAGE_DYNAMODB_STORE_INSERT_INVALID_ARGS",
1875
+ domain: error.ErrorDomain.STORAGE,
1876
+ category: error.ErrorCategory.USER,
1877
+ text: "No entity defined for tableName",
1878
+ details: { tableName }
1879
+ });
673
1880
  }
674
- if (processed.created_at instanceof Date) {
675
- processed.created_at = processed.created_at.toISOString();
1881
+ try {
1882
+ const dataToSave = { entity: entityName, ...this.preprocessRecord(record) };
1883
+ await this.service.entities[entityName].create(dataToSave).go();
1884
+ } catch (error$1) {
1885
+ throw new error.MastraError(
1886
+ {
1887
+ id: "STORAGE_DYNAMODB_STORE_INSERT_FAILED",
1888
+ domain: error.ErrorDomain.STORAGE,
1889
+ category: error.ErrorCategory.THIRD_PARTY,
1890
+ details: { tableName }
1891
+ },
1892
+ error$1
1893
+ );
676
1894
  }
677
- return processed;
678
1895
  }
679
1896
  async alterTable(_args) {
680
1897
  }
@@ -685,7 +1902,13 @@ var DynamoDBStore = class extends storage.MastraStorage {
685
1902
  this.logger.debug("DynamoDB clearTable called", { tableName });
686
1903
  const entityName = this.getEntityNameForTable(tableName);
687
1904
  if (!entityName || !this.service.entities[entityName]) {
688
- throw new Error(`No entity defined for ${tableName}`);
1905
+ throw new error.MastraError({
1906
+ id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_INVALID_ARGS",
1907
+ domain: error.ErrorDomain.STORAGE,
1908
+ category: error.ErrorCategory.USER,
1909
+ text: "No entity defined for tableName",
1910
+ details: { tableName }
1911
+ });
689
1912
  }
690
1913
  try {
691
1914
  const result = await this.service.entities[entityName].scan.go({ pages: "all" });
@@ -705,10 +1928,10 @@ var DynamoDBStore = class extends storage.MastraStorage {
705
1928
  if (!item.id) throw new Error(`Missing required key 'id' for entity 'message'`);
706
1929
  key.id = item.id;
707
1930
  break;
708
- case "workflowSnapshot":
1931
+ case "workflow_snapshot":
709
1932
  if (!item.workflow_name)
710
- throw new Error(`Missing required key 'workflow_name' for entity 'workflowSnapshot'`);
711
- if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'workflowSnapshot'`);
1933
+ throw new Error(`Missing required key 'workflow_name' for entity 'workflow_snapshot'`);
1934
+ if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'workflow_snapshot'`);
712
1935
  key.workflow_name = item.workflow_name;
713
1936
  key.run_id = item.run_id;
714
1937
  break;
@@ -720,6 +1943,10 @@ var DynamoDBStore = class extends storage.MastraStorage {
720
1943
  if (!item.id) throw new Error(`Missing required key 'id' for entity 'trace'`);
721
1944
  key.id = item.id;
722
1945
  break;
1946
+ case "score":
1947
+ if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
1948
+ key.id = item.id;
1949
+ break;
723
1950
  default:
724
1951
  this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
725
1952
  throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
@@ -732,26 +1959,16 @@ var DynamoDBStore = class extends storage.MastraStorage {
732
1959
  await this.service.entities[entityName].delete(batchKeys).go();
733
1960
  }
734
1961
  this.logger.debug(`Successfully cleared all records for ${tableName}`);
735
- } catch (error) {
736
- this.logger.error("Failed to clear table", { tableName, error });
737
- throw error;
738
- }
739
- }
740
- /**
741
- * Insert a record into the specified "table" (entity)
742
- */
743
- async insert({ tableName, record }) {
744
- this.logger.debug("DynamoDB insert called", { tableName });
745
- const entityName = this.getEntityNameForTable(tableName);
746
- if (!entityName || !this.service.entities[entityName]) {
747
- throw new Error(`No entity defined for ${tableName}`);
748
- }
749
- try {
750
- const dataToSave = { entity: entityName, ...this.preprocessRecord(record) };
751
- await this.service.entities[entityName].create(dataToSave).go();
752
- } catch (error) {
753
- this.logger.error("Failed to insert record", { tableName, error });
754
- throw error;
1962
+ } catch (error$1) {
1963
+ throw new error.MastraError(
1964
+ {
1965
+ id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_FAILED",
1966
+ domain: error.ErrorDomain.STORAGE,
1967
+ category: error.ErrorCategory.THIRD_PARTY,
1968
+ details: { tableName }
1969
+ },
1970
+ error$1
1971
+ );
755
1972
  }
756
1973
  }
757
1974
  /**
@@ -761,7 +1978,13 @@ var DynamoDBStore = class extends storage.MastraStorage {
761
1978
  this.logger.debug("DynamoDB batchInsert called", { tableName, count: records.length });
762
1979
  const entityName = this.getEntityNameForTable(tableName);
763
1980
  if (!entityName || !this.service.entities[entityName]) {
764
- throw new Error(`No entity defined for ${tableName}`);
1981
+ throw new error.MastraError({
1982
+ id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_INVALID_ARGS",
1983
+ domain: error.ErrorDomain.STORAGE,
1984
+ category: error.ErrorCategory.USER,
1985
+ text: "No entity defined for tableName",
1986
+ details: { tableName }
1987
+ });
765
1988
  }
766
1989
  const recordsToSave = records.map((rec) => ({ entity: entityName, ...this.preprocessRecord(rec) }));
767
1990
  const batchSize = 25;
@@ -781,9 +2004,16 @@ var DynamoDBStore = class extends storage.MastraStorage {
781
2004
  await this.service.entities[entityName].create(recordData).go();
782
2005
  }
783
2006
  }
784
- } catch (error) {
785
- this.logger.error("Failed to batch insert records", { tableName, error });
786
- throw error;
2007
+ } catch (error$1) {
2008
+ throw new error.MastraError(
2009
+ {
2010
+ id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_FAILED",
2011
+ domain: error.ErrorDomain.STORAGE,
2012
+ category: error.ErrorCategory.THIRD_PARTY,
2013
+ details: { tableName }
2014
+ },
2015
+ error$1
2016
+ );
787
2017
  }
788
2018
  }
789
2019
  /**
@@ -793,7 +2023,13 @@ var DynamoDBStore = class extends storage.MastraStorage {
793
2023
  this.logger.debug("DynamoDB load called", { tableName, keys });
794
2024
  const entityName = this.getEntityNameForTable(tableName);
795
2025
  if (!entityName || !this.service.entities[entityName]) {
796
- throw new Error(`No entity defined for ${tableName}`);
2026
+ throw new error.MastraError({
2027
+ id: "STORAGE_DYNAMODB_STORE_LOAD_INVALID_ARGS",
2028
+ domain: error.ErrorDomain.STORAGE,
2029
+ category: error.ErrorCategory.USER,
2030
+ text: "No entity defined for tableName",
2031
+ details: { tableName }
2032
+ });
797
2033
  }
798
2034
  try {
799
2035
  const keyObject = { entity: entityName, ...keys };
@@ -803,224 +2039,239 @@ var DynamoDBStore = class extends storage.MastraStorage {
803
2039
  }
804
2040
  let data = result.data;
805
2041
  return data;
806
- } catch (error) {
807
- this.logger.error("Failed to load record", { tableName, keys, error });
808
- throw error;
2042
+ } catch (error$1) {
2043
+ throw new error.MastraError(
2044
+ {
2045
+ id: "STORAGE_DYNAMODB_STORE_LOAD_FAILED",
2046
+ domain: error.ErrorDomain.STORAGE,
2047
+ category: error.ErrorCategory.THIRD_PARTY,
2048
+ details: { tableName }
2049
+ },
2050
+ error$1
2051
+ );
809
2052
  }
810
2053
  }
811
- // Thread operations
812
- async getThreadById({ threadId }) {
813
- this.logger.debug("Getting thread by ID", { threadId });
2054
+ };
2055
+ var ScoresStorageDynamoDB = class extends storage.ScoresStorage {
2056
+ service;
2057
+ constructor({ service }) {
2058
+ super();
2059
+ this.service = service;
2060
+ }
2061
+ // Helper function to parse score data (handle JSON fields)
2062
+ parseScoreData(data) {
2063
+ return {
2064
+ ...data,
2065
+ // Convert date strings back to Date objects for consistency
2066
+ createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
2067
+ updatedAt: data.updatedAt ? new Date(data.updatedAt) : /* @__PURE__ */ new Date()
2068
+ // JSON fields are already transformed by the entity's getters
2069
+ };
2070
+ }
2071
+ async getScoreById({ id }) {
2072
+ this.logger.debug("Getting score by ID", { id });
814
2073
  try {
815
- const result = await this.service.entities.thread.get({ entity: "thread", id: threadId }).go();
2074
+ const result = await this.service.entities.score.get({ entity: "score", id }).go();
816
2075
  if (!result.data) {
817
2076
  return null;
818
2077
  }
819
- const data = result.data;
820
- return {
821
- ...data,
822
- // Convert date strings back to Date objects for consistency
823
- createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
824
- updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
825
- // metadata: data.metadata ? JSON.parse(data.metadata) : undefined, // REMOVED by AI
826
- // metadata is already transformed by the entity's getter
827
- };
828
- } catch (error) {
829
- this.logger.error("Failed to get thread by ID", { threadId, error });
830
- throw error;
831
- }
832
- }
833
- async getThreadsByResourceId({ resourceId }) {
834
- this.logger.debug("Getting threads by resource ID", { resourceId });
835
- try {
836
- const result = await this.service.entities.thread.query.byResource({ entity: "thread", resourceId }).go();
837
- if (!result.data.length) {
838
- return [];
839
- }
840
- return result.data.map((data) => ({
841
- ...data,
842
- // Convert date strings back to Date objects for consistency
843
- createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
844
- updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
845
- // metadata: data.metadata ? JSON.parse(data.metadata) : undefined, // REMOVED by AI
846
- // metadata is already transformed by the entity's getter
847
- }));
848
- } catch (error) {
849
- this.logger.error("Failed to get threads by resource ID", { resourceId, error });
850
- throw error;
2078
+ return this.parseScoreData(result.data);
2079
+ } catch (error$1) {
2080
+ throw new error.MastraError(
2081
+ {
2082
+ id: "STORAGE_DYNAMODB_STORE_GET_SCORE_BY_ID_FAILED",
2083
+ domain: error.ErrorDomain.STORAGE,
2084
+ category: error.ErrorCategory.THIRD_PARTY,
2085
+ details: { id }
2086
+ },
2087
+ error$1
2088
+ );
851
2089
  }
852
2090
  }
853
- async saveThread({ thread }) {
854
- this.logger.debug("Saving thread", { threadId: thread.id });
2091
+ async saveScore(score) {
2092
+ this.logger.debug("Saving score", { scorerId: score.scorerId, runId: score.runId });
855
2093
  const now = /* @__PURE__ */ new Date();
856
- const threadData = {
857
- entity: "thread",
858
- id: thread.id,
859
- resourceId: thread.resourceId,
860
- title: thread.title || `Thread ${thread.id}`,
861
- createdAt: thread.createdAt?.toISOString() || now.toISOString(),
862
- updatedAt: now.toISOString(),
863
- metadata: thread.metadata ? JSON.stringify(thread.metadata) : void 0
2094
+ const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2095
+ const scoreData = {
2096
+ entity: "score",
2097
+ id: scoreId,
2098
+ scorerId: score.scorerId,
2099
+ traceId: score.traceId || "",
2100
+ runId: score.runId,
2101
+ scorer: typeof score.scorer === "string" ? score.scorer : JSON.stringify(score.scorer),
2102
+ extractStepResult: typeof score.extractStepResult === "string" ? score.extractStepResult : JSON.stringify(score.extractStepResult),
2103
+ analyzeStepResult: typeof score.analyzeStepResult === "string" ? score.analyzeStepResult : JSON.stringify(score.analyzeStepResult),
2104
+ score: score.score,
2105
+ reason: score.reason,
2106
+ extractPrompt: score.extractPrompt,
2107
+ analyzePrompt: score.analyzePrompt,
2108
+ reasonPrompt: score.reasonPrompt,
2109
+ input: typeof score.input === "string" ? score.input : JSON.stringify(score.input),
2110
+ output: typeof score.output === "string" ? score.output : JSON.stringify(score.output),
2111
+ additionalContext: typeof score.additionalContext === "string" ? score.additionalContext : JSON.stringify(score.additionalContext),
2112
+ runtimeContext: typeof score.runtimeContext === "string" ? score.runtimeContext : JSON.stringify(score.runtimeContext),
2113
+ entityType: score.entityType,
2114
+ entityData: typeof score.entity === "string" ? score.entity : JSON.stringify(score.entity),
2115
+ entityId: score.entityId,
2116
+ source: score.source,
2117
+ resourceId: score.resourceId || "",
2118
+ threadId: score.threadId || "",
2119
+ createdAt: now.toISOString(),
2120
+ updatedAt: now.toISOString()
864
2121
  };
865
2122
  try {
866
- await this.service.entities.thread.create(threadData).go();
867
- return {
868
- id: thread.id,
869
- resourceId: thread.resourceId,
870
- title: threadData.title,
871
- createdAt: thread.createdAt || now,
872
- updatedAt: now,
873
- metadata: thread.metadata
2123
+ await this.service.entities.score.upsert(scoreData).go();
2124
+ const savedScore = {
2125
+ ...score,
2126
+ id: scoreId,
2127
+ createdAt: now,
2128
+ updatedAt: now
874
2129
  };
875
- } catch (error) {
876
- this.logger.error("Failed to save thread", { threadId: thread.id, error });
877
- throw error;
2130
+ return { score: savedScore };
2131
+ } catch (error$1) {
2132
+ throw new error.MastraError(
2133
+ {
2134
+ id: "STORAGE_DYNAMODB_STORE_SAVE_SCORE_FAILED",
2135
+ domain: error.ErrorDomain.STORAGE,
2136
+ category: error.ErrorCategory.THIRD_PARTY,
2137
+ details: { scorerId: score.scorerId, runId: score.runId }
2138
+ },
2139
+ error$1
2140
+ );
878
2141
  }
879
2142
  }
880
- async updateThread({
881
- id,
882
- title,
883
- metadata
2143
+ async getScoresByScorerId({
2144
+ scorerId,
2145
+ pagination,
2146
+ entityId,
2147
+ entityType
884
2148
  }) {
885
- this.logger.debug("Updating thread", { threadId: id });
2149
+ this.logger.debug("Getting scores by scorer ID", { scorerId, pagination, entityId, entityType });
886
2150
  try {
887
- const existingThread = await this.getThreadById({ threadId: id });
888
- if (!existingThread) {
889
- throw new Error(`Thread not found: ${id}`);
890
- }
891
- const now = /* @__PURE__ */ new Date();
892
- const updateData = {
893
- updatedAt: now.toISOString()
894
- };
895
- if (title) {
896
- updateData.title = title;
2151
+ const query = this.service.entities.score.query.byScorer({ entity: "score", scorerId });
2152
+ const results = await query.go();
2153
+ let allScores = results.data.map((data) => this.parseScoreData(data));
2154
+ if (entityId) {
2155
+ allScores = allScores.filter((score) => score.entityId === entityId);
897
2156
  }
898
- if (metadata) {
899
- updateData.metadata = JSON.stringify(metadata);
2157
+ if (entityType) {
2158
+ allScores = allScores.filter((score) => score.entityType === entityType);
900
2159
  }
901
- await this.service.entities.thread.update({ entity: "thread", id }).set(updateData).go();
2160
+ allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2161
+ const startIndex = pagination.page * pagination.perPage;
2162
+ const endIndex = startIndex + pagination.perPage;
2163
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2164
+ const total = allScores.length;
2165
+ const hasMore = endIndex < total;
902
2166
  return {
903
- ...existingThread,
904
- title: title || existingThread.title,
905
- metadata: metadata || existingThread.metadata,
906
- updatedAt: now
2167
+ scores: paginatedScores,
2168
+ pagination: {
2169
+ total,
2170
+ page: pagination.page,
2171
+ perPage: pagination.perPage,
2172
+ hasMore
2173
+ }
907
2174
  };
908
- } catch (error) {
909
- this.logger.error("Failed to update thread", { threadId: id, error });
910
- throw error;
911
- }
912
- }
913
- async deleteThread({ threadId }) {
914
- this.logger.debug("Deleting thread", { threadId });
915
- try {
916
- await this.service.entities.thread.delete({ entity: "thread", id: threadId }).go();
917
- } catch (error) {
918
- this.logger.error("Failed to delete thread", { threadId, error });
919
- throw error;
2175
+ } catch (error$1) {
2176
+ throw new error.MastraError(
2177
+ {
2178
+ id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_SCORER_ID_FAILED",
2179
+ domain: error.ErrorDomain.STORAGE,
2180
+ category: error.ErrorCategory.THIRD_PARTY,
2181
+ details: {
2182
+ scorerId: scorerId || "",
2183
+ entityId: entityId || "",
2184
+ entityType: entityType || "",
2185
+ page: pagination.page,
2186
+ perPage: pagination.perPage
2187
+ }
2188
+ },
2189
+ error$1
2190
+ );
920
2191
  }
921
2192
  }
922
- async getMessages({
923
- threadId,
924
- resourceId,
925
- selectBy,
926
- format
2193
+ async getScoresByRunId({
2194
+ runId,
2195
+ pagination
927
2196
  }) {
928
- this.logger.debug("Getting messages", { threadId, selectBy });
2197
+ this.logger.debug("Getting scores by run ID", { runId, pagination });
929
2198
  try {
930
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
931
- const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
932
- if (limit !== Number.MAX_SAFE_INTEGER) {
933
- const results2 = await query.go({ limit, order: "desc" });
934
- const list2 = new agent.MessageList({ threadId, resourceId }).add(
935
- results2.data.map((data) => this.parseMessageData(data)),
936
- "memory"
937
- );
938
- if (format === `v2`) return list2.get.all.v2();
939
- return list2.get.all.v1();
940
- }
2199
+ const query = this.service.entities.score.query.byRun({ entity: "score", runId });
941
2200
  const results = await query.go();
942
- const list = new agent.MessageList({ threadId, resourceId }).add(
943
- results.data.map((data) => this.parseMessageData(data)),
944
- "memory"
2201
+ const allScores = results.data.map((data) => this.parseScoreData(data));
2202
+ allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2203
+ const startIndex = pagination.page * pagination.perPage;
2204
+ const endIndex = startIndex + pagination.perPage;
2205
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2206
+ const total = allScores.length;
2207
+ const hasMore = endIndex < total;
2208
+ return {
2209
+ scores: paginatedScores,
2210
+ pagination: {
2211
+ total,
2212
+ page: pagination.page,
2213
+ perPage: pagination.perPage,
2214
+ hasMore
2215
+ }
2216
+ };
2217
+ } catch (error$1) {
2218
+ throw new error.MastraError(
2219
+ {
2220
+ id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_RUN_ID_FAILED",
2221
+ domain: error.ErrorDomain.STORAGE,
2222
+ category: error.ErrorCategory.THIRD_PARTY,
2223
+ details: { runId, page: pagination.page, perPage: pagination.perPage }
2224
+ },
2225
+ error$1
945
2226
  );
946
- if (format === `v2`) return list.get.all.v2();
947
- return list.get.all.v1();
948
- } catch (error) {
949
- this.logger.error("Failed to get messages", { threadId, error });
950
- throw error;
951
2227
  }
952
2228
  }
953
- async saveMessages(args) {
954
- const { messages, format = "v1" } = args;
955
- this.logger.debug("Saving messages", { count: messages.length });
956
- if (!messages.length) {
957
- return [];
958
- }
959
- const threadId = messages[0]?.threadId;
960
- if (!threadId) {
961
- throw new Error("Thread ID is required");
962
- }
963
- const messagesToSave = messages.map((msg) => {
964
- const now = (/* @__PURE__ */ new Date()).toISOString();
2229
+ async getScoresByEntityId({
2230
+ entityId,
2231
+ entityType,
2232
+ pagination
2233
+ }) {
2234
+ this.logger.debug("Getting scores by entity ID", { entityId, entityType, pagination });
2235
+ try {
2236
+ const query = this.service.entities.score.query.byEntityData({ entity: "score", entityId });
2237
+ const results = await query.go();
2238
+ let allScores = results.data.map((data) => this.parseScoreData(data));
2239
+ allScores = allScores.filter((score) => score.entityType === entityType);
2240
+ allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2241
+ const startIndex = pagination.page * pagination.perPage;
2242
+ const endIndex = startIndex + pagination.perPage;
2243
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2244
+ const total = allScores.length;
2245
+ const hasMore = endIndex < total;
965
2246
  return {
966
- entity: "message",
967
- // Add entity type
968
- id: msg.id,
969
- threadId: msg.threadId,
970
- role: msg.role,
971
- type: msg.type,
972
- resourceId: msg.resourceId,
973
- // Ensure complex fields are stringified if not handled by attribute setters
974
- content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
975
- toolCallArgs: `toolCallArgs` in msg && msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
976
- toolCallIds: `toolCallIds` in msg && msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
977
- toolNames: `toolNames` in msg && msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
978
- createdAt: msg.createdAt instanceof Date ? msg.createdAt.toISOString() : msg.createdAt || now,
979
- updatedAt: now
980
- // Add updatedAt
2247
+ scores: paginatedScores,
2248
+ pagination: {
2249
+ total,
2250
+ page: pagination.page,
2251
+ perPage: pagination.perPage,
2252
+ hasMore
2253
+ }
981
2254
  };
982
- });
983
- try {
984
- const batchSize = 25;
985
- const batches = [];
986
- for (let i = 0; i < messagesToSave.length; i += batchSize) {
987
- const batch = messagesToSave.slice(i, i + batchSize);
988
- batches.push(batch);
989
- }
990
- await Promise.all([
991
- // Process message batches
992
- ...batches.map(async (batch) => {
993
- for (const messageData of batch) {
994
- if (!messageData.entity) {
995
- this.logger.error("Missing entity property in message data for create", { messageData });
996
- throw new Error("Internal error: Missing entity property during saveMessages");
997
- }
998
- await this.service.entities.message.create(messageData).go();
999
- }
1000
- }),
1001
- // Update thread's updatedAt timestamp
1002
- this.service.entities.thread.update({ entity: "thread", id: threadId }).set({
1003
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1004
- }).go()
1005
- ]);
1006
- const list = new agent.MessageList().add(messages, "memory");
1007
- if (format === `v1`) return list.get.all.v1();
1008
- return list.get.all.v2();
1009
- } catch (error) {
1010
- this.logger.error("Failed to save messages", { error });
1011
- throw error;
2255
+ } catch (error$1) {
2256
+ throw new error.MastraError(
2257
+ {
2258
+ id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_ENTITY_ID_FAILED",
2259
+ domain: error.ErrorDomain.STORAGE,
2260
+ category: error.ErrorCategory.THIRD_PARTY,
2261
+ details: { entityId, entityType, page: pagination.page, perPage: pagination.perPage }
2262
+ },
2263
+ error$1
2264
+ );
1012
2265
  }
1013
2266
  }
1014
- // Helper function to parse message data (handle JSON fields)
1015
- parseMessageData(data) {
1016
- return {
1017
- ...data,
1018
- // Ensure dates are Date objects if needed (ElectroDB might return strings)
1019
- createdAt: data.createdAt ? new Date(data.createdAt) : void 0,
1020
- updatedAt: data.updatedAt ? new Date(data.updatedAt) : void 0
1021
- // Other fields like content, toolCallArgs etc. are assumed to be correctly
1022
- // transformed by the ElectroDB entity getters.
1023
- };
2267
+ };
2268
+ var TracesStorageDynamoDB = class extends storage.TracesStorage {
2269
+ service;
2270
+ operations;
2271
+ constructor({ service, operations }) {
2272
+ super();
2273
+ this.service = service;
2274
+ this.operations = operations;
1024
2275
  }
1025
2276
  // Trace operations
1026
2277
  async getTraces(args) {
@@ -1047,34 +2298,222 @@ var DynamoDBStore = class extends storage.MastraStorage {
1047
2298
  items = results.data;
1048
2299
  break;
1049
2300
  }
1050
- cursor = results.cursor;
1051
- if (!cursor && results.data.length > 0 && pagesFetched < startPage) {
1052
- break;
2301
+ cursor = results.cursor;
2302
+ if (!cursor && results.data.length > 0 && pagesFetched < startPage) {
2303
+ break;
2304
+ }
2305
+ } while (cursor && pagesFetched < startPage);
2306
+ return items;
2307
+ } catch (error$1) {
2308
+ throw new error.MastraError(
2309
+ {
2310
+ id: "STORAGE_DYNAMODB_STORE_GET_TRACES_FAILED",
2311
+ domain: error.ErrorDomain.STORAGE,
2312
+ category: error.ErrorCategory.THIRD_PARTY
2313
+ },
2314
+ error$1
2315
+ );
2316
+ }
2317
+ }
2318
+ async batchTraceInsert({ records }) {
2319
+ this.logger.debug("Batch inserting traces", { count: records.length });
2320
+ if (!records.length) {
2321
+ return;
2322
+ }
2323
+ try {
2324
+ const recordsToSave = records.map((rec) => ({ entity: "trace", ...rec }));
2325
+ await this.operations.batchInsert({
2326
+ tableName: storage.TABLE_TRACES,
2327
+ records: recordsToSave
2328
+ // Pass records with 'entity' included
2329
+ });
2330
+ } catch (error$1) {
2331
+ throw new error.MastraError(
2332
+ {
2333
+ id: "STORAGE_DYNAMODB_STORE_BATCH_TRACE_INSERT_FAILED",
2334
+ domain: error.ErrorDomain.STORAGE,
2335
+ category: error.ErrorCategory.THIRD_PARTY,
2336
+ details: { count: records.length }
2337
+ },
2338
+ error$1
2339
+ );
2340
+ }
2341
+ }
2342
+ async getTracesPaginated(args) {
2343
+ const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
2344
+ this.logger.debug("Getting traces with pagination", { name, scope, page, perPage, attributes, filters, dateRange });
2345
+ try {
2346
+ let query;
2347
+ if (name) {
2348
+ query = this.service.entities.trace.query.byName({ entity: "trace", name });
2349
+ } else if (scope) {
2350
+ query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
2351
+ } else {
2352
+ this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
2353
+ query = this.service.entities.trace.scan;
2354
+ }
2355
+ const results = await query.go({
2356
+ order: "desc",
2357
+ pages: "all"
2358
+ // Get all pages to apply filtering and pagination
2359
+ });
2360
+ if (!results.data.length) {
2361
+ return {
2362
+ traces: [],
2363
+ total: 0,
2364
+ page,
2365
+ perPage,
2366
+ hasMore: false
2367
+ };
2368
+ }
2369
+ let filteredData = results.data;
2370
+ if (attributes) {
2371
+ filteredData = filteredData.filter((item) => {
2372
+ try {
2373
+ let itemAttributes = {};
2374
+ if (item.attributes) {
2375
+ if (typeof item.attributes === "string") {
2376
+ if (item.attributes === "[object Object]") {
2377
+ itemAttributes = {};
2378
+ } else {
2379
+ try {
2380
+ itemAttributes = JSON.parse(item.attributes);
2381
+ } catch {
2382
+ itemAttributes = {};
2383
+ }
2384
+ }
2385
+ } else if (typeof item.attributes === "object") {
2386
+ itemAttributes = item.attributes;
2387
+ }
2388
+ }
2389
+ return Object.entries(attributes).every(([key, value]) => itemAttributes[key] === value);
2390
+ } catch (e) {
2391
+ this.logger.warn("Failed to parse attributes during filtering", { item, error: e });
2392
+ return false;
2393
+ }
2394
+ });
2395
+ }
2396
+ if (dateRange?.start) {
2397
+ filteredData = filteredData.filter((item) => {
2398
+ const itemDate = new Date(item.createdAt);
2399
+ return itemDate >= dateRange.start;
2400
+ });
2401
+ }
2402
+ if (dateRange?.end) {
2403
+ filteredData = filteredData.filter((item) => {
2404
+ const itemDate = new Date(item.createdAt);
2405
+ return itemDate <= dateRange.end;
2406
+ });
2407
+ }
2408
+ const total = filteredData.length;
2409
+ const start = page * perPage;
2410
+ const end = start + perPage;
2411
+ const paginatedData = filteredData.slice(start, end);
2412
+ const traces = paginatedData.map((item) => {
2413
+ let attributes2;
2414
+ if (item.attributes) {
2415
+ if (typeof item.attributes === "string") {
2416
+ if (item.attributes === "[object Object]") {
2417
+ attributes2 = void 0;
2418
+ } else {
2419
+ try {
2420
+ attributes2 = JSON.parse(item.attributes);
2421
+ } catch {
2422
+ attributes2 = void 0;
2423
+ }
2424
+ }
2425
+ } else if (typeof item.attributes === "object") {
2426
+ attributes2 = item.attributes;
2427
+ }
2428
+ }
2429
+ let status;
2430
+ if (item.status) {
2431
+ if (typeof item.status === "string") {
2432
+ try {
2433
+ status = JSON.parse(item.status);
2434
+ } catch {
2435
+ status = void 0;
2436
+ }
2437
+ } else if (typeof item.status === "object") {
2438
+ status = item.status;
2439
+ }
1053
2440
  }
1054
- } while (cursor && pagesFetched < startPage);
1055
- return items;
1056
- } catch (error) {
1057
- this.logger.error("Failed to get traces", { error });
1058
- throw error;
1059
- }
1060
- }
1061
- async batchTraceInsert({ records }) {
1062
- this.logger.debug("Batch inserting traces", { count: records.length });
1063
- if (!records.length) {
1064
- return;
1065
- }
1066
- try {
1067
- const recordsToSave = records.map((rec) => ({ entity: "trace", ...rec }));
1068
- await this.batchInsert({
1069
- tableName: storage.TABLE_TRACES,
1070
- records: recordsToSave
1071
- // Pass records with 'entity' included
2441
+ let events;
2442
+ if (item.events) {
2443
+ if (typeof item.events === "string") {
2444
+ try {
2445
+ events = JSON.parse(item.events);
2446
+ } catch {
2447
+ events = void 0;
2448
+ }
2449
+ } else if (Array.isArray(item.events)) {
2450
+ events = item.events;
2451
+ }
2452
+ }
2453
+ let links;
2454
+ if (item.links) {
2455
+ if (typeof item.links === "string") {
2456
+ try {
2457
+ links = JSON.parse(item.links);
2458
+ } catch {
2459
+ links = void 0;
2460
+ }
2461
+ } else if (Array.isArray(item.links)) {
2462
+ links = item.links;
2463
+ }
2464
+ }
2465
+ return {
2466
+ id: item.id,
2467
+ parentSpanId: item.parentSpanId,
2468
+ name: item.name,
2469
+ traceId: item.traceId,
2470
+ scope: item.scope,
2471
+ kind: item.kind,
2472
+ attributes: attributes2,
2473
+ status,
2474
+ events,
2475
+ links,
2476
+ other: item.other,
2477
+ startTime: item.startTime,
2478
+ endTime: item.endTime,
2479
+ createdAt: item.createdAt
2480
+ };
1072
2481
  });
1073
- } catch (error) {
1074
- this.logger.error("Failed to batch insert traces", { error });
1075
- throw error;
2482
+ return {
2483
+ traces,
2484
+ total,
2485
+ page,
2486
+ perPage,
2487
+ hasMore: end < total
2488
+ };
2489
+ } catch (error$1) {
2490
+ throw new error.MastraError(
2491
+ {
2492
+ id: "STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED",
2493
+ domain: error.ErrorDomain.STORAGE,
2494
+ category: error.ErrorCategory.THIRD_PARTY
2495
+ },
2496
+ error$1
2497
+ );
1076
2498
  }
1077
2499
  }
2500
+ };
2501
+ function formatWorkflowRun(snapshotData) {
2502
+ return {
2503
+ workflowName: snapshotData.workflow_name,
2504
+ runId: snapshotData.run_id,
2505
+ snapshot: snapshotData.snapshot,
2506
+ createdAt: new Date(snapshotData.createdAt),
2507
+ updatedAt: new Date(snapshotData.updatedAt),
2508
+ resourceId: snapshotData.resourceId
2509
+ };
2510
+ }
2511
+ var WorkflowStorageDynamoDB = class extends storage.WorkflowsStorage {
2512
+ service;
2513
+ constructor({ service }) {
2514
+ super();
2515
+ this.service = service;
2516
+ }
1078
2517
  // Workflow operations
1079
2518
  async persistWorkflowSnapshot({
1080
2519
  workflowName,
@@ -1096,10 +2535,17 @@ var DynamoDBStore = class extends storage.MastraStorage {
1096
2535
  updatedAt: now,
1097
2536
  resourceId
1098
2537
  };
1099
- await this.service.entities.workflowSnapshot.upsert(data).go();
1100
- } catch (error) {
1101
- this.logger.error("Failed to persist workflow snapshot", { workflowName, runId, error });
1102
- throw error;
2538
+ await this.service.entities.workflow_snapshot.upsert(data).go();
2539
+ } catch (error$1) {
2540
+ throw new error.MastraError(
2541
+ {
2542
+ id: "STORAGE_DYNAMODB_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
2543
+ domain: error.ErrorDomain.STORAGE,
2544
+ category: error.ErrorCategory.THIRD_PARTY,
2545
+ details: { workflowName, runId }
2546
+ },
2547
+ error$1
2548
+ );
1103
2549
  }
1104
2550
  }
1105
2551
  async loadWorkflowSnapshot({
@@ -1108,7 +2554,7 @@ var DynamoDBStore = class extends storage.MastraStorage {
1108
2554
  }) {
1109
2555
  this.logger.debug("Loading workflow snapshot", { workflowName, runId });
1110
2556
  try {
1111
- const result = await this.service.entities.workflowSnapshot.get({
2557
+ const result = await this.service.entities.workflow_snapshot.get({
1112
2558
  entity: "workflow_snapshot",
1113
2559
  // Add entity type
1114
2560
  workflow_name: workflowName,
@@ -1118,9 +2564,16 @@ var DynamoDBStore = class extends storage.MastraStorage {
1118
2564
  return null;
1119
2565
  }
1120
2566
  return result.data.snapshot;
1121
- } catch (error) {
1122
- this.logger.error("Failed to load workflow snapshot", { workflowName, runId, error });
1123
- throw error;
2567
+ } catch (error$1) {
2568
+ throw new error.MastraError(
2569
+ {
2570
+ id: "STORAGE_DYNAMODB_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
2571
+ domain: error.ErrorDomain.STORAGE,
2572
+ category: error.ErrorCategory.THIRD_PARTY,
2573
+ details: { workflowName, runId }
2574
+ },
2575
+ error$1
2576
+ );
1124
2577
  }
1125
2578
  }
1126
2579
  async getWorkflowRuns(args) {
@@ -1130,14 +2583,14 @@ var DynamoDBStore = class extends storage.MastraStorage {
1130
2583
  const offset = args?.offset || 0;
1131
2584
  let query;
1132
2585
  if (args?.workflowName) {
1133
- query = this.service.entities.workflowSnapshot.query.primary({
2586
+ query = this.service.entities.workflow_snapshot.query.primary({
1134
2587
  entity: "workflow_snapshot",
1135
2588
  // Add entity type
1136
2589
  workflow_name: args.workflowName
1137
2590
  });
1138
2591
  } else {
1139
2592
  this.logger.warn("Performing a scan operation on workflow snapshots - consider using a more specific query");
1140
- query = this.service.entities.workflowSnapshot.scan;
2593
+ query = this.service.entities.workflow_snapshot.scan;
1141
2594
  }
1142
2595
  const allMatchingSnapshots = [];
1143
2596
  let cursor = null;
@@ -1175,28 +2628,38 @@ var DynamoDBStore = class extends storage.MastraStorage {
1175
2628
  }
1176
2629
  const total = allMatchingSnapshots.length;
1177
2630
  const paginatedData = allMatchingSnapshots.slice(offset, offset + limit);
1178
- const runs = paginatedData.map((snapshot) => this.formatWorkflowRun(snapshot));
2631
+ const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
1179
2632
  return {
1180
2633
  runs,
1181
2634
  total
1182
2635
  };
1183
- } catch (error) {
1184
- this.logger.error("Failed to get workflow runs", { error });
1185
- throw error;
2636
+ } catch (error$1) {
2637
+ throw new error.MastraError(
2638
+ {
2639
+ id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2640
+ domain: error.ErrorDomain.STORAGE,
2641
+ category: error.ErrorCategory.THIRD_PARTY,
2642
+ details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
2643
+ },
2644
+ error$1
2645
+ );
1186
2646
  }
1187
2647
  }
1188
2648
  async getWorkflowRunById(args) {
1189
2649
  const { runId, workflowName } = args;
1190
2650
  this.logger.debug("Getting workflow run by ID", { runId, workflowName });
2651
+ console.log("workflowName", workflowName);
2652
+ console.log("runId", runId);
1191
2653
  try {
1192
2654
  if (workflowName) {
1193
2655
  this.logger.debug("WorkflowName provided, using direct GET operation.");
1194
- const result2 = await this.service.entities.workflowSnapshot.get({
2656
+ const result2 = await this.service.entities.workflow_snapshot.get({
1195
2657
  entity: "workflow_snapshot",
1196
2658
  // Entity type for PK
1197
2659
  workflow_name: workflowName,
1198
2660
  run_id: runId
1199
2661
  }).go();
2662
+ console.log("result", result2);
1200
2663
  if (!result2.data) {
1201
2664
  return null;
1202
2665
  }
@@ -1213,7 +2676,7 @@ var DynamoDBStore = class extends storage.MastraStorage {
1213
2676
  this.logger.debug(
1214
2677
  'WorkflowName not provided. Attempting to find workflow run by runId using GSI. Ensure GSI (e.g., "byRunId") is defined on the workflowSnapshot entity with run_id as its key and provisioned in DynamoDB.'
1215
2678
  );
1216
- const result = await this.service.entities.workflowSnapshot.query.gsi2({ entity: "workflow_snapshot", run_id: runId }).go();
2679
+ const result = await this.service.entities.workflow_snapshot.query.gsi2({ entity: "workflow_snapshot", run_id: runId }).go();
1217
2680
  const matchingRunDbItem = result.data && result.data.length > 0 ? result.data[0] : null;
1218
2681
  if (!matchingRunDbItem) {
1219
2682
  return null;
@@ -1227,99 +2690,260 @@ var DynamoDBStore = class extends storage.MastraStorage {
1227
2690
  updatedAt: new Date(matchingRunDbItem.updatedAt),
1228
2691
  resourceId: matchingRunDbItem.resourceId
1229
2692
  };
1230
- } catch (error) {
1231
- this.logger.error("Failed to get workflow run by ID", { runId, workflowName, error });
1232
- throw error;
2693
+ } catch (error$1) {
2694
+ throw new error.MastraError(
2695
+ {
2696
+ id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
2697
+ domain: error.ErrorDomain.STORAGE,
2698
+ category: error.ErrorCategory.THIRD_PARTY,
2699
+ details: { runId, workflowName: args?.workflowName || "" }
2700
+ },
2701
+ error$1
2702
+ );
1233
2703
  }
1234
2704
  }
1235
- // Helper function to format workflow run
1236
- formatWorkflowRun(snapshotData) {
1237
- return {
1238
- workflowName: snapshotData.workflow_name,
1239
- runId: snapshotData.run_id,
1240
- snapshot: snapshotData.snapshot,
1241
- createdAt: new Date(snapshotData.createdAt),
1242
- updatedAt: new Date(snapshotData.updatedAt),
1243
- resourceId: snapshotData.resourceId
1244
- };
2705
+ };
2706
+
2707
+ // src/storage/index.ts
2708
+ var DynamoDBStore = class extends storage.MastraStorage {
2709
+ tableName;
2710
+ client;
2711
+ service;
2712
+ hasInitialized = null;
2713
+ stores;
2714
+ constructor({ name, config }) {
2715
+ super({ name });
2716
+ try {
2717
+ if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
2718
+ throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
2719
+ }
2720
+ if (!/^[a-zA-Z0-9_.-]{3,255}$/.test(config.tableName)) {
2721
+ throw new Error(
2722
+ `DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`
2723
+ );
2724
+ }
2725
+ const dynamoClient = new clientDynamodb.DynamoDBClient({
2726
+ region: config.region || "us-east-1",
2727
+ endpoint: config.endpoint,
2728
+ credentials: config.credentials
2729
+ });
2730
+ this.tableName = config.tableName;
2731
+ this.client = libDynamodb.DynamoDBDocumentClient.from(dynamoClient);
2732
+ this.service = getElectroDbService(this.client, this.tableName);
2733
+ const operations = new StoreOperationsDynamoDB({
2734
+ service: this.service,
2735
+ tableName: this.tableName,
2736
+ client: this.client
2737
+ });
2738
+ const traces = new TracesStorageDynamoDB({ service: this.service, operations });
2739
+ const workflows = new WorkflowStorageDynamoDB({ service: this.service });
2740
+ const memory = new MemoryStorageDynamoDB({ service: this.service });
2741
+ const scores = new ScoresStorageDynamoDB({ service: this.service });
2742
+ this.stores = {
2743
+ operations,
2744
+ legacyEvals: new LegacyEvalsDynamoDB({ service: this.service, tableName: this.tableName }),
2745
+ traces,
2746
+ workflows,
2747
+ memory,
2748
+ scores
2749
+ };
2750
+ } catch (error$1) {
2751
+ throw new error.MastraError(
2752
+ {
2753
+ id: "STORAGE_DYNAMODB_STORE_CONSTRUCTOR_FAILED",
2754
+ domain: error.ErrorDomain.STORAGE,
2755
+ category: error.ErrorCategory.USER
2756
+ },
2757
+ error$1
2758
+ );
2759
+ }
1245
2760
  }
1246
- // Helper methods for entity/table mapping
1247
- getEntityNameForTable(tableName) {
1248
- const mapping = {
1249
- [storage.TABLE_THREADS]: "thread",
1250
- [storage.TABLE_MESSAGES]: "message",
1251
- [storage.TABLE_WORKFLOW_SNAPSHOT]: "workflowSnapshot",
1252
- [storage.TABLE_EVALS]: "eval",
1253
- [storage.TABLE_TRACES]: "trace",
1254
- [storage.TABLE_RESOURCES]: "resource"
2761
+ get supports() {
2762
+ return {
2763
+ selectByIncludeResourceScope: true,
2764
+ resourceWorkingMemory: true,
2765
+ hasColumn: false,
2766
+ createTable: false,
2767
+ deleteMessages: false
1255
2768
  };
1256
- return mapping[tableName] || null;
1257
2769
  }
1258
- // Eval operations
1259
- async getEvalsByAgentName(agentName, type) {
1260
- this.logger.debug("Getting evals for agent", { agentName, type });
2770
+ /**
2771
+ * Validates that the required DynamoDB table exists and is accessible.
2772
+ * This does not check the table structure - it assumes the table
2773
+ * was created with the correct structure via CDK/CloudFormation.
2774
+ */
2775
+ async validateTableExists() {
1261
2776
  try {
1262
- const query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
1263
- const results = await query.go({ order: "desc", limit: 100 });
1264
- if (!results.data.length) {
1265
- return [];
1266
- }
1267
- let filteredData = results.data;
1268
- if (type) {
1269
- filteredData = filteredData.filter((evalRecord) => {
1270
- try {
1271
- const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
1272
- if (type === "test" && !testInfo) {
1273
- return false;
1274
- }
1275
- if (type === "live" && testInfo) {
1276
- return false;
1277
- }
1278
- } catch (e) {
1279
- this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
1280
- }
1281
- return true;
1282
- });
1283
- }
1284
- return filteredData.map((evalRecord) => {
1285
- try {
1286
- return {
1287
- input: evalRecord.input,
1288
- output: evalRecord.output,
1289
- // Safely parse result and test_info
1290
- result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
1291
- agentName: evalRecord.agent_name,
1292
- createdAt: evalRecord.created_at,
1293
- // Keep as string from DDB?
1294
- metricName: evalRecord.metric_name,
1295
- instructions: evalRecord.instructions,
1296
- runId: evalRecord.run_id,
1297
- globalRunId: evalRecord.global_run_id,
1298
- testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
1299
- };
1300
- } catch (parseError) {
1301
- this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
1302
- return {
1303
- agentName: evalRecord.agent_name,
1304
- createdAt: evalRecord.created_at,
1305
- runId: evalRecord.run_id,
1306
- globalRunId: evalRecord.global_run_id
1307
- };
1308
- }
2777
+ const command = new clientDynamodb.DescribeTableCommand({
2778
+ TableName: this.tableName
1309
2779
  });
1310
- } catch (error) {
1311
- this.logger.error("Failed to get evals by agent name", { agentName, type, error });
1312
- throw error;
2780
+ await this.client.send(command);
2781
+ return true;
2782
+ } catch (error$1) {
2783
+ if (error$1.name === "ResourceNotFoundException") {
2784
+ return false;
2785
+ }
2786
+ throw new error.MastraError(
2787
+ {
2788
+ id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
2789
+ domain: error.ErrorDomain.STORAGE,
2790
+ category: error.ErrorCategory.THIRD_PARTY,
2791
+ details: { tableName: this.tableName }
2792
+ },
2793
+ error$1
2794
+ );
1313
2795
  }
1314
2796
  }
2797
+ /**
2798
+ * Initialize storage, validating the externally managed table is accessible.
2799
+ * For the single-table design, we only validate once that we can access
2800
+ * the table that was created via CDK/CloudFormation.
2801
+ */
2802
+ async init() {
2803
+ if (this.hasInitialized === null) {
2804
+ this.hasInitialized = this._performInitializationAndStore();
2805
+ }
2806
+ try {
2807
+ await this.hasInitialized;
2808
+ } catch (error$1) {
2809
+ throw new error.MastraError(
2810
+ {
2811
+ id: "STORAGE_DYNAMODB_STORE_INIT_FAILED",
2812
+ domain: error.ErrorDomain.STORAGE,
2813
+ category: error.ErrorCategory.THIRD_PARTY,
2814
+ details: { tableName: this.tableName }
2815
+ },
2816
+ error$1
2817
+ );
2818
+ }
2819
+ }
2820
+ /**
2821
+ * Performs the actual table validation and stores the promise.
2822
+ * Handles resetting the stored promise on failure to allow retries.
2823
+ */
2824
+ _performInitializationAndStore() {
2825
+ return this.validateTableExists().then((exists) => {
2826
+ if (!exists) {
2827
+ throw new Error(
2828
+ `Table ${this.tableName} does not exist or is not accessible. Ensure it's created via CDK/CloudFormation before using this store.`
2829
+ );
2830
+ }
2831
+ return true;
2832
+ }).catch((err) => {
2833
+ this.hasInitialized = null;
2834
+ throw err;
2835
+ });
2836
+ }
2837
+ async createTable({ tableName, schema }) {
2838
+ return this.stores.operations.createTable({ tableName, schema });
2839
+ }
2840
+ async alterTable(_args) {
2841
+ return this.stores.operations.alterTable(_args);
2842
+ }
2843
+ async clearTable({ tableName }) {
2844
+ return this.stores.operations.clearTable({ tableName });
2845
+ }
2846
+ async dropTable({ tableName }) {
2847
+ return this.stores.operations.dropTable({ tableName });
2848
+ }
2849
+ async insert({ tableName, record }) {
2850
+ return this.stores.operations.insert({ tableName, record });
2851
+ }
2852
+ async batchInsert({ tableName, records }) {
2853
+ return this.stores.operations.batchInsert({ tableName, records });
2854
+ }
2855
+ async load({ tableName, keys }) {
2856
+ return this.stores.operations.load({ tableName, keys });
2857
+ }
2858
+ // Thread operations
2859
+ async getThreadById({ threadId }) {
2860
+ return this.stores.memory.getThreadById({ threadId });
2861
+ }
2862
+ async getThreadsByResourceId({ resourceId }) {
2863
+ return this.stores.memory.getThreadsByResourceId({ resourceId });
2864
+ }
2865
+ async saveThread({ thread }) {
2866
+ return this.stores.memory.saveThread({ thread });
2867
+ }
2868
+ async updateThread({
2869
+ id,
2870
+ title,
2871
+ metadata
2872
+ }) {
2873
+ return this.stores.memory.updateThread({ id, title, metadata });
2874
+ }
2875
+ async deleteThread({ threadId }) {
2876
+ return this.stores.memory.deleteThread({ threadId });
2877
+ }
2878
+ async getMessages({
2879
+ threadId,
2880
+ resourceId,
2881
+ selectBy,
2882
+ format
2883
+ }) {
2884
+ return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
2885
+ }
2886
+ async saveMessages(args) {
2887
+ return this.stores.memory.saveMessages(args);
2888
+ }
2889
+ async getThreadsByResourceIdPaginated(args) {
2890
+ return this.stores.memory.getThreadsByResourceIdPaginated(args);
2891
+ }
2892
+ async getMessagesPaginated(args) {
2893
+ return this.stores.memory.getMessagesPaginated(args);
2894
+ }
2895
+ async updateMessages(_args) {
2896
+ return this.stores.memory.updateMessages(_args);
2897
+ }
2898
+ // Trace operations
2899
+ async getTraces(args) {
2900
+ return this.stores.traces.getTraces(args);
2901
+ }
2902
+ async batchTraceInsert({ records }) {
2903
+ return this.stores.traces.batchTraceInsert({ records });
2904
+ }
1315
2905
  async getTracesPaginated(_args) {
1316
- throw new Error("Method not implemented.");
2906
+ return this.stores.traces.getTracesPaginated(_args);
2907
+ }
2908
+ // Workflow operations
2909
+ async persistWorkflowSnapshot({
2910
+ workflowName,
2911
+ runId,
2912
+ snapshot
2913
+ }) {
2914
+ return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
2915
+ }
2916
+ async loadWorkflowSnapshot({
2917
+ workflowName,
2918
+ runId
2919
+ }) {
2920
+ return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
2921
+ }
2922
+ async getWorkflowRuns(args) {
2923
+ return this.stores.workflows.getWorkflowRuns(args);
2924
+ }
2925
+ async getWorkflowRunById(args) {
2926
+ return this.stores.workflows.getWorkflowRunById(args);
2927
+ }
2928
+ async getResourceById({ resourceId }) {
2929
+ return this.stores.memory.getResourceById({ resourceId });
2930
+ }
2931
+ async saveResource({ resource }) {
2932
+ return this.stores.memory.saveResource({ resource });
2933
+ }
2934
+ async updateResource({
2935
+ resourceId,
2936
+ workingMemory,
2937
+ metadata
2938
+ }) {
2939
+ return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
1317
2940
  }
1318
- async getThreadsByResourceIdPaginated(_args) {
1319
- throw new Error("Method not implemented.");
2941
+ // Eval operations
2942
+ async getEvalsByAgentName(agentName, type) {
2943
+ return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
1320
2944
  }
1321
- async getMessagesPaginated(_args) {
1322
- throw new Error("Method not implemented.");
2945
+ async getEvals(options) {
2946
+ return this.stores.legacyEvals.getEvals(options);
1323
2947
  }
1324
2948
  /**
1325
2949
  * Closes the DynamoDB client connection and cleans up resources.
@@ -1330,15 +2954,51 @@ var DynamoDBStore = class extends storage.MastraStorage {
1330
2954
  try {
1331
2955
  this.client.destroy();
1332
2956
  this.logger.debug("DynamoDB client closed successfully for store:", { name: this.name });
1333
- } catch (error) {
1334
- this.logger.error("Error closing DynamoDB client for store:", { name: this.name, error });
1335
- throw error;
2957
+ } catch (error$1) {
2958
+ throw new error.MastraError(
2959
+ {
2960
+ id: "STORAGE_DYNAMODB_STORE_CLOSE_FAILED",
2961
+ domain: error.ErrorDomain.STORAGE,
2962
+ category: error.ErrorCategory.THIRD_PARTY
2963
+ },
2964
+ error$1
2965
+ );
1336
2966
  }
1337
2967
  }
1338
- async updateMessages(_args) {
1339
- this.logger.error("updateMessages is not yet implemented in DynamoDBStore");
1340
- throw new Error("Method not implemented");
2968
+ /**
2969
+ * SCORERS - Not implemented
2970
+ */
2971
+ async getScoreById({ id: _id }) {
2972
+ return this.stores.scores.getScoreById({ id: _id });
2973
+ }
2974
+ async saveScore(_score) {
2975
+ return this.stores.scores.saveScore(_score);
2976
+ }
2977
+ async getScoresByRunId({
2978
+ runId: _runId,
2979
+ pagination: _pagination
2980
+ }) {
2981
+ return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
2982
+ }
2983
+ async getScoresByEntityId({
2984
+ entityId: _entityId,
2985
+ entityType: _entityType,
2986
+ pagination: _pagination
2987
+ }) {
2988
+ return this.stores.scores.getScoresByEntityId({
2989
+ entityId: _entityId,
2990
+ entityType: _entityType,
2991
+ pagination: _pagination
2992
+ });
2993
+ }
2994
+ async getScoresByScorerId({
2995
+ scorerId: _scorerId,
2996
+ pagination: _pagination
2997
+ }) {
2998
+ return this.stores.scores.getScoresByScorerId({ scorerId: _scorerId, pagination: _pagination });
1341
2999
  }
1342
3000
  };
1343
3001
 
1344
3002
  exports.DynamoDBStore = DynamoDBStore;
3003
+ //# sourceMappingURL=index.cjs.map
3004
+ //# sourceMappingURL=index.cjs.map