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