@mastra/dynamodb 0.0.0-support-d1-client-20250701191943 → 0.0.0-taofeeq-fix-tool-call-showing-after-message-20250806162745

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