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