@mastra/dynamodb 0.0.0-support-d1-client-20250701191943 → 0.0.0-suspendRuntimeContextTypeFix-20250930142630

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