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