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