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