@mastra/dynamodb 0.10.0 → 0.10.1-alpha.1
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/dist/index.cjs +28 -11
- package/dist/index.js +28 -11
- package/package.json +4 -4
- package/src/storage/index.test.ts +32 -5
- package/src/storage/index.ts +38 -15
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var clientDynamodb = require('@aws-sdk/client-dynamodb');
|
|
4
4
|
var libDynamodb = require('@aws-sdk/lib-dynamodb');
|
|
5
|
+
var agent = require('@mastra/core/agent');
|
|
5
6
|
var storage = require('@mastra/core/storage');
|
|
6
7
|
var electrodb = require('electrodb');
|
|
7
8
|
|
|
@@ -890,24 +891,38 @@ var DynamoDBStore = class extends storage.MastraStorage {
|
|
|
890
891
|
throw error;
|
|
891
892
|
}
|
|
892
893
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
894
|
+
async getMessages({
|
|
895
|
+
threadId,
|
|
896
|
+
resourceId,
|
|
897
|
+
selectBy,
|
|
898
|
+
format
|
|
899
|
+
}) {
|
|
896
900
|
this.logger.debug("Getting messages", { threadId, selectBy });
|
|
897
901
|
try {
|
|
898
902
|
const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
|
|
899
903
|
if (selectBy?.last && typeof selectBy.last === "number") {
|
|
900
904
|
const results2 = await query.go({ limit: selectBy.last, reverse: true });
|
|
901
|
-
|
|
905
|
+
const list2 = new agent.MessageList({ threadId, resourceId }).add(
|
|
906
|
+
results2.data.map((data) => this.parseMessageData(data)),
|
|
907
|
+
"memory"
|
|
908
|
+
);
|
|
909
|
+
if (format === `v2`) return list2.get.all.mastra();
|
|
910
|
+
return list2.get.all.v1();
|
|
902
911
|
}
|
|
903
912
|
const results = await query.go();
|
|
904
|
-
|
|
913
|
+
const list = new agent.MessageList({ threadId, resourceId }).add(
|
|
914
|
+
results.data.map((data) => this.parseMessageData(data)),
|
|
915
|
+
"memory"
|
|
916
|
+
);
|
|
917
|
+
if (format === `v2`) return list.get.all.mastra();
|
|
918
|
+
return list.get.all.v1();
|
|
905
919
|
} catch (error) {
|
|
906
920
|
this.logger.error("Failed to get messages", { threadId, error });
|
|
907
921
|
throw error;
|
|
908
922
|
}
|
|
909
923
|
}
|
|
910
|
-
async saveMessages(
|
|
924
|
+
async saveMessages(args) {
|
|
925
|
+
const { messages, format = "v1" } = args;
|
|
911
926
|
this.logger.debug("Saving messages", { count: messages.length });
|
|
912
927
|
if (!messages.length) {
|
|
913
928
|
return [];
|
|
@@ -924,10 +939,10 @@ var DynamoDBStore = class extends storage.MastraStorage {
|
|
|
924
939
|
resourceId: msg.resourceId,
|
|
925
940
|
// Ensure complex fields are stringified if not handled by attribute setters
|
|
926
941
|
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
|
|
927
|
-
toolCallArgs: msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
|
|
928
|
-
toolCallIds: msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
|
|
929
|
-
toolNames: msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
|
|
930
|
-
createdAt: msg.createdAt
|
|
942
|
+
toolCallArgs: `toolCallArgs` in msg && msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
|
|
943
|
+
toolCallIds: `toolCallIds` in msg && msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
|
|
944
|
+
toolNames: `toolNames` in msg && msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
|
|
945
|
+
createdAt: msg.createdAt instanceof Date ? msg.createdAt.toISOString() : msg.createdAt || now,
|
|
931
946
|
updatedAt: now
|
|
932
947
|
// Add updatedAt
|
|
933
948
|
};
|
|
@@ -948,7 +963,9 @@ var DynamoDBStore = class extends storage.MastraStorage {
|
|
|
948
963
|
await this.service.entities.message.create(messageData).go();
|
|
949
964
|
}
|
|
950
965
|
}
|
|
951
|
-
|
|
966
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
967
|
+
if (format === `v1`) return list.get.all.v1();
|
|
968
|
+
return list.get.all.mastra();
|
|
952
969
|
} catch (error) {
|
|
953
970
|
this.logger.error("Failed to save messages", { error });
|
|
954
971
|
throw error;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
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';
|
|
3
4
|
import { MastraStorage, TABLE_TRACES, TABLE_EVALS, TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
|
|
4
5
|
import { Entity, Service } from 'electrodb';
|
|
5
6
|
|
|
@@ -888,24 +889,38 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
888
889
|
throw error;
|
|
889
890
|
}
|
|
890
891
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
892
|
+
async getMessages({
|
|
893
|
+
threadId,
|
|
894
|
+
resourceId,
|
|
895
|
+
selectBy,
|
|
896
|
+
format
|
|
897
|
+
}) {
|
|
894
898
|
this.logger.debug("Getting messages", { threadId, selectBy });
|
|
895
899
|
try {
|
|
896
900
|
const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
|
|
897
901
|
if (selectBy?.last && typeof selectBy.last === "number") {
|
|
898
902
|
const results2 = await query.go({ limit: selectBy.last, reverse: true });
|
|
899
|
-
|
|
903
|
+
const list2 = new MessageList({ threadId, resourceId }).add(
|
|
904
|
+
results2.data.map((data) => this.parseMessageData(data)),
|
|
905
|
+
"memory"
|
|
906
|
+
);
|
|
907
|
+
if (format === `v2`) return list2.get.all.mastra();
|
|
908
|
+
return list2.get.all.v1();
|
|
900
909
|
}
|
|
901
910
|
const results = await query.go();
|
|
902
|
-
|
|
911
|
+
const list = new MessageList({ threadId, resourceId }).add(
|
|
912
|
+
results.data.map((data) => this.parseMessageData(data)),
|
|
913
|
+
"memory"
|
|
914
|
+
);
|
|
915
|
+
if (format === `v2`) return list.get.all.mastra();
|
|
916
|
+
return list.get.all.v1();
|
|
903
917
|
} catch (error) {
|
|
904
918
|
this.logger.error("Failed to get messages", { threadId, error });
|
|
905
919
|
throw error;
|
|
906
920
|
}
|
|
907
921
|
}
|
|
908
|
-
async saveMessages(
|
|
922
|
+
async saveMessages(args) {
|
|
923
|
+
const { messages, format = "v1" } = args;
|
|
909
924
|
this.logger.debug("Saving messages", { count: messages.length });
|
|
910
925
|
if (!messages.length) {
|
|
911
926
|
return [];
|
|
@@ -922,10 +937,10 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
922
937
|
resourceId: msg.resourceId,
|
|
923
938
|
// Ensure complex fields are stringified if not handled by attribute setters
|
|
924
939
|
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
|
|
925
|
-
toolCallArgs: msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
|
|
926
|
-
toolCallIds: msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
|
|
927
|
-
toolNames: msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
|
|
928
|
-
createdAt: msg.createdAt
|
|
940
|
+
toolCallArgs: `toolCallArgs` in msg && msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
|
|
941
|
+
toolCallIds: `toolCallIds` in msg && msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
|
|
942
|
+
toolNames: `toolNames` in msg && msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
|
|
943
|
+
createdAt: msg.createdAt instanceof Date ? msg.createdAt.toISOString() : msg.createdAt || now,
|
|
929
944
|
updatedAt: now
|
|
930
945
|
// Add updatedAt
|
|
931
946
|
};
|
|
@@ -946,7 +961,9 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
946
961
|
await this.service.entities.message.create(messageData).go();
|
|
947
962
|
}
|
|
948
963
|
}
|
|
949
|
-
|
|
964
|
+
const list = new MessageList().add(messages, "memory");
|
|
965
|
+
if (format === `v1`) return list.get.all.v1();
|
|
966
|
+
return list.get.all.mastra();
|
|
950
967
|
} catch (error) {
|
|
951
968
|
this.logger.error("Failed to save messages", { error });
|
|
952
969
|
throw error;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/dynamodb",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1-alpha.1",
|
|
4
4
|
"description": "DynamoDB storage adapter for Mastra",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"electrodb": "^3.4.1"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"@mastra/core": "^0.10.0"
|
|
18
|
+
"@mastra/core": "^0.10.0-alpha.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@microsoft/api-extractor": "^7.52.1",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"tsup": "^8.4.0",
|
|
28
28
|
"typescript": "^5.8.2",
|
|
29
29
|
"vitest": "^3.0.9",
|
|
30
|
-
"@internal/lint": "0.0.
|
|
31
|
-
"@mastra/core": "0.10.
|
|
30
|
+
"@internal/lint": "0.0.7",
|
|
31
|
+
"@mastra/core": "0.10.2-alpha.2"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "tsup src/index.ts --format esm,cjs --clean --treeshake=smallest --splitting",
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
waitUntilTableExists,
|
|
12
12
|
waitUntilTableNotExists,
|
|
13
13
|
} from '@aws-sdk/client-dynamodb';
|
|
14
|
-
import type {
|
|
14
|
+
import type { MastraMessageV1, StorageThreadType, WorkflowRun, WorkflowRunState } from '@mastra/core';
|
|
15
|
+
import type { MastraMessageV2 } from '@mastra/core/agent';
|
|
15
16
|
import { TABLE_EVALS, TABLE_THREADS, TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
|
|
16
17
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from 'vitest';
|
|
17
18
|
import { DynamoDBStore } from '..';
|
|
@@ -388,17 +389,17 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
388
389
|
});
|
|
389
390
|
|
|
390
391
|
describe('Batch Operations', () => {
|
|
391
|
-
test('should handle batch message inserts efficiently (up to 25 items)', async () => {
|
|
392
|
+
test('should handle batch message inserts efficiently (up to 25 items) [v1 storage]', async () => {
|
|
392
393
|
const startTime = Date.now(); // Get a base time
|
|
393
394
|
const threadId = 'batch-thread';
|
|
394
|
-
const messages:
|
|
395
|
+
const messages: MastraMessageV1[] = Array.from({ length: 25 }, (_, i) => ({
|
|
395
396
|
id: `msg-${i}`,
|
|
396
397
|
threadId,
|
|
397
398
|
resourceId: 'test-resource',
|
|
398
399
|
content: `Message ${i}`,
|
|
399
400
|
// Increment timestamp slightly for each message to ensure order
|
|
400
401
|
createdAt: new Date(startTime + i),
|
|
401
|
-
role: 'user',
|
|
402
|
+
role: i % 2 === 0 ? 'user' : 'assistant',
|
|
402
403
|
type: 'text',
|
|
403
404
|
}));
|
|
404
405
|
|
|
@@ -412,10 +413,36 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
412
413
|
expect(retrieved[24]?.content).toBe('Message 24');
|
|
413
414
|
});
|
|
414
415
|
|
|
416
|
+
test('should handle batch message inserts efficiently (up to 25 items) [v2 storage]', async () => {
|
|
417
|
+
const startTime = Date.now(); // Get a base time
|
|
418
|
+
const threadId = 'batch-thread';
|
|
419
|
+
const messages: MastraMessageV2[] = Array.from({ length: 25 }, (_, i) => ({
|
|
420
|
+
id: `msg-${i}`,
|
|
421
|
+
threadId,
|
|
422
|
+
resourceId: 'test-resource',
|
|
423
|
+
content: { format: 2, parts: [{ type: 'text', text: `Message ${i}` }] },
|
|
424
|
+
// Increment timestamp slightly for each message to ensure order
|
|
425
|
+
createdAt: new Date(startTime + i),
|
|
426
|
+
role: i % 2 === 0 ? 'user' : 'assistant',
|
|
427
|
+
type: 'text',
|
|
428
|
+
}));
|
|
429
|
+
|
|
430
|
+
// Assuming saveMessages uses BatchWriteItem internally
|
|
431
|
+
await expect(store.saveMessages({ messages, format: 'v2' })).resolves.not.toThrow();
|
|
432
|
+
|
|
433
|
+
const retrieved = await store.getMessages({ threadId, format: 'v2' });
|
|
434
|
+
expect(retrieved).toHaveLength(25);
|
|
435
|
+
// Now the order should be guaranteed by the ascending createdAt timestamp
|
|
436
|
+
if (retrieved[0]?.content?.parts[0]?.type !== `text`) throw new Error(`Expected text part`);
|
|
437
|
+
expect(retrieved[0].content.parts[0].text).toBe('Message 0');
|
|
438
|
+
if (retrieved[24]?.content?.parts?.[0]?.type !== `text`) throw new Error(`Expected text part`);
|
|
439
|
+
expect(retrieved[24].content.parts[0].text).toBe('Message 24');
|
|
440
|
+
});
|
|
441
|
+
|
|
415
442
|
test('should handle batch inserts exceeding 25 items (if saveMessages chunks)', async () => {
|
|
416
443
|
const startTime = Date.now(); // Get a base time
|
|
417
444
|
const threadId = 'batch-thread-large';
|
|
418
|
-
const messages:
|
|
445
|
+
const messages: MastraMessageV1[] = Array.from({ length: 30 }, (_, i) => ({
|
|
419
446
|
id: `msg-large-${i}`,
|
|
420
447
|
threadId,
|
|
421
448
|
resourceId: 'test-resource-large',
|
package/src/storage/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DynamoDBClient, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
|
|
2
2
|
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
|
|
3
|
-
import type { StorageThreadType,
|
|
3
|
+
import type { StorageThreadType, WorkflowRunState, MastraMessageV1 } from '@mastra/core';
|
|
4
|
+
import type { MastraMessageV2 } from '@mastra/core/agent';
|
|
5
|
+
import { MessageList } from '@mastra/core/agent';
|
|
4
6
|
import {
|
|
5
7
|
MastraStorage,
|
|
6
8
|
TABLE_THREADS,
|
|
@@ -514,8 +516,14 @@ export class DynamoDBStore extends MastraStorage {
|
|
|
514
516
|
}
|
|
515
517
|
|
|
516
518
|
// Message operations
|
|
517
|
-
async getMessages(args: StorageGetMessagesArg): Promise<
|
|
518
|
-
|
|
519
|
+
public async getMessages(args: StorageGetMessagesArg & { format?: 'v1' }): Promise<MastraMessageV1[]>;
|
|
520
|
+
public async getMessages(args: StorageGetMessagesArg & { format: 'v2' }): Promise<MastraMessageV2[]>;
|
|
521
|
+
public async getMessages({
|
|
522
|
+
threadId,
|
|
523
|
+
resourceId,
|
|
524
|
+
selectBy,
|
|
525
|
+
format,
|
|
526
|
+
}: StorageGetMessagesArg & { format?: 'v1' | 'v2' }): Promise<MastraMessageV1[] | MastraMessageV2[]> {
|
|
519
527
|
this.logger.debug('Getting messages', { threadId, selectBy });
|
|
520
528
|
|
|
521
529
|
try {
|
|
@@ -530,21 +538,34 @@ export class DynamoDBStore extends MastraStorage {
|
|
|
530
538
|
// Assuming default sort is ascending on SK, use reverse: true for descending
|
|
531
539
|
const results = await query.go({ limit: selectBy.last, reverse: true });
|
|
532
540
|
// Use arrow function in map to preserve 'this' context for parseMessageData
|
|
533
|
-
|
|
541
|
+
const list = new MessageList({ threadId, resourceId }).add(
|
|
542
|
+
results.data.map((data: any) => this.parseMessageData(data)),
|
|
543
|
+
'memory',
|
|
544
|
+
);
|
|
545
|
+
if (format === `v2`) return list.get.all.mastra();
|
|
546
|
+
return list.get.all.v1();
|
|
534
547
|
}
|
|
535
548
|
|
|
536
549
|
// If no limit specified, get all messages (potentially paginated by ElectroDB)
|
|
537
550
|
// Consider adding default limit or handling pagination if needed
|
|
538
551
|
const results = await query.go();
|
|
539
|
-
|
|
540
|
-
|
|
552
|
+
const list = new MessageList({ threadId, resourceId }).add(
|
|
553
|
+
results.data.map((data: any) => this.parseMessageData(data)),
|
|
554
|
+
'memory',
|
|
555
|
+
);
|
|
556
|
+
if (format === `v2`) return list.get.all.mastra();
|
|
557
|
+
return list.get.all.v1();
|
|
541
558
|
} catch (error) {
|
|
542
559
|
this.logger.error('Failed to get messages', { threadId, error });
|
|
543
560
|
throw error;
|
|
544
561
|
}
|
|
545
562
|
}
|
|
546
|
-
|
|
547
|
-
async saveMessages(
|
|
563
|
+
async saveMessages(args: { messages: MastraMessageV1[]; format?: undefined | 'v1' }): Promise<MastraMessageV1[]>;
|
|
564
|
+
async saveMessages(args: { messages: MastraMessageV2[]; format: 'v2' }): Promise<MastraMessageV2[]>;
|
|
565
|
+
async saveMessages(
|
|
566
|
+
args: { messages: MastraMessageV1[]; format?: undefined | 'v1' } | { messages: MastraMessageV2[]; format: 'v2' },
|
|
567
|
+
): Promise<MastraMessageV2[] | MastraMessageV1[]> {
|
|
568
|
+
const { messages, format = 'v1' } = args;
|
|
548
569
|
this.logger.debug('Saving messages', { count: messages.length });
|
|
549
570
|
|
|
550
571
|
if (!messages.length) {
|
|
@@ -563,10 +584,10 @@ export class DynamoDBStore extends MastraStorage {
|
|
|
563
584
|
resourceId: msg.resourceId,
|
|
564
585
|
// Ensure complex fields are stringified if not handled by attribute setters
|
|
565
586
|
content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
|
|
566
|
-
toolCallArgs: msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : undefined,
|
|
567
|
-
toolCallIds: msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : undefined,
|
|
568
|
-
toolNames: msg.toolNames ? JSON.stringify(msg.toolNames) : undefined,
|
|
569
|
-
createdAt: msg.createdAt
|
|
587
|
+
toolCallArgs: `toolCallArgs` in msg && msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : undefined,
|
|
588
|
+
toolCallIds: `toolCallIds` in msg && msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : undefined,
|
|
589
|
+
toolNames: `toolNames` in msg && msg.toolNames ? JSON.stringify(msg.toolNames) : undefined,
|
|
590
|
+
createdAt: msg.createdAt instanceof Date ? msg.createdAt.toISOString() : msg.createdAt || now,
|
|
570
591
|
updatedAt: now, // Add updatedAt
|
|
571
592
|
};
|
|
572
593
|
});
|
|
@@ -595,7 +616,9 @@ export class DynamoDBStore extends MastraStorage {
|
|
|
595
616
|
// Original batch call: await this.service.entities.message.create(batch).go();
|
|
596
617
|
}
|
|
597
618
|
|
|
598
|
-
|
|
619
|
+
const list = new MessageList().add(messages, 'memory');
|
|
620
|
+
if (format === `v1`) return list.get.all.v1();
|
|
621
|
+
return list.get.all.mastra();
|
|
599
622
|
} catch (error) {
|
|
600
623
|
this.logger.error('Failed to save messages', { error });
|
|
601
624
|
throw error;
|
|
@@ -603,7 +626,7 @@ export class DynamoDBStore extends MastraStorage {
|
|
|
603
626
|
}
|
|
604
627
|
|
|
605
628
|
// Helper function to parse message data (handle JSON fields)
|
|
606
|
-
private parseMessageData(data: any):
|
|
629
|
+
private parseMessageData(data: any): MastraMessageV2 | MastraMessageV1 {
|
|
607
630
|
// Removed try/catch and JSON.parse logic - now handled by entity 'get' attributes
|
|
608
631
|
// This function now primarily ensures correct typing and Date conversion.
|
|
609
632
|
return {
|
|
@@ -613,7 +636,7 @@ export class DynamoDBStore extends MastraStorage {
|
|
|
613
636
|
updatedAt: data.updatedAt ? new Date(data.updatedAt) : undefined,
|
|
614
637
|
// Other fields like content, toolCallArgs etc. are assumed to be correctly
|
|
615
638
|
// transformed by the ElectroDB entity getters.
|
|
616
|
-
}
|
|
639
|
+
};
|
|
617
640
|
}
|
|
618
641
|
|
|
619
642
|
// Trace operations
|