@mastra/dynamodb 0.0.0-pass-headers-for-create-mastra-client-20250530010057 → 0.0.0-rag-chunk-extract-llm-option-20250926183645

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