@mastra/dynamodb 0.0.0-error-handler-fix-20251020202607 → 0.0.0-execa-dynamic-import-20260304221256
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 +1442 -3
- package/LICENSE.md +15 -0
- package/README.md +1 -2
- package/dist/docs/SKILL.md +22 -0
- package/dist/docs/assets/SOURCE_MAP.json +6 -0
- package/dist/docs/references/reference-storage-dynamodb.md +282 -0
- package/dist/entities/eval.d.ts +8 -0
- package/dist/entities/eval.d.ts.map +1 -1
- package/dist/entities/index.d.ts +66 -5
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/message.d.ts +8 -0
- package/dist/entities/message.d.ts.map +1 -1
- package/dist/entities/resource.d.ts +8 -0
- package/dist/entities/resource.d.ts.map +1 -1
- package/dist/entities/score.d.ts +18 -5
- package/dist/entities/score.d.ts.map +1 -1
- package/dist/entities/thread.d.ts +8 -0
- package/dist/entities/thread.d.ts.map +1 -1
- package/dist/entities/trace.d.ts +8 -0
- package/dist/entities/trace.d.ts.map +1 -1
- package/dist/entities/utils.d.ts +90 -0
- package/dist/entities/utils.d.ts.map +1 -1
- package/dist/entities/workflow-snapshot.d.ts +8 -0
- package/dist/entities/workflow-snapshot.d.ts.map +1 -1
- package/dist/index.cjs +786 -1269
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +780 -1270
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +48 -0
- package/dist/storage/db/index.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +18 -45
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +47 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -0
- package/dist/storage/domains/utils.d.ts +7 -0
- package/dist/storage/domains/utils.d.ts.map +1 -0
- package/dist/storage/domains/workflows/index.d.ts +26 -24
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +177 -221
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/ttl.d.ts +52 -0
- package/dist/storage/ttl.d.ts.map +1 -0
- package/package.json +17 -16
- package/dist/storage/domains/legacy-evals/index.d.ts +0 -19
- package/dist/storage/domains/legacy-evals/index.d.ts.map +0 -1
- package/dist/storage/domains/operations/index.d.ts +0 -69
- package/dist/storage/domains/operations/index.d.ts.map +0 -1
- package/dist/storage/domains/score/index.d.ts +0 -51
- package/dist/storage/domains/score/index.d.ts.map +0 -1
- package/dist/storage/domains/traces/index.d.ts +0 -28
- package/dist/storage/domains/traces/index.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { DynamoDBClient, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
|
|
2
2
|
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
|
|
3
3
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
4
|
-
import {
|
|
4
|
+
import { MemoryStorage, createStorageErrorId, normalizePerPage, calculatePagination, filterByDateRange, ScoresStorage, SCORERS_SCHEMA, WorkflowsStorage, MastraCompositeStore, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_RESOURCES, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
|
|
5
5
|
import { Entity, Service } from 'electrodb';
|
|
6
6
|
import { MessageList } from '@mastra/core/agent';
|
|
7
|
-
import { saveScorePayloadSchema } from '@mastra/core/
|
|
7
|
+
import { saveScorePayloadSchema } from '@mastra/core/evals';
|
|
8
8
|
|
|
9
9
|
// src/storage/index.ts
|
|
10
10
|
|
|
@@ -58,6 +58,25 @@ var baseAttributes = {
|
|
|
58
58
|
}
|
|
59
59
|
return value;
|
|
60
60
|
}
|
|
61
|
+
},
|
|
62
|
+
/**
|
|
63
|
+
* TTL attribute for DynamoDB automatic item expiration.
|
|
64
|
+
* This is a Unix timestamp (epoch seconds) that indicates when the item should be deleted.
|
|
65
|
+
*
|
|
66
|
+
* Note: For TTL to work, you must enable TTL on your DynamoDB table
|
|
67
|
+
* specifying this attribute name (default: 'ttl').
|
|
68
|
+
*/
|
|
69
|
+
ttl: {
|
|
70
|
+
type: "number",
|
|
71
|
+
required: false
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Alternative TTL attribute with configurable name.
|
|
75
|
+
* Use this if you've configured TTL on your DynamoDB table with 'expiresAt' as the attribute name.
|
|
76
|
+
*/
|
|
77
|
+
expiresAt: {
|
|
78
|
+
type: "number",
|
|
79
|
+
required: false
|
|
61
80
|
}
|
|
62
81
|
};
|
|
63
82
|
|
|
@@ -423,6 +442,10 @@ var scoreEntity = new Entity({
|
|
|
423
442
|
return value;
|
|
424
443
|
}
|
|
425
444
|
},
|
|
445
|
+
preprocessPrompt: {
|
|
446
|
+
type: "string",
|
|
447
|
+
required: false
|
|
448
|
+
},
|
|
426
449
|
preprocessStepResult: {
|
|
427
450
|
type: "string",
|
|
428
451
|
required: false,
|
|
@@ -562,7 +585,29 @@ var scoreEntity = new Entity({
|
|
|
562
585
|
return value;
|
|
563
586
|
}
|
|
564
587
|
},
|
|
565
|
-
|
|
588
|
+
metadata: {
|
|
589
|
+
type: "string",
|
|
590
|
+
required: false,
|
|
591
|
+
set: (value) => {
|
|
592
|
+
if (value && typeof value !== "string") {
|
|
593
|
+
return JSON.stringify(value);
|
|
594
|
+
}
|
|
595
|
+
return value;
|
|
596
|
+
},
|
|
597
|
+
get: (value) => {
|
|
598
|
+
if (value && typeof value === "string") {
|
|
599
|
+
try {
|
|
600
|
+
if (value.startsWith("{") || value.startsWith("[")) {
|
|
601
|
+
return JSON.parse(value);
|
|
602
|
+
}
|
|
603
|
+
} catch {
|
|
604
|
+
return value;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return value;
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
requestContext: {
|
|
566
611
|
type: "string",
|
|
567
612
|
required: false,
|
|
568
613
|
set: (value) => {
|
|
@@ -933,193 +978,146 @@ function getElectroDbService(client, tableName) {
|
|
|
933
978
|
}
|
|
934
979
|
);
|
|
935
980
|
}
|
|
936
|
-
|
|
981
|
+
function resolveDynamoDBConfig(config) {
|
|
982
|
+
if ("service" in config) {
|
|
983
|
+
return { service: config.service, ttl: config.ttl };
|
|
984
|
+
}
|
|
985
|
+
const dynamoClient = new DynamoDBClient({
|
|
986
|
+
region: config.region || "us-east-1",
|
|
987
|
+
endpoint: config.endpoint,
|
|
988
|
+
credentials: config.credentials
|
|
989
|
+
});
|
|
990
|
+
const client = DynamoDBDocumentClient.from(dynamoClient);
|
|
991
|
+
return {
|
|
992
|
+
service: getElectroDbService(client, config.tableName),
|
|
993
|
+
ttl: config.ttl
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// src/storage/ttl.ts
|
|
998
|
+
function calculateTtl(entityName, ttlConfig, customTtlSeconds) {
|
|
999
|
+
const entityConfig = ttlConfig?.[entityName];
|
|
1000
|
+
if (!entityConfig?.enabled) {
|
|
1001
|
+
return void 0;
|
|
1002
|
+
}
|
|
1003
|
+
const ttlSeconds = customTtlSeconds ?? entityConfig.defaultTtlSeconds;
|
|
1004
|
+
if (ttlSeconds === void 0 || ttlSeconds <= 0) {
|
|
1005
|
+
return void 0;
|
|
1006
|
+
}
|
|
1007
|
+
return Math.floor(Date.now() / 1e3) + ttlSeconds;
|
|
1008
|
+
}
|
|
1009
|
+
function getTtlAttributeName(entityName, ttlConfig) {
|
|
1010
|
+
const entityConfig = ttlConfig?.[entityName];
|
|
1011
|
+
return entityConfig?.attributeName ?? "ttl";
|
|
1012
|
+
}
|
|
1013
|
+
function isTtlEnabled(entityName, ttlConfig) {
|
|
1014
|
+
return ttlConfig?.[entityName]?.enabled === true;
|
|
1015
|
+
}
|
|
1016
|
+
function getTtlProps(entityName, ttlConfig, customTtlSeconds) {
|
|
1017
|
+
const ttlValue = calculateTtl(entityName, ttlConfig, customTtlSeconds);
|
|
1018
|
+
if (ttlValue === void 0) return {};
|
|
1019
|
+
const attributeName = getTtlAttributeName(entityName, ttlConfig);
|
|
1020
|
+
return { [attributeName]: ttlValue };
|
|
1021
|
+
}
|
|
1022
|
+
var ENTITY_MAP = {
|
|
1023
|
+
[TABLE_THREADS]: "thread",
|
|
1024
|
+
[TABLE_MESSAGES]: "message",
|
|
1025
|
+
[TABLE_RESOURCES]: "resource",
|
|
1026
|
+
[TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
|
|
1027
|
+
[TABLE_SCORERS]: "score"
|
|
1028
|
+
};
|
|
1029
|
+
function getDeleteKey(entityName, item) {
|
|
1030
|
+
const key = { entity: entityName };
|
|
1031
|
+
switch (entityName) {
|
|
1032
|
+
case "thread":
|
|
1033
|
+
case "message":
|
|
1034
|
+
case "resource":
|
|
1035
|
+
case "score":
|
|
1036
|
+
key.id = item.id;
|
|
1037
|
+
break;
|
|
1038
|
+
case "workflow_snapshot":
|
|
1039
|
+
key.workflow_name = item.workflow_name;
|
|
1040
|
+
key.run_id = item.run_id;
|
|
1041
|
+
break;
|
|
1042
|
+
default:
|
|
1043
|
+
key.id = item.id;
|
|
1044
|
+
}
|
|
1045
|
+
return key;
|
|
1046
|
+
}
|
|
1047
|
+
async function deleteTableData(service, tableName) {
|
|
1048
|
+
const entityName = ENTITY_MAP[tableName];
|
|
1049
|
+
if (!entityName || !service.entities[entityName]) {
|
|
1050
|
+
throw new Error(`No entity mapping found for table: ${tableName}`);
|
|
1051
|
+
}
|
|
1052
|
+
const entity = service.entities[entityName];
|
|
1053
|
+
const result = await entity.scan.go({ pages: "all" });
|
|
1054
|
+
if (!result.data.length) {
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
const batchSize = 25;
|
|
1058
|
+
for (let i = 0; i < result.data.length; i += batchSize) {
|
|
1059
|
+
const batch = result.data.slice(i, i + batchSize);
|
|
1060
|
+
const keysToDelete = batch.map((item) => getDeleteKey(entityName, item));
|
|
1061
|
+
await entity.delete(keysToDelete).go();
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// src/storage/domains/memory/index.ts
|
|
1066
|
+
var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
937
1067
|
service;
|
|
938
|
-
|
|
939
|
-
constructor(
|
|
1068
|
+
ttlConfig;
|
|
1069
|
+
constructor(config) {
|
|
940
1070
|
super();
|
|
941
|
-
|
|
942
|
-
this.
|
|
1071
|
+
const resolved = resolveDynamoDBConfig(config);
|
|
1072
|
+
this.service = resolved.service;
|
|
1073
|
+
this.ttlConfig = resolved.ttl;
|
|
943
1074
|
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
this.
|
|
947
|
-
|
|
948
|
-
const query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
|
|
949
|
-
const results = await query.go({ order: "desc", limit: 100 });
|
|
950
|
-
if (!results.data.length) {
|
|
951
|
-
return [];
|
|
952
|
-
}
|
|
953
|
-
let filteredData = results.data;
|
|
954
|
-
if (type) {
|
|
955
|
-
filteredData = filteredData.filter((evalRecord) => {
|
|
956
|
-
try {
|
|
957
|
-
const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
|
|
958
|
-
if (type === "test" && !testInfo) {
|
|
959
|
-
return false;
|
|
960
|
-
}
|
|
961
|
-
if (type === "live" && testInfo) {
|
|
962
|
-
return false;
|
|
963
|
-
}
|
|
964
|
-
} catch (e) {
|
|
965
|
-
this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
|
|
966
|
-
}
|
|
967
|
-
return true;
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
return filteredData.map((evalRecord) => {
|
|
971
|
-
try {
|
|
972
|
-
return {
|
|
973
|
-
input: evalRecord.input,
|
|
974
|
-
output: evalRecord.output,
|
|
975
|
-
// Safely parse result and test_info
|
|
976
|
-
result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
|
|
977
|
-
agentName: evalRecord.agent_name,
|
|
978
|
-
createdAt: evalRecord.created_at,
|
|
979
|
-
// Keep as string from DDB?
|
|
980
|
-
metricName: evalRecord.metric_name,
|
|
981
|
-
instructions: evalRecord.instructions,
|
|
982
|
-
runId: evalRecord.run_id,
|
|
983
|
-
globalRunId: evalRecord.global_run_id,
|
|
984
|
-
testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
|
|
985
|
-
};
|
|
986
|
-
} catch (parseError) {
|
|
987
|
-
this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
|
|
988
|
-
return {
|
|
989
|
-
agentName: evalRecord.agent_name,
|
|
990
|
-
createdAt: evalRecord.created_at,
|
|
991
|
-
runId: evalRecord.run_id,
|
|
992
|
-
globalRunId: evalRecord.global_run_id
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
} catch (error) {
|
|
997
|
-
throw new MastraError(
|
|
998
|
-
{
|
|
999
|
-
id: "STORAGE_DYNAMODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
|
|
1000
|
-
domain: ErrorDomain.STORAGE,
|
|
1001
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1002
|
-
details: { agentName }
|
|
1003
|
-
},
|
|
1004
|
-
error
|
|
1005
|
-
);
|
|
1006
|
-
}
|
|
1075
|
+
async dangerouslyClearAll() {
|
|
1076
|
+
await deleteTableData(this.service, TABLE_THREADS);
|
|
1077
|
+
await deleteTableData(this.service, TABLE_MESSAGES);
|
|
1078
|
+
await deleteTableData(this.service, TABLE_RESOURCES);
|
|
1007
1079
|
}
|
|
1008
|
-
async
|
|
1009
|
-
|
|
1010
|
-
|
|
1080
|
+
async deleteMessages(messageIds) {
|
|
1081
|
+
if (!messageIds || messageIds.length === 0) {
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
this.logger.debug("Deleting messages", { count: messageIds.length });
|
|
1011
1085
|
try {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
total: 0,
|
|
1027
|
-
page,
|
|
1028
|
-
perPage,
|
|
1029
|
-
hasMore: false
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
let filteredData = results.data;
|
|
1033
|
-
if (type) {
|
|
1034
|
-
filteredData = filteredData.filter((evalRecord) => {
|
|
1035
|
-
try {
|
|
1036
|
-
const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
|
|
1037
|
-
if (type === "test" && !testInfo) {
|
|
1038
|
-
return false;
|
|
1039
|
-
}
|
|
1040
|
-
if (type === "live" && testInfo) {
|
|
1041
|
-
return false;
|
|
1086
|
+
const threadIds = /* @__PURE__ */ new Set();
|
|
1087
|
+
const batchSize = 25;
|
|
1088
|
+
for (let i = 0; i < messageIds.length; i += batchSize) {
|
|
1089
|
+
const batch = messageIds.slice(i, i + batchSize);
|
|
1090
|
+
const messagesToDelete = await Promise.all(
|
|
1091
|
+
batch.map(async (id) => {
|
|
1092
|
+
const result = await this.service.entities.message.get({ entity: "message", id }).go();
|
|
1093
|
+
return result.data;
|
|
1094
|
+
})
|
|
1095
|
+
);
|
|
1096
|
+
for (const message of messagesToDelete) {
|
|
1097
|
+
if (message) {
|
|
1098
|
+
if (message.threadId) {
|
|
1099
|
+
threadIds.add(message.threadId);
|
|
1042
1100
|
}
|
|
1043
|
-
|
|
1044
|
-
this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
|
|
1101
|
+
await this.service.entities.message.delete({ entity: "message", id: message.id }).go();
|
|
1045
1102
|
}
|
|
1046
|
-
|
|
1047
|
-
});
|
|
1103
|
+
}
|
|
1048
1104
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
filteredData = filteredData.filter((evalRecord) => {
|
|
1053
|
-
const recordDate = new Date(evalRecord.created_at);
|
|
1054
|
-
if (fromDate && recordDate < fromDate) {
|
|
1055
|
-
return false;
|
|
1056
|
-
}
|
|
1057
|
-
if (toDate && recordDate > toDate) {
|
|
1058
|
-
return false;
|
|
1059
|
-
}
|
|
1060
|
-
return true;
|
|
1061
|
-
});
|
|
1105
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1106
|
+
for (const threadId of threadIds) {
|
|
1107
|
+
await this.service.entities.thread.update({ entity: "thread", id: threadId }).set({ updatedAt: now }).go();
|
|
1062
1108
|
}
|
|
1063
|
-
const total = filteredData.length;
|
|
1064
|
-
const start = page * perPage;
|
|
1065
|
-
const end = start + perPage;
|
|
1066
|
-
const paginatedData = filteredData.slice(start, end);
|
|
1067
|
-
const evals = paginatedData.map((evalRecord) => {
|
|
1068
|
-
try {
|
|
1069
|
-
return {
|
|
1070
|
-
input: evalRecord.input,
|
|
1071
|
-
output: evalRecord.output,
|
|
1072
|
-
result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
|
|
1073
|
-
agentName: evalRecord.agent_name,
|
|
1074
|
-
createdAt: evalRecord.created_at,
|
|
1075
|
-
metricName: evalRecord.metric_name,
|
|
1076
|
-
instructions: evalRecord.instructions,
|
|
1077
|
-
runId: evalRecord.run_id,
|
|
1078
|
-
globalRunId: evalRecord.global_run_id,
|
|
1079
|
-
testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
|
|
1080
|
-
};
|
|
1081
|
-
} catch (parseError) {
|
|
1082
|
-
this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
|
|
1083
|
-
return {
|
|
1084
|
-
agentName: evalRecord.agent_name,
|
|
1085
|
-
createdAt: evalRecord.created_at,
|
|
1086
|
-
runId: evalRecord.run_id,
|
|
1087
|
-
globalRunId: evalRecord.global_run_id
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
});
|
|
1091
|
-
const hasMore = end < total;
|
|
1092
|
-
return {
|
|
1093
|
-
evals,
|
|
1094
|
-
total,
|
|
1095
|
-
page,
|
|
1096
|
-
perPage,
|
|
1097
|
-
hasMore
|
|
1098
|
-
};
|
|
1099
1109
|
} catch (error) {
|
|
1100
1110
|
throw new MastraError(
|
|
1101
1111
|
{
|
|
1102
|
-
id: "
|
|
1112
|
+
id: createStorageErrorId("DYNAMODB", "DELETE_MESSAGES", "FAILED"),
|
|
1103
1113
|
domain: ErrorDomain.STORAGE,
|
|
1104
1114
|
category: ErrorCategory.THIRD_PARTY,
|
|
1105
|
-
details: {
|
|
1106
|
-
agentName: agentName || "all",
|
|
1107
|
-
type: type || "all",
|
|
1108
|
-
page,
|
|
1109
|
-
perPage
|
|
1110
|
-
}
|
|
1115
|
+
details: { count: messageIds.length }
|
|
1111
1116
|
},
|
|
1112
1117
|
error
|
|
1113
1118
|
);
|
|
1114
1119
|
}
|
|
1115
1120
|
}
|
|
1116
|
-
};
|
|
1117
|
-
var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
1118
|
-
service;
|
|
1119
|
-
constructor({ service }) {
|
|
1120
|
-
super();
|
|
1121
|
-
this.service = service;
|
|
1122
|
-
}
|
|
1123
1121
|
// Helper function to parse message data (handle JSON fields)
|
|
1124
1122
|
parseMessageData(data) {
|
|
1125
1123
|
return {
|
|
@@ -1132,17 +1130,17 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1132
1130
|
};
|
|
1133
1131
|
}
|
|
1134
1132
|
// Helper function to transform and sort threads
|
|
1135
|
-
transformAndSortThreads(rawThreads,
|
|
1133
|
+
transformAndSortThreads(rawThreads, field, direction) {
|
|
1136
1134
|
return rawThreads.map((data) => ({
|
|
1137
1135
|
...data,
|
|
1138
1136
|
// Convert date strings back to Date objects for consistency
|
|
1139
1137
|
createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
|
|
1140
1138
|
updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
|
|
1141
1139
|
})).sort((a, b) => {
|
|
1142
|
-
const fieldA =
|
|
1143
|
-
const fieldB =
|
|
1140
|
+
const fieldA = field === "createdAt" ? a.createdAt : a.updatedAt;
|
|
1141
|
+
const fieldB = field === "createdAt" ? b.createdAt : b.updatedAt;
|
|
1144
1142
|
const comparison = fieldA.getTime() - fieldB.getTime();
|
|
1145
|
-
return
|
|
1143
|
+
return direction === "DESC" ? -comparison : comparison;
|
|
1146
1144
|
});
|
|
1147
1145
|
}
|
|
1148
1146
|
async getThreadById({ threadId }) {
|
|
@@ -1164,7 +1162,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1164
1162
|
} catch (error) {
|
|
1165
1163
|
throw new MastraError(
|
|
1166
1164
|
{
|
|
1167
|
-
id: "
|
|
1165
|
+
id: createStorageErrorId("DYNAMODB", "GET_THREAD_BY_ID", "FAILED"),
|
|
1168
1166
|
domain: ErrorDomain.STORAGE,
|
|
1169
1167
|
category: ErrorCategory.THIRD_PARTY,
|
|
1170
1168
|
details: { threadId }
|
|
@@ -1173,32 +1171,6 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1173
1171
|
);
|
|
1174
1172
|
}
|
|
1175
1173
|
}
|
|
1176
|
-
/**
|
|
1177
|
-
* @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
|
|
1178
|
-
*/
|
|
1179
|
-
async getThreadsByResourceId(args) {
|
|
1180
|
-
const resourceId = args.resourceId;
|
|
1181
|
-
const orderBy = this.castThreadOrderBy(args.orderBy);
|
|
1182
|
-
const sortDirection = this.castThreadSortDirection(args.sortDirection);
|
|
1183
|
-
this.logger.debug("Getting threads by resource ID", { resourceId, orderBy, sortDirection });
|
|
1184
|
-
try {
|
|
1185
|
-
const result = await this.service.entities.thread.query.byResource({ entity: "thread", resourceId }).go();
|
|
1186
|
-
if (!result.data.length) {
|
|
1187
|
-
return [];
|
|
1188
|
-
}
|
|
1189
|
-
return this.transformAndSortThreads(result.data, orderBy, sortDirection);
|
|
1190
|
-
} catch (error) {
|
|
1191
|
-
throw new MastraError(
|
|
1192
|
-
{
|
|
1193
|
-
id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
1194
|
-
domain: ErrorDomain.STORAGE,
|
|
1195
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1196
|
-
details: { resourceId }
|
|
1197
|
-
},
|
|
1198
|
-
error
|
|
1199
|
-
);
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
1174
|
async saveThread({ thread }) {
|
|
1203
1175
|
this.logger.debug("Saving thread", { threadId: thread.id });
|
|
1204
1176
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -1209,7 +1181,8 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1209
1181
|
title: thread.title || `Thread ${thread.id}`,
|
|
1210
1182
|
createdAt: thread.createdAt?.toISOString() || now.toISOString(),
|
|
1211
1183
|
updatedAt: thread.updatedAt?.toISOString() || now.toISOString(),
|
|
1212
|
-
metadata: thread.metadata ? JSON.stringify(thread.metadata) : void 0
|
|
1184
|
+
metadata: thread.metadata ? JSON.stringify(thread.metadata) : void 0,
|
|
1185
|
+
...getTtlProps("thread", this.ttlConfig)
|
|
1213
1186
|
};
|
|
1214
1187
|
try {
|
|
1215
1188
|
await this.service.entities.thread.upsert(threadData).go();
|
|
@@ -1218,13 +1191,13 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1218
1191
|
resourceId: thread.resourceId,
|
|
1219
1192
|
title: threadData.title,
|
|
1220
1193
|
createdAt: thread.createdAt || now,
|
|
1221
|
-
updatedAt: now,
|
|
1194
|
+
updatedAt: thread.updatedAt || now,
|
|
1222
1195
|
metadata: thread.metadata
|
|
1223
1196
|
};
|
|
1224
1197
|
} catch (error) {
|
|
1225
1198
|
throw new MastraError(
|
|
1226
1199
|
{
|
|
1227
|
-
id: "
|
|
1200
|
+
id: createStorageErrorId("DYNAMODB", "SAVE_THREAD", "FAILED"),
|
|
1228
1201
|
domain: ErrorDomain.STORAGE,
|
|
1229
1202
|
category: ErrorCategory.THIRD_PARTY,
|
|
1230
1203
|
details: { threadId: thread.id }
|
|
@@ -1266,7 +1239,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1266
1239
|
} catch (error) {
|
|
1267
1240
|
throw new MastraError(
|
|
1268
1241
|
{
|
|
1269
|
-
id: "
|
|
1242
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_THREAD", "FAILED"),
|
|
1270
1243
|
domain: ErrorDomain.STORAGE,
|
|
1271
1244
|
category: ErrorCategory.THIRD_PARTY,
|
|
1272
1245
|
details: { threadId: id }
|
|
@@ -1278,7 +1251,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1278
1251
|
async deleteThread({ threadId }) {
|
|
1279
1252
|
this.logger.debug("Deleting thread", { threadId });
|
|
1280
1253
|
try {
|
|
1281
|
-
const messages = await this.
|
|
1254
|
+
const { messages } = await this.listMessages({ threadId, perPage: false });
|
|
1282
1255
|
if (messages.length > 0) {
|
|
1283
1256
|
const batchSize = 25;
|
|
1284
1257
|
for (let i = 0; i < messages.length; i += batchSize) {
|
|
@@ -1298,7 +1271,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1298
1271
|
} catch (error) {
|
|
1299
1272
|
throw new MastraError(
|
|
1300
1273
|
{
|
|
1301
|
-
id: "
|
|
1274
|
+
id: createStorageErrorId("DYNAMODB", "DELETE_THREAD", "FAILED"),
|
|
1302
1275
|
domain: ErrorDomain.STORAGE,
|
|
1303
1276
|
category: ErrorCategory.THIRD_PARTY,
|
|
1304
1277
|
details: { threadId }
|
|
@@ -1307,104 +1280,166 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1307
1280
|
);
|
|
1308
1281
|
}
|
|
1309
1282
|
}
|
|
1310
|
-
async
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
selectBy,
|
|
1314
|
-
format
|
|
1315
|
-
}) {
|
|
1316
|
-
this.logger.debug("Getting messages", { threadId, selectBy });
|
|
1283
|
+
async listMessagesById({ messageIds }) {
|
|
1284
|
+
this.logger.debug("Getting messages by ID", { messageIds });
|
|
1285
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
1317
1286
|
try {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
messages.push(...includeMessages);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
if (limit !== 0) {
|
|
1328
|
-
const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
|
|
1329
|
-
let results;
|
|
1330
|
-
if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
|
|
1331
|
-
results = await query.go({ limit, order: "desc" });
|
|
1332
|
-
results.data = results.data.reverse();
|
|
1333
|
-
} else {
|
|
1334
|
-
results = await query.go();
|
|
1335
|
-
}
|
|
1336
|
-
let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
|
|
1337
|
-
allThreadMessages.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
|
-
messages.push(...allThreadMessages);
|
|
1346
|
-
}
|
|
1347
|
-
messages.sort((a, b) => {
|
|
1348
|
-
const timeA = a.createdAt.getTime();
|
|
1349
|
-
const timeB = b.createdAt.getTime();
|
|
1350
|
-
if (timeA === timeB) {
|
|
1351
|
-
return a.id.localeCompare(b.id);
|
|
1352
|
-
}
|
|
1353
|
-
return timeA - timeB;
|
|
1354
|
-
});
|
|
1355
|
-
const uniqueMessages = messages.filter(
|
|
1287
|
+
const results = await Promise.all(
|
|
1288
|
+
messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
|
|
1289
|
+
);
|
|
1290
|
+
const data = results.map((result) => result.data).flat(1);
|
|
1291
|
+
let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
|
|
1292
|
+
const uniqueMessages = parsedMessages.filter(
|
|
1356
1293
|
(message, index, self) => index === self.findIndex((m) => m.id === message.id)
|
|
1357
1294
|
);
|
|
1358
|
-
const list = new MessageList(
|
|
1359
|
-
|
|
1360
|
-
return list.get.all.v1();
|
|
1295
|
+
const list = new MessageList().add(uniqueMessages, "memory");
|
|
1296
|
+
return { messages: list.get.all.db() };
|
|
1361
1297
|
} catch (error) {
|
|
1362
1298
|
throw new MastraError(
|
|
1363
1299
|
{
|
|
1364
|
-
id: "
|
|
1300
|
+
id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
1365
1301
|
domain: ErrorDomain.STORAGE,
|
|
1366
1302
|
category: ErrorCategory.THIRD_PARTY,
|
|
1367
|
-
details: {
|
|
1303
|
+
details: { messageIds: JSON.stringify(messageIds) }
|
|
1368
1304
|
},
|
|
1369
1305
|
error
|
|
1370
1306
|
);
|
|
1371
1307
|
}
|
|
1372
1308
|
}
|
|
1373
|
-
async
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1309
|
+
async listMessages(args) {
|
|
1310
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
1311
|
+
const threadIds = Array.isArray(threadId) ? threadId : [threadId];
|
|
1312
|
+
if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
|
|
1313
|
+
throw new MastraError(
|
|
1314
|
+
{
|
|
1315
|
+
id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
1316
|
+
domain: ErrorDomain.STORAGE,
|
|
1317
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1318
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
1319
|
+
},
|
|
1320
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
1382
1321
|
);
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1322
|
+
}
|
|
1323
|
+
const perPage = normalizePerPage(perPageInput, 40);
|
|
1324
|
+
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1325
|
+
try {
|
|
1326
|
+
if (page < 0) {
|
|
1327
|
+
throw new MastraError(
|
|
1328
|
+
{
|
|
1329
|
+
id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "INVALID_PAGE"),
|
|
1330
|
+
domain: ErrorDomain.STORAGE,
|
|
1331
|
+
category: ErrorCategory.USER,
|
|
1332
|
+
details: { page }
|
|
1333
|
+
},
|
|
1334
|
+
new Error("page must be >= 0")
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
1338
|
+
this.logger.debug("Getting messages with listMessages", {
|
|
1339
|
+
threadId,
|
|
1340
|
+
resourceId,
|
|
1341
|
+
perPageInput,
|
|
1342
|
+
offset,
|
|
1343
|
+
perPage,
|
|
1344
|
+
page,
|
|
1345
|
+
field,
|
|
1346
|
+
direction
|
|
1347
|
+
});
|
|
1348
|
+
const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
|
|
1349
|
+
const results = await query.go();
|
|
1350
|
+
let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
|
|
1351
|
+
if (resourceId) {
|
|
1352
|
+
allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
|
|
1353
|
+
}
|
|
1354
|
+
allThreadMessages = filterByDateRange(
|
|
1355
|
+
allThreadMessages,
|
|
1356
|
+
(msg) => new Date(msg.createdAt),
|
|
1357
|
+
filter?.dateRange
|
|
1387
1358
|
);
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1359
|
+
allThreadMessages.sort((a, b) => {
|
|
1360
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
1361
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
1362
|
+
if (aValue === bValue) {
|
|
1363
|
+
return a.id.localeCompare(b.id);
|
|
1364
|
+
}
|
|
1365
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
1366
|
+
});
|
|
1367
|
+
const total = allThreadMessages.length;
|
|
1368
|
+
const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
|
|
1369
|
+
const paginatedCount = paginatedMessages.length;
|
|
1370
|
+
if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
|
|
1371
|
+
return {
|
|
1372
|
+
messages: [],
|
|
1373
|
+
total: 0,
|
|
1374
|
+
page,
|
|
1375
|
+
perPage: perPageForResponse,
|
|
1376
|
+
hasMore: false
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
const messageIds = new Set(paginatedMessages.map((m) => m.id));
|
|
1380
|
+
let includeMessages = [];
|
|
1381
|
+
if (include && include.length > 0) {
|
|
1382
|
+
const selectBy = { include };
|
|
1383
|
+
includeMessages = await this._getIncludedMessages(selectBy);
|
|
1384
|
+
for (const includeMsg of includeMessages) {
|
|
1385
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
1386
|
+
paginatedMessages.push(includeMsg);
|
|
1387
|
+
messageIds.add(includeMsg.id);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
const list = new MessageList().add(paginatedMessages, "memory");
|
|
1392
|
+
let finalMessages = list.get.all.db();
|
|
1393
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
1394
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
1395
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
1396
|
+
if (aValue === bValue) {
|
|
1397
|
+
return a.id.localeCompare(b.id);
|
|
1398
|
+
}
|
|
1399
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
1400
|
+
});
|
|
1401
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
1402
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
1403
|
+
let hasMore = false;
|
|
1404
|
+
if (perPageInput !== false && !allThreadMessagesReturned) {
|
|
1405
|
+
hasMore = offset + paginatedCount < total;
|
|
1406
|
+
}
|
|
1407
|
+
return {
|
|
1408
|
+
messages: finalMessages,
|
|
1409
|
+
total,
|
|
1410
|
+
page,
|
|
1411
|
+
perPage: perPageForResponse,
|
|
1412
|
+
hasMore
|
|
1413
|
+
};
|
|
1391
1414
|
} catch (error) {
|
|
1392
|
-
|
|
1415
|
+
const mastraError = new MastraError(
|
|
1393
1416
|
{
|
|
1394
|
-
id: "
|
|
1417
|
+
id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "FAILED"),
|
|
1395
1418
|
domain: ErrorDomain.STORAGE,
|
|
1396
1419
|
category: ErrorCategory.THIRD_PARTY,
|
|
1397
|
-
details: {
|
|
1420
|
+
details: {
|
|
1421
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
1422
|
+
resourceId: resourceId ?? ""
|
|
1423
|
+
}
|
|
1398
1424
|
},
|
|
1399
1425
|
error
|
|
1400
1426
|
);
|
|
1427
|
+
this.logger?.error?.(mastraError.toString());
|
|
1428
|
+
this.logger?.trackException?.(mastraError);
|
|
1429
|
+
return {
|
|
1430
|
+
messages: [],
|
|
1431
|
+
total: 0,
|
|
1432
|
+
page,
|
|
1433
|
+
perPage: perPageForResponse,
|
|
1434
|
+
hasMore: false
|
|
1435
|
+
};
|
|
1401
1436
|
}
|
|
1402
1437
|
}
|
|
1403
1438
|
async saveMessages(args) {
|
|
1404
|
-
const { messages
|
|
1439
|
+
const { messages } = args;
|
|
1405
1440
|
this.logger.debug("Saving messages", { count: messages.length });
|
|
1406
1441
|
if (!messages.length) {
|
|
1407
|
-
return [];
|
|
1442
|
+
return { messages: [] };
|
|
1408
1443
|
}
|
|
1409
1444
|
const threadId = messages[0]?.threadId;
|
|
1410
1445
|
if (!threadId) {
|
|
@@ -1414,20 +1449,18 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1414
1449
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1415
1450
|
return {
|
|
1416
1451
|
entity: "message",
|
|
1417
|
-
// Add entity type
|
|
1418
1452
|
id: msg.id,
|
|
1419
1453
|
threadId: msg.threadId,
|
|
1420
1454
|
role: msg.role,
|
|
1421
1455
|
type: msg.type,
|
|
1422
1456
|
resourceId: msg.resourceId,
|
|
1423
|
-
// Ensure complex fields are stringified if not handled by attribute setters
|
|
1424
1457
|
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
|
|
1425
1458
|
toolCallArgs: `toolCallArgs` in msg && msg.toolCallArgs ? JSON.stringify(msg.toolCallArgs) : void 0,
|
|
1426
1459
|
toolCallIds: `toolCallIds` in msg && msg.toolCallIds ? JSON.stringify(msg.toolCallIds) : void 0,
|
|
1427
1460
|
toolNames: `toolNames` in msg && msg.toolNames ? JSON.stringify(msg.toolNames) : void 0,
|
|
1428
1461
|
createdAt: msg.createdAt instanceof Date ? msg.createdAt.toISOString() : msg.createdAt || now,
|
|
1429
|
-
updatedAt: now
|
|
1430
|
-
|
|
1462
|
+
updatedAt: now,
|
|
1463
|
+
...getTtlProps("message", this.ttlConfig)
|
|
1431
1464
|
};
|
|
1432
1465
|
});
|
|
1433
1466
|
try {
|
|
@@ -1458,12 +1491,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1458
1491
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1459
1492
|
}).go();
|
|
1460
1493
|
const list = new MessageList().add(messages, "memory");
|
|
1461
|
-
|
|
1462
|
-
return list.get.all.v2();
|
|
1494
|
+
return { messages: list.get.all.db() };
|
|
1463
1495
|
} catch (error) {
|
|
1464
1496
|
throw new MastraError(
|
|
1465
1497
|
{
|
|
1466
|
-
id: "
|
|
1498
|
+
id: createStorageErrorId("DYNAMODB", "SAVE_MESSAGES", "FAILED"),
|
|
1467
1499
|
domain: ErrorDomain.STORAGE,
|
|
1468
1500
|
category: ErrorCategory.THIRD_PARTY,
|
|
1469
1501
|
details: { count: messages.length }
|
|
@@ -1472,137 +1504,103 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1472
1504
|
);
|
|
1473
1505
|
}
|
|
1474
1506
|
}
|
|
1475
|
-
async
|
|
1476
|
-
const {
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1507
|
+
async listThreads(args) {
|
|
1508
|
+
const { page = 0, perPage: perPageInput, orderBy, filter } = args;
|
|
1509
|
+
try {
|
|
1510
|
+
this.validatePaginationInput(page, perPageInput ?? 100);
|
|
1511
|
+
} catch (error) {
|
|
1512
|
+
throw new MastraError(
|
|
1513
|
+
{
|
|
1514
|
+
id: createStorageErrorId("DYNAMODB", "LIST_THREADS", "INVALID_PAGE"),
|
|
1515
|
+
domain: ErrorDomain.STORAGE,
|
|
1516
|
+
category: ErrorCategory.USER,
|
|
1517
|
+
details: {
|
|
1518
|
+
page,
|
|
1519
|
+
...perPageInput !== void 0 && { perPage: perPageInput }
|
|
1520
|
+
}
|
|
1521
|
+
},
|
|
1522
|
+
error instanceof Error ? error : new Error("Invalid pagination parameters")
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
1526
|
+
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1527
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
1528
|
+
this.logger.debug("Listing threads with filters", {
|
|
1529
|
+
resourceId: filter?.resourceId,
|
|
1530
|
+
metadataKeys: filter?.metadata ? Object.keys(filter.metadata) : [],
|
|
1481
1531
|
page,
|
|
1482
1532
|
perPage,
|
|
1483
|
-
|
|
1484
|
-
|
|
1533
|
+
field,
|
|
1534
|
+
direction
|
|
1485
1535
|
});
|
|
1486
1536
|
try {
|
|
1487
|
-
const
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1537
|
+
const rawThreads = filter?.resourceId ? (await this.service.entities.thread.query.byResource({
|
|
1538
|
+
entity: "thread",
|
|
1539
|
+
resourceId: filter.resourceId
|
|
1540
|
+
}).go({ pages: "all" })).data : (await this.service.entities.thread.scan.go({ pages: "all" })).data;
|
|
1541
|
+
let allThreads = this.transformAndSortThreads(rawThreads, field, direction);
|
|
1542
|
+
if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
|
|
1543
|
+
allThreads = allThreads.filter((thread) => {
|
|
1544
|
+
let threadMeta = null;
|
|
1545
|
+
if (typeof thread.metadata === "string") {
|
|
1546
|
+
try {
|
|
1547
|
+
threadMeta = JSON.parse(thread.metadata);
|
|
1548
|
+
} catch {
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
} else if (thread.metadata && typeof thread.metadata === "object") {
|
|
1552
|
+
threadMeta = thread.metadata;
|
|
1553
|
+
}
|
|
1554
|
+
if (!threadMeta) return false;
|
|
1555
|
+
return Object.entries(filter.metadata).every(([key, value]) => threadMeta[key] === value);
|
|
1556
|
+
});
|
|
1557
|
+
}
|
|
1558
|
+
const endIndex = offset + perPage;
|
|
1559
|
+
const paginatedThreads = allThreads.slice(offset, endIndex);
|
|
1493
1560
|
const total = allThreads.length;
|
|
1494
|
-
const hasMore =
|
|
1561
|
+
const hasMore = offset + perPage < total;
|
|
1495
1562
|
return {
|
|
1496
1563
|
threads: paginatedThreads,
|
|
1497
1564
|
total,
|
|
1498
1565
|
page,
|
|
1499
|
-
perPage,
|
|
1566
|
+
perPage: perPageForResponse,
|
|
1500
1567
|
hasMore
|
|
1501
1568
|
};
|
|
1502
1569
|
} catch (error) {
|
|
1503
1570
|
throw new MastraError(
|
|
1504
1571
|
{
|
|
1505
|
-
id: "
|
|
1572
|
+
id: createStorageErrorId("DYNAMODB", "LIST_THREADS", "FAILED"),
|
|
1506
1573
|
domain: ErrorDomain.STORAGE,
|
|
1507
1574
|
category: ErrorCategory.THIRD_PARTY,
|
|
1508
|
-
details: {
|
|
1575
|
+
details: {
|
|
1576
|
+
...filter?.resourceId && { resourceId: filter.resourceId },
|
|
1577
|
+
hasMetadataFilter: !!(filter?.metadata && Object.keys(filter.metadata).length),
|
|
1578
|
+
page,
|
|
1579
|
+
perPage: perPageForResponse
|
|
1580
|
+
}
|
|
1509
1581
|
},
|
|
1510
1582
|
error
|
|
1511
1583
|
);
|
|
1512
1584
|
}
|
|
1513
1585
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
const
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
messages.push(...includeMessages);
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
if (limit !== 0) {
|
|
1531
|
-
const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
|
|
1532
|
-
let results;
|
|
1533
|
-
if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
|
|
1534
|
-
results = await query.go({ limit, order: "desc" });
|
|
1535
|
-
results.data = results.data.reverse();
|
|
1536
|
-
} else {
|
|
1537
|
-
results = await query.go();
|
|
1586
|
+
// Helper method to get included messages with context
|
|
1587
|
+
async _getIncludedMessages(selectBy) {
|
|
1588
|
+
if (!selectBy?.include?.length) {
|
|
1589
|
+
return [];
|
|
1590
|
+
}
|
|
1591
|
+
const includeMessages = [];
|
|
1592
|
+
for (const includeItem of selectBy.include) {
|
|
1593
|
+
try {
|
|
1594
|
+
const { id, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
|
|
1595
|
+
const targetResult = await this.service.entities.message.get({ entity: "message", id }).go();
|
|
1596
|
+
if (!targetResult.data) {
|
|
1597
|
+
this.logger.warn("Target message not found", { id });
|
|
1598
|
+
continue;
|
|
1538
1599
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
const timeA = a.createdAt.getTime();
|
|
1542
|
-
const timeB = b.createdAt.getTime();
|
|
1543
|
-
if (timeA === timeB) {
|
|
1544
|
-
return a.id.localeCompare(b.id);
|
|
1545
|
-
}
|
|
1546
|
-
return timeA - timeB;
|
|
1547
|
-
});
|
|
1548
|
-
const excludeIds = messages.map((m) => m.id);
|
|
1549
|
-
if (excludeIds.length > 0) {
|
|
1550
|
-
allThreadMessages = allThreadMessages.filter((msg) => !excludeIds.includes(msg.id));
|
|
1551
|
-
}
|
|
1552
|
-
messages.push(...allThreadMessages);
|
|
1553
|
-
}
|
|
1554
|
-
messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
1555
|
-
if (fromDate || toDate) {
|
|
1556
|
-
messages = messages.filter((msg) => {
|
|
1557
|
-
const createdAt = new Date(msg.createdAt).getTime();
|
|
1558
|
-
if (fromDate && createdAt < new Date(fromDate).getTime()) return false;
|
|
1559
|
-
if (toDate && createdAt > new Date(toDate).getTime()) return false;
|
|
1560
|
-
return true;
|
|
1561
|
-
});
|
|
1562
|
-
}
|
|
1563
|
-
const total = messages.length;
|
|
1564
|
-
const start = page * perPage;
|
|
1565
|
-
const end = start + perPage;
|
|
1566
|
-
const paginatedMessages = messages.slice(start, end);
|
|
1567
|
-
const hasMore = end < total;
|
|
1568
|
-
const list = new MessageList({ threadId, resourceId }).add(paginatedMessages, "memory");
|
|
1569
|
-
const finalMessages = format === "v2" ? list.get.all.v2() : list.get.all.v1();
|
|
1570
|
-
return {
|
|
1571
|
-
messages: finalMessages,
|
|
1572
|
-
total,
|
|
1573
|
-
page,
|
|
1574
|
-
perPage,
|
|
1575
|
-
hasMore
|
|
1576
|
-
};
|
|
1577
|
-
} catch (error) {
|
|
1578
|
-
const mastraError = new MastraError(
|
|
1579
|
-
{
|
|
1580
|
-
id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
|
|
1581
|
-
domain: ErrorDomain.STORAGE,
|
|
1582
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1583
|
-
details: { threadId, resourceId: resourceId ?? "" }
|
|
1584
|
-
},
|
|
1585
|
-
error
|
|
1586
|
-
);
|
|
1587
|
-
this.logger?.trackException?.(mastraError);
|
|
1588
|
-
this.logger?.error?.(mastraError.toString());
|
|
1589
|
-
return { messages: [], total: 0, page, perPage, hasMore: false };
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
// Helper method to get included messages with context
|
|
1593
|
-
async _getIncludedMessages(threadId, selectBy) {
|
|
1594
|
-
if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
|
|
1595
|
-
if (!selectBy?.include?.length) {
|
|
1596
|
-
return [];
|
|
1597
|
-
}
|
|
1598
|
-
const includeMessages = [];
|
|
1599
|
-
for (const includeItem of selectBy.include) {
|
|
1600
|
-
try {
|
|
1601
|
-
const { id, threadId: targetThreadId, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
|
|
1602
|
-
const searchThreadId = targetThreadId || threadId;
|
|
1600
|
+
const targetMessageData = targetResult.data;
|
|
1601
|
+
const searchThreadId = targetMessageData.threadId;
|
|
1603
1602
|
this.logger.debug("Getting included messages for", {
|
|
1604
1603
|
id,
|
|
1605
|
-
targetThreadId,
|
|
1606
1604
|
searchThreadId,
|
|
1607
1605
|
withPreviousMessages,
|
|
1608
1606
|
withNextMessages
|
|
@@ -1625,7 +1623,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1625
1623
|
});
|
|
1626
1624
|
const targetIndex = allMessages.findIndex((msg) => msg.id === id);
|
|
1627
1625
|
if (targetIndex === -1) {
|
|
1628
|
-
this.logger.warn("Target message not found", { id, threadId: searchThreadId });
|
|
1626
|
+
this.logger.warn("Target message not found in thread", { id, threadId: searchThreadId });
|
|
1629
1627
|
continue;
|
|
1630
1628
|
}
|
|
1631
1629
|
this.logger.debug("Found target message at index", { id, targetIndex, totalMessages: allMessages.length });
|
|
@@ -1710,7 +1708,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1710
1708
|
} catch (error) {
|
|
1711
1709
|
throw new MastraError(
|
|
1712
1710
|
{
|
|
1713
|
-
id: "
|
|
1711
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_MESSAGES", "FAILED"),
|
|
1714
1712
|
domain: ErrorDomain.STORAGE,
|
|
1715
1713
|
category: ErrorCategory.THIRD_PARTY,
|
|
1716
1714
|
details: { count: messages.length }
|
|
@@ -1739,7 +1737,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1739
1737
|
} catch (error) {
|
|
1740
1738
|
throw new MastraError(
|
|
1741
1739
|
{
|
|
1742
|
-
id: "
|
|
1740
|
+
id: createStorageErrorId("DYNAMODB", "GET_RESOURCE_BY_ID", "FAILED"),
|
|
1743
1741
|
domain: ErrorDomain.STORAGE,
|
|
1744
1742
|
category: ErrorCategory.THIRD_PARTY,
|
|
1745
1743
|
details: { resourceId }
|
|
@@ -1757,7 +1755,8 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1757
1755
|
workingMemory: resource.workingMemory,
|
|
1758
1756
|
metadata: resource.metadata ? JSON.stringify(resource.metadata) : void 0,
|
|
1759
1757
|
createdAt: resource.createdAt?.toISOString() || now.toISOString(),
|
|
1760
|
-
updatedAt: now.toISOString()
|
|
1758
|
+
updatedAt: now.toISOString(),
|
|
1759
|
+
...getTtlProps("resource", this.ttlConfig)
|
|
1761
1760
|
};
|
|
1762
1761
|
try {
|
|
1763
1762
|
await this.service.entities.resource.upsert(resourceData).go();
|
|
@@ -1771,7 +1770,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1771
1770
|
} catch (error) {
|
|
1772
1771
|
throw new MastraError(
|
|
1773
1772
|
{
|
|
1774
|
-
id: "
|
|
1773
|
+
id: createStorageErrorId("DYNAMODB", "SAVE_RESOURCE", "FAILED"),
|
|
1775
1774
|
domain: ErrorDomain.STORAGE,
|
|
1776
1775
|
category: ErrorCategory.THIRD_PARTY,
|
|
1777
1776
|
details: { resourceId: resource.id }
|
|
@@ -1820,7 +1819,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1820
1819
|
} catch (error) {
|
|
1821
1820
|
throw new MastraError(
|
|
1822
1821
|
{
|
|
1823
|
-
id: "
|
|
1822
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_RESOURCE", "FAILED"),
|
|
1824
1823
|
domain: ErrorDomain.STORAGE,
|
|
1825
1824
|
category: ErrorCategory.THIRD_PARTY,
|
|
1826
1825
|
details: { resourceId }
|
|
@@ -1830,339 +1829,40 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
|
|
|
1830
1829
|
}
|
|
1831
1830
|
}
|
|
1832
1831
|
};
|
|
1833
|
-
var
|
|
1834
|
-
client;
|
|
1835
|
-
tableName;
|
|
1832
|
+
var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
1836
1833
|
service;
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
tableName,
|
|
1840
|
-
client
|
|
1841
|
-
}) {
|
|
1834
|
+
ttlConfig;
|
|
1835
|
+
constructor(config) {
|
|
1842
1836
|
super();
|
|
1843
|
-
|
|
1844
|
-
this.
|
|
1845
|
-
this.
|
|
1846
|
-
}
|
|
1847
|
-
async hasColumn() {
|
|
1848
|
-
return true;
|
|
1837
|
+
const resolved = resolveDynamoDBConfig(config);
|
|
1838
|
+
this.service = resolved.service;
|
|
1839
|
+
this.ttlConfig = resolved.ttl;
|
|
1849
1840
|
}
|
|
1850
|
-
async
|
|
1851
|
-
|
|
1852
|
-
// Helper methods for entity/table mapping
|
|
1853
|
-
getEntityNameForTable(tableName) {
|
|
1854
|
-
const mapping = {
|
|
1855
|
-
[TABLE_THREADS]: "thread",
|
|
1856
|
-
[TABLE_MESSAGES]: "message",
|
|
1857
|
-
[TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
|
|
1858
|
-
[TABLE_EVALS]: "eval",
|
|
1859
|
-
[TABLE_SCORERS]: "score",
|
|
1860
|
-
[TABLE_TRACES]: "trace",
|
|
1861
|
-
[TABLE_RESOURCES]: "resource",
|
|
1862
|
-
[TABLE_AI_SPANS]: "ai_span"
|
|
1863
|
-
};
|
|
1864
|
-
return mapping[tableName] || null;
|
|
1841
|
+
async dangerouslyClearAll() {
|
|
1842
|
+
await deleteTableData(this.service, TABLE_SCORERS);
|
|
1865
1843
|
}
|
|
1866
1844
|
/**
|
|
1867
|
-
*
|
|
1868
|
-
* This is necessary because ElectroDB validation happens before setters are applied
|
|
1869
|
-
*/
|
|
1870
|
-
preprocessRecord(record) {
|
|
1871
|
-
const processed = { ...record };
|
|
1872
|
-
if (processed.createdAt instanceof Date) {
|
|
1873
|
-
processed.createdAt = processed.createdAt.toISOString();
|
|
1874
|
-
}
|
|
1875
|
-
if (processed.updatedAt instanceof Date) {
|
|
1876
|
-
processed.updatedAt = processed.updatedAt.toISOString();
|
|
1877
|
-
}
|
|
1878
|
-
if (processed.created_at instanceof Date) {
|
|
1879
|
-
processed.created_at = processed.created_at.toISOString();
|
|
1880
|
-
}
|
|
1881
|
-
if (processed.result && typeof processed.result === "object") {
|
|
1882
|
-
processed.result = JSON.stringify(processed.result);
|
|
1883
|
-
}
|
|
1884
|
-
if (processed.test_info && typeof processed.test_info === "object") {
|
|
1885
|
-
processed.test_info = JSON.stringify(processed.test_info);
|
|
1886
|
-
} else if (processed.test_info === void 0 || processed.test_info === null) {
|
|
1887
|
-
delete processed.test_info;
|
|
1888
|
-
}
|
|
1889
|
-
if (processed.snapshot && typeof processed.snapshot === "object") {
|
|
1890
|
-
processed.snapshot = JSON.stringify(processed.snapshot);
|
|
1891
|
-
}
|
|
1892
|
-
if (processed.attributes && typeof processed.attributes === "object") {
|
|
1893
|
-
processed.attributes = JSON.stringify(processed.attributes);
|
|
1894
|
-
}
|
|
1895
|
-
if (processed.status && typeof processed.status === "object") {
|
|
1896
|
-
processed.status = JSON.stringify(processed.status);
|
|
1897
|
-
}
|
|
1898
|
-
if (processed.events && typeof processed.events === "object") {
|
|
1899
|
-
processed.events = JSON.stringify(processed.events);
|
|
1900
|
-
}
|
|
1901
|
-
if (processed.links && typeof processed.links === "object") {
|
|
1902
|
-
processed.links = JSON.stringify(processed.links);
|
|
1903
|
-
}
|
|
1904
|
-
return processed;
|
|
1905
|
-
}
|
|
1906
|
-
/**
|
|
1907
|
-
* Validates that the required DynamoDB table exists and is accessible.
|
|
1908
|
-
* This does not check the table structure - it assumes the table
|
|
1909
|
-
* was created with the correct structure via CDK/CloudFormation.
|
|
1910
|
-
*/
|
|
1911
|
-
async validateTableExists() {
|
|
1912
|
-
try {
|
|
1913
|
-
const command = new DescribeTableCommand({
|
|
1914
|
-
TableName: this.tableName
|
|
1915
|
-
});
|
|
1916
|
-
await this.client.send(command);
|
|
1917
|
-
return true;
|
|
1918
|
-
} catch (error) {
|
|
1919
|
-
if (error.name === "ResourceNotFoundException") {
|
|
1920
|
-
return false;
|
|
1921
|
-
}
|
|
1922
|
-
throw new MastraError(
|
|
1923
|
-
{
|
|
1924
|
-
id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
|
|
1925
|
-
domain: ErrorDomain.STORAGE,
|
|
1926
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1927
|
-
details: { tableName: this.tableName }
|
|
1928
|
-
},
|
|
1929
|
-
error
|
|
1930
|
-
);
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
/**
|
|
1934
|
-
* This method is modified for DynamoDB with ElectroDB single-table design.
|
|
1935
|
-
* It assumes the table is created and managed externally via CDK/CloudFormation.
|
|
1845
|
+
* DynamoDB-specific score row transformation.
|
|
1936
1846
|
*
|
|
1937
|
-
* This implementation
|
|
1938
|
-
*
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
this.logger.debug("Validating access to externally managed table", { tableName, physicalTable: this.tableName });
|
|
1942
|
-
try {
|
|
1943
|
-
const tableExists = await this.validateTableExists();
|
|
1944
|
-
if (!tableExists) {
|
|
1945
|
-
this.logger.error(
|
|
1946
|
-
`Table ${this.tableName} does not exist or is not accessible. It should be created via CDK/CloudFormation.`
|
|
1947
|
-
);
|
|
1948
|
-
throw new Error(
|
|
1949
|
-
`Table ${this.tableName} does not exist or is not accessible. Ensure it's created via CDK/CloudFormation before using this store.`
|
|
1950
|
-
);
|
|
1951
|
-
}
|
|
1952
|
-
this.logger.debug(`Table ${this.tableName} exists and is accessible`);
|
|
1953
|
-
} catch (error) {
|
|
1954
|
-
this.logger.error("Error validating table access", { tableName: this.tableName, error });
|
|
1955
|
-
throw new MastraError(
|
|
1956
|
-
{
|
|
1957
|
-
id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_ACCESS_FAILED",
|
|
1958
|
-
domain: ErrorDomain.STORAGE,
|
|
1959
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1960
|
-
details: { tableName: this.tableName }
|
|
1961
|
-
},
|
|
1962
|
-
error
|
|
1963
|
-
);
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
|
-
async insert({ tableName, record }) {
|
|
1967
|
-
this.logger.debug("DynamoDB insert called", { tableName });
|
|
1968
|
-
const entityName = this.getEntityNameForTable(tableName);
|
|
1969
|
-
if (!entityName || !this.service.entities[entityName]) {
|
|
1970
|
-
throw new MastraError({
|
|
1971
|
-
id: "STORAGE_DYNAMODB_STORE_INSERT_INVALID_ARGS",
|
|
1972
|
-
domain: ErrorDomain.STORAGE,
|
|
1973
|
-
category: ErrorCategory.USER,
|
|
1974
|
-
text: "No entity defined for tableName",
|
|
1975
|
-
details: { tableName }
|
|
1976
|
-
});
|
|
1977
|
-
}
|
|
1978
|
-
try {
|
|
1979
|
-
const dataToSave = { entity: entityName, ...this.preprocessRecord(record) };
|
|
1980
|
-
await this.service.entities[entityName].create(dataToSave).go();
|
|
1981
|
-
} catch (error) {
|
|
1982
|
-
throw new MastraError(
|
|
1983
|
-
{
|
|
1984
|
-
id: "STORAGE_DYNAMODB_STORE_INSERT_FAILED",
|
|
1985
|
-
domain: ErrorDomain.STORAGE,
|
|
1986
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1987
|
-
details: { tableName }
|
|
1988
|
-
},
|
|
1989
|
-
error
|
|
1990
|
-
);
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
async alterTable(_args) {
|
|
1994
|
-
}
|
|
1995
|
-
/**
|
|
1996
|
-
* Clear all items from a logical "table" (entity type)
|
|
1997
|
-
*/
|
|
1998
|
-
async clearTable({ tableName }) {
|
|
1999
|
-
this.logger.debug("DynamoDB clearTable called", { tableName });
|
|
2000
|
-
const entityName = this.getEntityNameForTable(tableName);
|
|
2001
|
-
if (!entityName || !this.service.entities[entityName]) {
|
|
2002
|
-
throw new MastraError({
|
|
2003
|
-
id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_INVALID_ARGS",
|
|
2004
|
-
domain: ErrorDomain.STORAGE,
|
|
2005
|
-
category: ErrorCategory.USER,
|
|
2006
|
-
text: "No entity defined for tableName",
|
|
2007
|
-
details: { tableName }
|
|
2008
|
-
});
|
|
2009
|
-
}
|
|
2010
|
-
try {
|
|
2011
|
-
const result = await this.service.entities[entityName].scan.go({ pages: "all" });
|
|
2012
|
-
if (!result.data.length) {
|
|
2013
|
-
this.logger.debug(`No records found to clear for ${tableName}`);
|
|
2014
|
-
return;
|
|
2015
|
-
}
|
|
2016
|
-
this.logger.debug(`Found ${result.data.length} records to delete for ${tableName}`);
|
|
2017
|
-
const keysToDelete = result.data.map((item) => {
|
|
2018
|
-
const key = { entity: entityName };
|
|
2019
|
-
switch (entityName) {
|
|
2020
|
-
case "thread":
|
|
2021
|
-
if (!item.id) throw new Error(`Missing required key 'id' for entity 'thread'`);
|
|
2022
|
-
key.id = item.id;
|
|
2023
|
-
break;
|
|
2024
|
-
case "message":
|
|
2025
|
-
if (!item.id) throw new Error(`Missing required key 'id' for entity 'message'`);
|
|
2026
|
-
key.id = item.id;
|
|
2027
|
-
break;
|
|
2028
|
-
case "workflow_snapshot":
|
|
2029
|
-
if (!item.workflow_name)
|
|
2030
|
-
throw new Error(`Missing required key 'workflow_name' for entity 'workflow_snapshot'`);
|
|
2031
|
-
if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'workflow_snapshot'`);
|
|
2032
|
-
key.workflow_name = item.workflow_name;
|
|
2033
|
-
key.run_id = item.run_id;
|
|
2034
|
-
break;
|
|
2035
|
-
case "eval":
|
|
2036
|
-
if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'eval'`);
|
|
2037
|
-
key.run_id = item.run_id;
|
|
2038
|
-
break;
|
|
2039
|
-
case "trace":
|
|
2040
|
-
if (!item.id) throw new Error(`Missing required key 'id' for entity 'trace'`);
|
|
2041
|
-
key.id = item.id;
|
|
2042
|
-
break;
|
|
2043
|
-
case "score":
|
|
2044
|
-
if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
|
|
2045
|
-
key.id = item.id;
|
|
2046
|
-
break;
|
|
2047
|
-
default:
|
|
2048
|
-
this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
|
|
2049
|
-
throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
|
|
2050
|
-
}
|
|
2051
|
-
return key;
|
|
2052
|
-
});
|
|
2053
|
-
const batchSize = 25;
|
|
2054
|
-
for (let i = 0; i < keysToDelete.length; i += batchSize) {
|
|
2055
|
-
const batchKeys = keysToDelete.slice(i, i + batchSize);
|
|
2056
|
-
await this.service.entities[entityName].delete(batchKeys).go();
|
|
2057
|
-
}
|
|
2058
|
-
this.logger.debug(`Successfully cleared all records for ${tableName}`);
|
|
2059
|
-
} catch (error) {
|
|
2060
|
-
throw new MastraError(
|
|
2061
|
-
{
|
|
2062
|
-
id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_FAILED",
|
|
2063
|
-
domain: ErrorDomain.STORAGE,
|
|
2064
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
2065
|
-
details: { tableName }
|
|
2066
|
-
},
|
|
2067
|
-
error
|
|
2068
|
-
);
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
/**
|
|
2072
|
-
* Insert multiple records as a batch
|
|
1847
|
+
* Note: This implementation does NOT use coreTransformScoreRow because:
|
|
1848
|
+
* 1. ElectroDB already parses JSON fields via its entity getters
|
|
1849
|
+
* 2. DynamoDB stores empty strings for null values (which need special handling)
|
|
1850
|
+
* 3. 'entity' is a reserved ElectroDB key, so we use 'entityData' column
|
|
2073
1851
|
*/
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
const
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
domain: ErrorDomain.STORAGE,
|
|
2081
|
-
category: ErrorCategory.USER,
|
|
2082
|
-
text: "No entity defined for tableName",
|
|
2083
|
-
details: { tableName }
|
|
2084
|
-
});
|
|
2085
|
-
}
|
|
2086
|
-
const recordsToSave = records.map((rec) => ({ entity: entityName, ...this.preprocessRecord(rec) }));
|
|
2087
|
-
const batchSize = 25;
|
|
2088
|
-
const batches = [];
|
|
2089
|
-
for (let i = 0; i < recordsToSave.length; i += batchSize) {
|
|
2090
|
-
const batch = recordsToSave.slice(i, i + batchSize);
|
|
2091
|
-
batches.push(batch);
|
|
2092
|
-
}
|
|
2093
|
-
try {
|
|
2094
|
-
for (const batch of batches) {
|
|
2095
|
-
for (const recordData of batch) {
|
|
2096
|
-
if (!recordData.entity) {
|
|
2097
|
-
this.logger.error("Missing entity property in record data for batchInsert", { recordData, tableName });
|
|
2098
|
-
throw new Error(`Internal error: Missing entity property during batchInsert for ${tableName}`);
|
|
2099
|
-
}
|
|
2100
|
-
this.logger.debug("Attempting to create record in batchInsert:", { entityName, recordData });
|
|
2101
|
-
await this.service.entities[entityName].create(recordData).go();
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
} catch (error) {
|
|
2105
|
-
throw new MastraError(
|
|
2106
|
-
{
|
|
2107
|
-
id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_FAILED",
|
|
2108
|
-
domain: ErrorDomain.STORAGE,
|
|
2109
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
2110
|
-
details: { tableName }
|
|
2111
|
-
},
|
|
2112
|
-
error
|
|
2113
|
-
);
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
/**
|
|
2117
|
-
* Load a record by its keys
|
|
2118
|
-
*/
|
|
2119
|
-
async load({ tableName, keys }) {
|
|
2120
|
-
this.logger.debug("DynamoDB load called", { tableName, keys });
|
|
2121
|
-
const entityName = this.getEntityNameForTable(tableName);
|
|
2122
|
-
if (!entityName || !this.service.entities[entityName]) {
|
|
2123
|
-
throw new MastraError({
|
|
2124
|
-
id: "STORAGE_DYNAMODB_STORE_LOAD_INVALID_ARGS",
|
|
2125
|
-
domain: ErrorDomain.STORAGE,
|
|
2126
|
-
category: ErrorCategory.USER,
|
|
2127
|
-
text: "No entity defined for tableName",
|
|
2128
|
-
details: { tableName }
|
|
2129
|
-
});
|
|
2130
|
-
}
|
|
2131
|
-
try {
|
|
2132
|
-
const keyObject = { entity: entityName, ...keys };
|
|
2133
|
-
const result = await this.service.entities[entityName].get(keyObject).go();
|
|
2134
|
-
if (!result.data) {
|
|
2135
|
-
return null;
|
|
1852
|
+
parseScoreData(data) {
|
|
1853
|
+
const result = {};
|
|
1854
|
+
for (const key of Object.keys(SCORERS_SCHEMA)) {
|
|
1855
|
+
if (["traceId", "resourceId", "threadId", "spanId"].includes(key)) {
|
|
1856
|
+
result[key] = data[key] === "" ? null : data[key];
|
|
1857
|
+
continue;
|
|
2136
1858
|
}
|
|
2137
|
-
|
|
2138
|
-
return data;
|
|
2139
|
-
} catch (error) {
|
|
2140
|
-
throw new MastraError(
|
|
2141
|
-
{
|
|
2142
|
-
id: "STORAGE_DYNAMODB_STORE_LOAD_FAILED",
|
|
2143
|
-
domain: ErrorDomain.STORAGE,
|
|
2144
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
2145
|
-
details: { tableName }
|
|
2146
|
-
},
|
|
2147
|
-
error
|
|
2148
|
-
);
|
|
1859
|
+
result[key] = data[key];
|
|
2149
1860
|
}
|
|
2150
|
-
|
|
2151
|
-
};
|
|
2152
|
-
var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
2153
|
-
service;
|
|
2154
|
-
constructor({ service }) {
|
|
2155
|
-
super();
|
|
2156
|
-
this.service = service;
|
|
2157
|
-
}
|
|
2158
|
-
// Helper function to parse score data (handle JSON fields)
|
|
2159
|
-
parseScoreData(data) {
|
|
1861
|
+
result.entity = data.entityData ?? null;
|
|
2160
1862
|
return {
|
|
2161
|
-
...
|
|
2162
|
-
// Convert date strings back to Date objects for consistency
|
|
1863
|
+
...result,
|
|
2163
1864
|
createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
|
|
2164
1865
|
updatedAt: data.updatedAt ? new Date(data.updatedAt) : /* @__PURE__ */ new Date()
|
|
2165
|
-
// JSON fields are already transformed by the entity's getters
|
|
2166
1866
|
};
|
|
2167
1867
|
}
|
|
2168
1868
|
async getScoreById({ id }) {
|
|
@@ -2176,7 +1876,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2176
1876
|
} catch (error) {
|
|
2177
1877
|
throw new MastraError(
|
|
2178
1878
|
{
|
|
2179
|
-
id: "
|
|
1879
|
+
id: createStorageErrorId("DYNAMODB", "GET_SCORE_BY_ID", "FAILED"),
|
|
2180
1880
|
domain: ErrorDomain.STORAGE,
|
|
2181
1881
|
category: ErrorCategory.THIRD_PARTY,
|
|
2182
1882
|
details: { id }
|
|
@@ -2192,57 +1892,68 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2192
1892
|
} catch (error) {
|
|
2193
1893
|
throw new MastraError(
|
|
2194
1894
|
{
|
|
2195
|
-
id: "
|
|
1895
|
+
id: createStorageErrorId("DYNAMODB", "SAVE_SCORE", "VALIDATION_FAILED"),
|
|
2196
1896
|
domain: ErrorDomain.STORAGE,
|
|
2197
|
-
category: ErrorCategory.
|
|
1897
|
+
category: ErrorCategory.USER,
|
|
1898
|
+
details: {
|
|
1899
|
+
scorer: typeof score.scorer?.id === "string" ? score.scorer.id : String(score.scorer?.id ?? "unknown"),
|
|
1900
|
+
entityId: score.entityId ?? "unknown",
|
|
1901
|
+
entityType: score.entityType ?? "unknown",
|
|
1902
|
+
traceId: score.traceId ?? "",
|
|
1903
|
+
spanId: score.spanId ?? ""
|
|
1904
|
+
}
|
|
2198
1905
|
},
|
|
2199
1906
|
error
|
|
2200
1907
|
);
|
|
2201
1908
|
}
|
|
2202
1909
|
const now = /* @__PURE__ */ new Date();
|
|
2203
|
-
const scoreId =
|
|
2204
|
-
const
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
1910
|
+
const scoreId = crypto.randomUUID();
|
|
1911
|
+
const scorer = typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer);
|
|
1912
|
+
const preprocessStepResult = typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult);
|
|
1913
|
+
const analyzeStepResult = typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult);
|
|
1914
|
+
const input = typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input);
|
|
1915
|
+
const output = typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output);
|
|
1916
|
+
const requestContext = typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext);
|
|
1917
|
+
const entity = typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity);
|
|
1918
|
+
const metadata = typeof validatedScore.metadata === "string" ? validatedScore.metadata : validatedScore.metadata ? JSON.stringify(validatedScore.metadata) : void 0;
|
|
1919
|
+
const additionalContext = typeof validatedScore.additionalContext === "string" ? validatedScore.additionalContext : validatedScore.additionalContext ? JSON.stringify(validatedScore.additionalContext) : void 0;
|
|
1920
|
+
const scoreData = Object.fromEntries(
|
|
1921
|
+
Object.entries({
|
|
1922
|
+
...validatedScore,
|
|
1923
|
+
entity: "score",
|
|
1924
|
+
id: scoreId,
|
|
1925
|
+
scorer,
|
|
1926
|
+
preprocessStepResult,
|
|
1927
|
+
analyzeStepResult,
|
|
1928
|
+
input,
|
|
1929
|
+
output,
|
|
1930
|
+
requestContext,
|
|
1931
|
+
metadata,
|
|
1932
|
+
additionalContext,
|
|
1933
|
+
entityData: entity,
|
|
1934
|
+
traceId: validatedScore.traceId || "",
|
|
1935
|
+
resourceId: validatedScore.resourceId || "",
|
|
1936
|
+
threadId: validatedScore.threadId || "",
|
|
1937
|
+
spanId: validatedScore.spanId || "",
|
|
1938
|
+
createdAt: now.toISOString(),
|
|
1939
|
+
updatedAt: now.toISOString(),
|
|
1940
|
+
...getTtlProps("score", this.ttlConfig)
|
|
1941
|
+
}).filter(([_, value]) => value !== void 0 && value !== null)
|
|
1942
|
+
);
|
|
2233
1943
|
try {
|
|
2234
1944
|
await this.service.entities.score.upsert(scoreData).go();
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
1945
|
+
return {
|
|
1946
|
+
score: {
|
|
1947
|
+
...validatedScore,
|
|
1948
|
+
id: scoreId,
|
|
1949
|
+
createdAt: now,
|
|
1950
|
+
updatedAt: now
|
|
1951
|
+
}
|
|
2240
1952
|
};
|
|
2241
|
-
return { score: savedScore };
|
|
2242
1953
|
} catch (error) {
|
|
2243
1954
|
throw new MastraError(
|
|
2244
1955
|
{
|
|
2245
|
-
id: "
|
|
1956
|
+
id: createStorageErrorId("DYNAMODB", "SAVE_SCORE", "FAILED"),
|
|
2246
1957
|
domain: ErrorDomain.STORAGE,
|
|
2247
1958
|
category: ErrorCategory.THIRD_PARTY,
|
|
2248
1959
|
details: { scorerId: score.scorerId, runId: score.runId }
|
|
@@ -2251,7 +1962,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2251
1962
|
);
|
|
2252
1963
|
}
|
|
2253
1964
|
}
|
|
2254
|
-
async
|
|
1965
|
+
async listScoresByScorerId({
|
|
2255
1966
|
scorerId,
|
|
2256
1967
|
pagination,
|
|
2257
1968
|
entityId,
|
|
@@ -2272,24 +1983,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2272
1983
|
allScores = allScores.filter((score) => score.source === source);
|
|
2273
1984
|
}
|
|
2274
1985
|
allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
2275
|
-
const
|
|
2276
|
-
const
|
|
2277
|
-
const
|
|
1986
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1987
|
+
const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
|
|
1988
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2278
1989
|
const total = allScores.length;
|
|
2279
|
-
const
|
|
1990
|
+
const end = perPageInput === false ? allScores.length : start + perPage;
|
|
1991
|
+
const paginatedScores = allScores.slice(start, end);
|
|
2280
1992
|
return {
|
|
2281
1993
|
scores: paginatedScores,
|
|
2282
1994
|
pagination: {
|
|
2283
1995
|
total,
|
|
2284
|
-
page
|
|
2285
|
-
perPage:
|
|
2286
|
-
hasMore
|
|
1996
|
+
page,
|
|
1997
|
+
perPage: perPageForResponse,
|
|
1998
|
+
hasMore: end < total
|
|
2287
1999
|
}
|
|
2288
2000
|
};
|
|
2289
2001
|
} catch (error) {
|
|
2290
2002
|
throw new MastraError(
|
|
2291
2003
|
{
|
|
2292
|
-
id: "
|
|
2004
|
+
id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
|
|
2293
2005
|
domain: ErrorDomain.STORAGE,
|
|
2294
2006
|
category: ErrorCategory.THIRD_PARTY,
|
|
2295
2007
|
details: {
|
|
@@ -2305,7 +2017,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2305
2017
|
);
|
|
2306
2018
|
}
|
|
2307
2019
|
}
|
|
2308
|
-
async
|
|
2020
|
+
async listScoresByRunId({
|
|
2309
2021
|
runId,
|
|
2310
2022
|
pagination
|
|
2311
2023
|
}) {
|
|
@@ -2315,24 +2027,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2315
2027
|
const results = await query.go();
|
|
2316
2028
|
const allScores = results.data.map((data) => this.parseScoreData(data));
|
|
2317
2029
|
allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
2318
|
-
const
|
|
2319
|
-
const
|
|
2320
|
-
const
|
|
2030
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2031
|
+
const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
|
|
2032
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2321
2033
|
const total = allScores.length;
|
|
2322
|
-
const
|
|
2034
|
+
const end = perPageInput === false ? allScores.length : start + perPage;
|
|
2035
|
+
const paginatedScores = allScores.slice(start, end);
|
|
2323
2036
|
return {
|
|
2324
2037
|
scores: paginatedScores,
|
|
2325
2038
|
pagination: {
|
|
2326
2039
|
total,
|
|
2327
|
-
page
|
|
2328
|
-
perPage:
|
|
2329
|
-
hasMore
|
|
2040
|
+
page,
|
|
2041
|
+
perPage: perPageForResponse,
|
|
2042
|
+
hasMore: end < total
|
|
2330
2043
|
}
|
|
2331
2044
|
};
|
|
2332
2045
|
} catch (error) {
|
|
2333
2046
|
throw new MastraError(
|
|
2334
2047
|
{
|
|
2335
|
-
id: "
|
|
2048
|
+
id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_RUN_ID", "FAILED"),
|
|
2336
2049
|
domain: ErrorDomain.STORAGE,
|
|
2337
2050
|
category: ErrorCategory.THIRD_PARTY,
|
|
2338
2051
|
details: { runId, page: pagination.page, perPage: pagination.perPage }
|
|
@@ -2341,7 +2054,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2341
2054
|
);
|
|
2342
2055
|
}
|
|
2343
2056
|
}
|
|
2344
|
-
async
|
|
2057
|
+
async listScoresByEntityId({
|
|
2345
2058
|
entityId,
|
|
2346
2059
|
entityType,
|
|
2347
2060
|
pagination
|
|
@@ -2353,24 +2066,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2353
2066
|
let allScores = results.data.map((data) => this.parseScoreData(data));
|
|
2354
2067
|
allScores = allScores.filter((score) => score.entityType === entityType);
|
|
2355
2068
|
allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
2356
|
-
const
|
|
2357
|
-
const
|
|
2358
|
-
const
|
|
2069
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2070
|
+
const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
|
|
2071
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2359
2072
|
const total = allScores.length;
|
|
2360
|
-
const
|
|
2073
|
+
const end = perPageInput === false ? allScores.length : start + perPage;
|
|
2074
|
+
const paginatedScores = allScores.slice(start, end);
|
|
2361
2075
|
return {
|
|
2362
2076
|
scores: paginatedScores,
|
|
2363
2077
|
pagination: {
|
|
2364
2078
|
total,
|
|
2365
|
-
page
|
|
2366
|
-
perPage:
|
|
2367
|
-
hasMore
|
|
2079
|
+
page,
|
|
2080
|
+
perPage: perPageForResponse,
|
|
2081
|
+
hasMore: end < total
|
|
2368
2082
|
}
|
|
2369
2083
|
};
|
|
2370
2084
|
} catch (error) {
|
|
2371
2085
|
throw new MastraError(
|
|
2372
2086
|
{
|
|
2373
|
-
id: "
|
|
2087
|
+
id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
|
|
2374
2088
|
domain: ErrorDomain.STORAGE,
|
|
2375
2089
|
category: ErrorCategory.THIRD_PARTY,
|
|
2376
2090
|
details: { entityId, entityType, page: pagination.page, perPage: pagination.perPage }
|
|
@@ -2379,7 +2093,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2379
2093
|
);
|
|
2380
2094
|
}
|
|
2381
2095
|
}
|
|
2382
|
-
async
|
|
2096
|
+
async listScoresBySpan({
|
|
2383
2097
|
traceId,
|
|
2384
2098
|
spanId,
|
|
2385
2099
|
pagination
|
|
@@ -2390,24 +2104,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2390
2104
|
const results = await query.go();
|
|
2391
2105
|
const allScores = results.data.map((data) => this.parseScoreData(data));
|
|
2392
2106
|
allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
2393
|
-
const
|
|
2394
|
-
const
|
|
2395
|
-
const
|
|
2107
|
+
const { page, perPage: perPageInput } = pagination;
|
|
2108
|
+
const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
|
|
2109
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
2396
2110
|
const total = allScores.length;
|
|
2397
|
-
const
|
|
2111
|
+
const end = perPageInput === false ? allScores.length : start + perPage;
|
|
2112
|
+
const paginatedScores = allScores.slice(start, end);
|
|
2398
2113
|
return {
|
|
2399
2114
|
scores: paginatedScores,
|
|
2400
2115
|
pagination: {
|
|
2401
2116
|
total,
|
|
2402
|
-
page
|
|
2403
|
-
perPage:
|
|
2404
|
-
hasMore
|
|
2117
|
+
page,
|
|
2118
|
+
perPage: perPageForResponse,
|
|
2119
|
+
hasMore: end < total
|
|
2405
2120
|
}
|
|
2406
2121
|
};
|
|
2407
2122
|
} catch (error) {
|
|
2408
2123
|
throw new MastraError(
|
|
2409
2124
|
{
|
|
2410
|
-
id: "
|
|
2125
|
+
id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_SPAN", "FAILED"),
|
|
2411
2126
|
domain: ErrorDomain.STORAGE,
|
|
2412
2127
|
category: ErrorCategory.THIRD_PARTY,
|
|
2413
2128
|
details: { traceId, spanId, page: pagination.page, perPage: pagination.perPage }
|
|
@@ -2417,239 +2132,6 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
|
|
|
2417
2132
|
}
|
|
2418
2133
|
}
|
|
2419
2134
|
};
|
|
2420
|
-
var TracesStorageDynamoDB = class extends TracesStorage {
|
|
2421
|
-
service;
|
|
2422
|
-
operations;
|
|
2423
|
-
constructor({ service, operations }) {
|
|
2424
|
-
super();
|
|
2425
|
-
this.service = service;
|
|
2426
|
-
this.operations = operations;
|
|
2427
|
-
}
|
|
2428
|
-
// Trace operations
|
|
2429
|
-
async getTraces(args) {
|
|
2430
|
-
const { name, scope, page, perPage } = args;
|
|
2431
|
-
this.logger.debug("Getting traces", { name, scope, page, perPage });
|
|
2432
|
-
try {
|
|
2433
|
-
let query;
|
|
2434
|
-
if (name) {
|
|
2435
|
-
query = this.service.entities.trace.query.byName({ entity: "trace", name });
|
|
2436
|
-
} else if (scope) {
|
|
2437
|
-
query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
|
|
2438
|
-
} else {
|
|
2439
|
-
this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
|
|
2440
|
-
query = this.service.entities.trace.scan;
|
|
2441
|
-
}
|
|
2442
|
-
let items = [];
|
|
2443
|
-
let cursor = null;
|
|
2444
|
-
let pagesFetched = 0;
|
|
2445
|
-
const startPage = page > 0 ? page : 1;
|
|
2446
|
-
do {
|
|
2447
|
-
const results = await query.go({ cursor, limit: perPage });
|
|
2448
|
-
pagesFetched++;
|
|
2449
|
-
if (pagesFetched === startPage) {
|
|
2450
|
-
items = results.data;
|
|
2451
|
-
break;
|
|
2452
|
-
}
|
|
2453
|
-
cursor = results.cursor;
|
|
2454
|
-
if (!cursor && results.data.length > 0 && pagesFetched < startPage) {
|
|
2455
|
-
break;
|
|
2456
|
-
}
|
|
2457
|
-
} while (cursor && pagesFetched < startPage);
|
|
2458
|
-
return items;
|
|
2459
|
-
} catch (error) {
|
|
2460
|
-
throw new MastraError(
|
|
2461
|
-
{
|
|
2462
|
-
id: "STORAGE_DYNAMODB_STORE_GET_TRACES_FAILED",
|
|
2463
|
-
domain: ErrorDomain.STORAGE,
|
|
2464
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2465
|
-
},
|
|
2466
|
-
error
|
|
2467
|
-
);
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
async batchTraceInsert({ records }) {
|
|
2471
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
2472
|
-
if (!records.length) {
|
|
2473
|
-
return;
|
|
2474
|
-
}
|
|
2475
|
-
try {
|
|
2476
|
-
const recordsToSave = records.map((rec) => ({ entity: "trace", ...rec }));
|
|
2477
|
-
await this.operations.batchInsert({
|
|
2478
|
-
tableName: TABLE_TRACES,
|
|
2479
|
-
records: recordsToSave
|
|
2480
|
-
// Pass records with 'entity' included
|
|
2481
|
-
});
|
|
2482
|
-
} catch (error) {
|
|
2483
|
-
throw new MastraError(
|
|
2484
|
-
{
|
|
2485
|
-
id: "STORAGE_DYNAMODB_STORE_BATCH_TRACE_INSERT_FAILED",
|
|
2486
|
-
domain: ErrorDomain.STORAGE,
|
|
2487
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
2488
|
-
details: { count: records.length }
|
|
2489
|
-
},
|
|
2490
|
-
error
|
|
2491
|
-
);
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
async getTracesPaginated(args) {
|
|
2495
|
-
const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
|
|
2496
|
-
this.logger.debug("Getting traces with pagination", { name, scope, page, perPage, attributes, filters, dateRange });
|
|
2497
|
-
try {
|
|
2498
|
-
let query;
|
|
2499
|
-
if (name) {
|
|
2500
|
-
query = this.service.entities.trace.query.byName({ entity: "trace", name });
|
|
2501
|
-
} else if (scope) {
|
|
2502
|
-
query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
|
|
2503
|
-
} else {
|
|
2504
|
-
this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
|
|
2505
|
-
query = this.service.entities.trace.scan;
|
|
2506
|
-
}
|
|
2507
|
-
const results = await query.go({
|
|
2508
|
-
order: "desc",
|
|
2509
|
-
pages: "all"
|
|
2510
|
-
// Get all pages to apply filtering and pagination
|
|
2511
|
-
});
|
|
2512
|
-
if (!results.data.length) {
|
|
2513
|
-
return {
|
|
2514
|
-
traces: [],
|
|
2515
|
-
total: 0,
|
|
2516
|
-
page,
|
|
2517
|
-
perPage,
|
|
2518
|
-
hasMore: false
|
|
2519
|
-
};
|
|
2520
|
-
}
|
|
2521
|
-
let filteredData = results.data;
|
|
2522
|
-
if (attributes) {
|
|
2523
|
-
filteredData = filteredData.filter((item) => {
|
|
2524
|
-
try {
|
|
2525
|
-
let itemAttributes = {};
|
|
2526
|
-
if (item.attributes) {
|
|
2527
|
-
if (typeof item.attributes === "string") {
|
|
2528
|
-
if (item.attributes === "[object Object]") {
|
|
2529
|
-
itemAttributes = {};
|
|
2530
|
-
} else {
|
|
2531
|
-
try {
|
|
2532
|
-
itemAttributes = JSON.parse(item.attributes);
|
|
2533
|
-
} catch {
|
|
2534
|
-
itemAttributes = {};
|
|
2535
|
-
}
|
|
2536
|
-
}
|
|
2537
|
-
} else if (typeof item.attributes === "object") {
|
|
2538
|
-
itemAttributes = item.attributes;
|
|
2539
|
-
}
|
|
2540
|
-
}
|
|
2541
|
-
return Object.entries(attributes).every(([key, value]) => itemAttributes[key] === value);
|
|
2542
|
-
} catch (e) {
|
|
2543
|
-
this.logger.warn("Failed to parse attributes during filtering", { item, error: e });
|
|
2544
|
-
return false;
|
|
2545
|
-
}
|
|
2546
|
-
});
|
|
2547
|
-
}
|
|
2548
|
-
if (dateRange?.start) {
|
|
2549
|
-
filteredData = filteredData.filter((item) => {
|
|
2550
|
-
const itemDate = new Date(item.createdAt);
|
|
2551
|
-
return itemDate >= dateRange.start;
|
|
2552
|
-
});
|
|
2553
|
-
}
|
|
2554
|
-
if (dateRange?.end) {
|
|
2555
|
-
filteredData = filteredData.filter((item) => {
|
|
2556
|
-
const itemDate = new Date(item.createdAt);
|
|
2557
|
-
return itemDate <= dateRange.end;
|
|
2558
|
-
});
|
|
2559
|
-
}
|
|
2560
|
-
const total = filteredData.length;
|
|
2561
|
-
const start = page * perPage;
|
|
2562
|
-
const end = start + perPage;
|
|
2563
|
-
const paginatedData = filteredData.slice(start, end);
|
|
2564
|
-
const traces = paginatedData.map((item) => {
|
|
2565
|
-
let attributes2;
|
|
2566
|
-
if (item.attributes) {
|
|
2567
|
-
if (typeof item.attributes === "string") {
|
|
2568
|
-
if (item.attributes === "[object Object]") {
|
|
2569
|
-
attributes2 = void 0;
|
|
2570
|
-
} else {
|
|
2571
|
-
try {
|
|
2572
|
-
attributes2 = JSON.parse(item.attributes);
|
|
2573
|
-
} catch {
|
|
2574
|
-
attributes2 = void 0;
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
} else if (typeof item.attributes === "object") {
|
|
2578
|
-
attributes2 = item.attributes;
|
|
2579
|
-
}
|
|
2580
|
-
}
|
|
2581
|
-
let status;
|
|
2582
|
-
if (item.status) {
|
|
2583
|
-
if (typeof item.status === "string") {
|
|
2584
|
-
try {
|
|
2585
|
-
status = JSON.parse(item.status);
|
|
2586
|
-
} catch {
|
|
2587
|
-
status = void 0;
|
|
2588
|
-
}
|
|
2589
|
-
} else if (typeof item.status === "object") {
|
|
2590
|
-
status = item.status;
|
|
2591
|
-
}
|
|
2592
|
-
}
|
|
2593
|
-
let events;
|
|
2594
|
-
if (item.events) {
|
|
2595
|
-
if (typeof item.events === "string") {
|
|
2596
|
-
try {
|
|
2597
|
-
events = JSON.parse(item.events);
|
|
2598
|
-
} catch {
|
|
2599
|
-
events = void 0;
|
|
2600
|
-
}
|
|
2601
|
-
} else if (Array.isArray(item.events)) {
|
|
2602
|
-
events = item.events;
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
let links;
|
|
2606
|
-
if (item.links) {
|
|
2607
|
-
if (typeof item.links === "string") {
|
|
2608
|
-
try {
|
|
2609
|
-
links = JSON.parse(item.links);
|
|
2610
|
-
} catch {
|
|
2611
|
-
links = void 0;
|
|
2612
|
-
}
|
|
2613
|
-
} else if (Array.isArray(item.links)) {
|
|
2614
|
-
links = item.links;
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
return {
|
|
2618
|
-
id: item.id,
|
|
2619
|
-
parentSpanId: item.parentSpanId,
|
|
2620
|
-
name: item.name,
|
|
2621
|
-
traceId: item.traceId,
|
|
2622
|
-
scope: item.scope,
|
|
2623
|
-
kind: item.kind,
|
|
2624
|
-
attributes: attributes2,
|
|
2625
|
-
status,
|
|
2626
|
-
events,
|
|
2627
|
-
links,
|
|
2628
|
-
other: item.other,
|
|
2629
|
-
startTime: item.startTime,
|
|
2630
|
-
endTime: item.endTime,
|
|
2631
|
-
createdAt: item.createdAt
|
|
2632
|
-
};
|
|
2633
|
-
});
|
|
2634
|
-
return {
|
|
2635
|
-
traces,
|
|
2636
|
-
total,
|
|
2637
|
-
page,
|
|
2638
|
-
perPage,
|
|
2639
|
-
hasMore: end < total
|
|
2640
|
-
};
|
|
2641
|
-
} catch (error) {
|
|
2642
|
-
throw new MastraError(
|
|
2643
|
-
{
|
|
2644
|
-
id: "STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
2645
|
-
domain: ErrorDomain.STORAGE,
|
|
2646
|
-
category: ErrorCategory.THIRD_PARTY
|
|
2647
|
-
},
|
|
2648
|
-
error
|
|
2649
|
-
);
|
|
2650
|
-
}
|
|
2651
|
-
}
|
|
2652
|
-
};
|
|
2653
2135
|
function formatWorkflowRun(snapshotData) {
|
|
2654
2136
|
return {
|
|
2655
2137
|
workflowName: snapshotData.workflow_name,
|
|
@@ -2660,54 +2142,228 @@ function formatWorkflowRun(snapshotData) {
|
|
|
2660
2142
|
resourceId: snapshotData.resourceId
|
|
2661
2143
|
};
|
|
2662
2144
|
}
|
|
2145
|
+
var MAX_RETRIES = 5;
|
|
2146
|
+
var BASE_DELAY_MS = 50;
|
|
2663
2147
|
var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
2664
2148
|
service;
|
|
2665
|
-
|
|
2149
|
+
ttlConfig;
|
|
2150
|
+
constructor(config) {
|
|
2666
2151
|
super();
|
|
2667
|
-
|
|
2152
|
+
const resolved = resolveDynamoDBConfig(config);
|
|
2153
|
+
this.service = resolved.service;
|
|
2154
|
+
this.ttlConfig = resolved.ttl;
|
|
2155
|
+
}
|
|
2156
|
+
supportsConcurrentUpdates() {
|
|
2157
|
+
return true;
|
|
2158
|
+
}
|
|
2159
|
+
async dangerouslyClearAll() {
|
|
2160
|
+
await deleteTableData(this.service, TABLE_WORKFLOW_SNAPSHOT);
|
|
2161
|
+
}
|
|
2162
|
+
/**
|
|
2163
|
+
* Helper to check if an error is a DynamoDB conditional check failure
|
|
2164
|
+
*/
|
|
2165
|
+
isConditionalCheckFailed(error) {
|
|
2166
|
+
if (error && typeof error === "object") {
|
|
2167
|
+
const err = error;
|
|
2168
|
+
if (err.name === "ConditionalCheckFailedException" || err.code === "ConditionalCheckFailedException" || (err.__type?.includes("ConditionalCheckFailedException") ?? false)) {
|
|
2169
|
+
return true;
|
|
2170
|
+
}
|
|
2171
|
+
if (err.message?.includes("conditional request failed")) {
|
|
2172
|
+
return true;
|
|
2173
|
+
}
|
|
2174
|
+
if (err.cause && typeof err.cause === "object") {
|
|
2175
|
+
const cause = err.cause;
|
|
2176
|
+
if (cause.name === "ConditionalCheckFailedException" || cause.code === "ConditionalCheckFailedException") {
|
|
2177
|
+
return true;
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
return false;
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* Helper to delay with exponential backoff and jitter
|
|
2185
|
+
*/
|
|
2186
|
+
async delay(attempt) {
|
|
2187
|
+
const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
2188
|
+
const jitter = Math.random() * backoff * 0.5;
|
|
2189
|
+
await new Promise((resolve) => setTimeout(resolve, backoff + jitter));
|
|
2668
2190
|
}
|
|
2669
|
-
updateWorkflowResults({
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2191
|
+
async updateWorkflowResults({
|
|
2192
|
+
workflowName,
|
|
2193
|
+
runId,
|
|
2194
|
+
stepId,
|
|
2195
|
+
result,
|
|
2196
|
+
requestContext
|
|
2675
2197
|
}) {
|
|
2676
|
-
|
|
2198
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
2199
|
+
try {
|
|
2200
|
+
const existingRecord = await this.service.entities.workflow_snapshot.get({
|
|
2201
|
+
entity: "workflow_snapshot",
|
|
2202
|
+
workflow_name: workflowName,
|
|
2203
|
+
run_id: runId
|
|
2204
|
+
}).go();
|
|
2205
|
+
const now = /* @__PURE__ */ new Date();
|
|
2206
|
+
let snapshot;
|
|
2207
|
+
let previousUpdatedAt;
|
|
2208
|
+
if (!existingRecord.data) {
|
|
2209
|
+
snapshot = {
|
|
2210
|
+
context: {},
|
|
2211
|
+
activePaths: [],
|
|
2212
|
+
timestamp: Date.now(),
|
|
2213
|
+
suspendedPaths: {},
|
|
2214
|
+
activeStepsPath: {},
|
|
2215
|
+
resumeLabels: {},
|
|
2216
|
+
serializedStepGraph: [],
|
|
2217
|
+
status: "pending",
|
|
2218
|
+
value: {},
|
|
2219
|
+
waitingPaths: {},
|
|
2220
|
+
runId,
|
|
2221
|
+
requestContext: {}
|
|
2222
|
+
};
|
|
2223
|
+
} else {
|
|
2224
|
+
snapshot = existingRecord.data.snapshot;
|
|
2225
|
+
previousUpdatedAt = existingRecord.data.updatedAt;
|
|
2226
|
+
}
|
|
2227
|
+
snapshot.context[stepId] = result;
|
|
2228
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
2229
|
+
const data = {
|
|
2230
|
+
entity: "workflow_snapshot",
|
|
2231
|
+
workflow_name: workflowName,
|
|
2232
|
+
run_id: runId,
|
|
2233
|
+
snapshot: JSON.stringify(snapshot),
|
|
2234
|
+
createdAt: existingRecord.data?.createdAt ?? now.toISOString(),
|
|
2235
|
+
updatedAt: now.toISOString(),
|
|
2236
|
+
...getTtlProps("workflow_snapshot", this.ttlConfig)
|
|
2237
|
+
};
|
|
2238
|
+
if (previousUpdatedAt) {
|
|
2239
|
+
await this.service.entities.workflow_snapshot.upsert(data).where((attr, op) => op.eq(attr.updatedAt, previousUpdatedAt)).go();
|
|
2240
|
+
} else {
|
|
2241
|
+
await this.service.entities.workflow_snapshot.create(data).where((attr, op) => op.notExists(attr.run_id)).go();
|
|
2242
|
+
}
|
|
2243
|
+
return snapshot.context;
|
|
2244
|
+
} catch (error) {
|
|
2245
|
+
if (this.isConditionalCheckFailed(error)) {
|
|
2246
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
2247
|
+
this.logger.debug(
|
|
2248
|
+
`Optimistic locking conflict in updateWorkflowResults, retrying (attempt ${attempt + 1})`
|
|
2249
|
+
);
|
|
2250
|
+
await this.delay(attempt);
|
|
2251
|
+
continue;
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
if (error instanceof MastraError) throw error;
|
|
2255
|
+
throw new MastraError(
|
|
2256
|
+
{
|
|
2257
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
|
|
2258
|
+
domain: ErrorDomain.STORAGE,
|
|
2259
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2260
|
+
details: { workflowName, runId, stepId }
|
|
2261
|
+
},
|
|
2262
|
+
error
|
|
2263
|
+
);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
throw new MastraError(
|
|
2267
|
+
{
|
|
2268
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_RESULTS", "MAX_RETRIES_EXCEEDED"),
|
|
2269
|
+
domain: ErrorDomain.STORAGE,
|
|
2270
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2271
|
+
details: { workflowName, runId, stepId }
|
|
2272
|
+
},
|
|
2273
|
+
new Error("Max retries exceeded for optimistic locking")
|
|
2274
|
+
);
|
|
2677
2275
|
}
|
|
2678
|
-
updateWorkflowState({
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2276
|
+
async updateWorkflowState({
|
|
2277
|
+
workflowName,
|
|
2278
|
+
runId,
|
|
2279
|
+
opts
|
|
2682
2280
|
}) {
|
|
2683
|
-
|
|
2281
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
2282
|
+
try {
|
|
2283
|
+
const existingRecord = await this.service.entities.workflow_snapshot.get({
|
|
2284
|
+
entity: "workflow_snapshot",
|
|
2285
|
+
workflow_name: workflowName,
|
|
2286
|
+
run_id: runId
|
|
2287
|
+
}).go();
|
|
2288
|
+
if (!existingRecord.data) {
|
|
2289
|
+
return void 0;
|
|
2290
|
+
}
|
|
2291
|
+
const existingSnapshot = existingRecord.data.snapshot;
|
|
2292
|
+
if (!existingSnapshot || !existingSnapshot.context) {
|
|
2293
|
+
return void 0;
|
|
2294
|
+
}
|
|
2295
|
+
const previousUpdatedAt = existingRecord.data.updatedAt;
|
|
2296
|
+
const updatedSnapshot = { ...existingSnapshot, ...opts };
|
|
2297
|
+
const now = /* @__PURE__ */ new Date();
|
|
2298
|
+
const data = {
|
|
2299
|
+
entity: "workflow_snapshot",
|
|
2300
|
+
workflow_name: workflowName,
|
|
2301
|
+
run_id: runId,
|
|
2302
|
+
snapshot: JSON.stringify(updatedSnapshot),
|
|
2303
|
+
createdAt: existingRecord.data.createdAt,
|
|
2304
|
+
updatedAt: now.toISOString(),
|
|
2305
|
+
resourceId: existingRecord.data.resourceId,
|
|
2306
|
+
...getTtlProps("workflow_snapshot", this.ttlConfig)
|
|
2307
|
+
};
|
|
2308
|
+
await this.service.entities.workflow_snapshot.upsert(data).where((attr, op) => op.eq(attr.updatedAt, previousUpdatedAt)).go();
|
|
2309
|
+
return updatedSnapshot;
|
|
2310
|
+
} catch (error) {
|
|
2311
|
+
if (this.isConditionalCheckFailed(error)) {
|
|
2312
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
2313
|
+
this.logger.debug(`Optimistic locking conflict in updateWorkflowState, retrying (attempt ${attempt + 1})`);
|
|
2314
|
+
await this.delay(attempt);
|
|
2315
|
+
continue;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
if (error instanceof MastraError) throw error;
|
|
2319
|
+
throw new MastraError(
|
|
2320
|
+
{
|
|
2321
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_STATE", "FAILED"),
|
|
2322
|
+
domain: ErrorDomain.STORAGE,
|
|
2323
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2324
|
+
details: { workflowName, runId }
|
|
2325
|
+
},
|
|
2326
|
+
error
|
|
2327
|
+
);
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
throw new MastraError(
|
|
2331
|
+
{
|
|
2332
|
+
id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_STATE", "MAX_RETRIES_EXCEEDED"),
|
|
2333
|
+
domain: ErrorDomain.STORAGE,
|
|
2334
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2335
|
+
details: { workflowName, runId }
|
|
2336
|
+
},
|
|
2337
|
+
new Error("Max retries exceeded for optimistic locking")
|
|
2338
|
+
);
|
|
2684
2339
|
}
|
|
2685
2340
|
// Workflow operations
|
|
2686
2341
|
async persistWorkflowSnapshot({
|
|
2687
2342
|
workflowName,
|
|
2688
2343
|
runId,
|
|
2689
2344
|
resourceId,
|
|
2690
|
-
snapshot
|
|
2345
|
+
snapshot,
|
|
2346
|
+
createdAt,
|
|
2347
|
+
updatedAt
|
|
2691
2348
|
}) {
|
|
2692
2349
|
this.logger.debug("Persisting workflow snapshot", { workflowName, runId });
|
|
2693
2350
|
try {
|
|
2694
|
-
const now =
|
|
2351
|
+
const now = /* @__PURE__ */ new Date();
|
|
2695
2352
|
const data = {
|
|
2696
2353
|
entity: "workflow_snapshot",
|
|
2697
|
-
// Add entity type
|
|
2698
2354
|
workflow_name: workflowName,
|
|
2699
2355
|
run_id: runId,
|
|
2700
2356
|
snapshot: JSON.stringify(snapshot),
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2357
|
+
createdAt: (createdAt ?? now).toISOString(),
|
|
2358
|
+
updatedAt: (updatedAt ?? now).toISOString(),
|
|
2359
|
+
resourceId,
|
|
2360
|
+
...getTtlProps("workflow_snapshot", this.ttlConfig)
|
|
2705
2361
|
};
|
|
2706
2362
|
await this.service.entities.workflow_snapshot.upsert(data).go();
|
|
2707
2363
|
} catch (error) {
|
|
2708
2364
|
throw new MastraError(
|
|
2709
2365
|
{
|
|
2710
|
-
id: "
|
|
2366
|
+
id: createStorageErrorId("DYNAMODB", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
2711
2367
|
domain: ErrorDomain.STORAGE,
|
|
2712
2368
|
category: ErrorCategory.THIRD_PARTY,
|
|
2713
2369
|
details: { workflowName, runId }
|
|
@@ -2735,7 +2391,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2735
2391
|
} catch (error) {
|
|
2736
2392
|
throw new MastraError(
|
|
2737
2393
|
{
|
|
2738
|
-
id: "
|
|
2394
|
+
id: createStorageErrorId("DYNAMODB", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
2739
2395
|
domain: ErrorDomain.STORAGE,
|
|
2740
2396
|
category: ErrorCategory.THIRD_PARTY,
|
|
2741
2397
|
details: { workflowName, runId }
|
|
@@ -2744,11 +2400,24 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2744
2400
|
);
|
|
2745
2401
|
}
|
|
2746
2402
|
}
|
|
2747
|
-
async
|
|
2403
|
+
async listWorkflowRuns(args) {
|
|
2748
2404
|
this.logger.debug("Getting workflow runs", { args });
|
|
2749
2405
|
try {
|
|
2750
|
-
const
|
|
2751
|
-
const
|
|
2406
|
+
const perPage = args?.perPage !== void 0 ? args.perPage : 10;
|
|
2407
|
+
const page = args?.page !== void 0 ? args.page : 0;
|
|
2408
|
+
if (page < 0) {
|
|
2409
|
+
throw new MastraError(
|
|
2410
|
+
{
|
|
2411
|
+
id: createStorageErrorId("DYNAMODB", "LIST_WORKFLOW_RUNS", "INVALID_PAGE"),
|
|
2412
|
+
domain: ErrorDomain.STORAGE,
|
|
2413
|
+
category: ErrorCategory.USER,
|
|
2414
|
+
details: { page }
|
|
2415
|
+
},
|
|
2416
|
+
new Error("page must be >= 0")
|
|
2417
|
+
);
|
|
2418
|
+
}
|
|
2419
|
+
const normalizedPerPage = normalizePerPage(perPage, 10);
|
|
2420
|
+
const offset = page * normalizedPerPage;
|
|
2752
2421
|
let query;
|
|
2753
2422
|
if (args?.workflowName) {
|
|
2754
2423
|
query = this.service.entities.workflow_snapshot.query.primary({
|
|
@@ -2770,6 +2439,11 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2770
2439
|
});
|
|
2771
2440
|
if (pageResults.data && pageResults.data.length > 0) {
|
|
2772
2441
|
let pageFilteredData = pageResults.data;
|
|
2442
|
+
if (args?.status) {
|
|
2443
|
+
pageFilteredData = pageFilteredData.filter((snapshot) => {
|
|
2444
|
+
return snapshot.snapshot.status === args.status;
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2773
2447
|
if (args?.fromDate || args?.toDate) {
|
|
2774
2448
|
pageFilteredData = pageFilteredData.filter((snapshot) => {
|
|
2775
2449
|
const createdAt = new Date(snapshot.createdAt);
|
|
@@ -2795,7 +2469,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2795
2469
|
return { runs: [], total: 0 };
|
|
2796
2470
|
}
|
|
2797
2471
|
const total = allMatchingSnapshots.length;
|
|
2798
|
-
const paginatedData = allMatchingSnapshots.slice(offset, offset +
|
|
2472
|
+
const paginatedData = allMatchingSnapshots.slice(offset, offset + normalizedPerPage);
|
|
2799
2473
|
const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
|
|
2800
2474
|
return {
|
|
2801
2475
|
runs,
|
|
@@ -2804,7 +2478,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2804
2478
|
} catch (error) {
|
|
2805
2479
|
throw new MastraError(
|
|
2806
2480
|
{
|
|
2807
|
-
id: "
|
|
2481
|
+
id: createStorageErrorId("DYNAMODB", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
2808
2482
|
domain: ErrorDomain.STORAGE,
|
|
2809
2483
|
category: ErrorCategory.THIRD_PARTY,
|
|
2810
2484
|
details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
|
|
@@ -2858,7 +2532,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2858
2532
|
} catch (error) {
|
|
2859
2533
|
throw new MastraError(
|
|
2860
2534
|
{
|
|
2861
|
-
id: "
|
|
2535
|
+
id: createStorageErrorId("DYNAMODB", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
2862
2536
|
domain: ErrorDomain.STORAGE,
|
|
2863
2537
|
category: ErrorCategory.THIRD_PARTY,
|
|
2864
2538
|
details: { runId, workflowName: args?.workflowName || "" }
|
|
@@ -2867,17 +2541,41 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
|
|
|
2867
2541
|
);
|
|
2868
2542
|
}
|
|
2869
2543
|
}
|
|
2544
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
2545
|
+
this.logger.debug("Deleting workflow run by ID", { runId, workflowName });
|
|
2546
|
+
try {
|
|
2547
|
+
await this.service.entities.workflow_snapshot.delete({
|
|
2548
|
+
entity: "workflow_snapshot",
|
|
2549
|
+
workflow_name: workflowName,
|
|
2550
|
+
run_id: runId
|
|
2551
|
+
}).go();
|
|
2552
|
+
} catch (error) {
|
|
2553
|
+
throw new MastraError(
|
|
2554
|
+
{
|
|
2555
|
+
id: createStorageErrorId("DYNAMODB", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
2556
|
+
domain: ErrorDomain.STORAGE,
|
|
2557
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2558
|
+
details: { runId, workflowName }
|
|
2559
|
+
},
|
|
2560
|
+
error
|
|
2561
|
+
);
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2870
2564
|
};
|
|
2871
2565
|
|
|
2872
2566
|
// src/storage/index.ts
|
|
2873
|
-
var
|
|
2567
|
+
var isClientConfig = (config) => {
|
|
2568
|
+
return "client" in config;
|
|
2569
|
+
};
|
|
2570
|
+
var DynamoDBStore = class extends MastraCompositeStore {
|
|
2874
2571
|
tableName;
|
|
2875
2572
|
client;
|
|
2876
2573
|
service;
|
|
2574
|
+
ttlConfig;
|
|
2877
2575
|
hasInitialized = null;
|
|
2878
2576
|
stores;
|
|
2879
2577
|
constructor({ name, config }) {
|
|
2880
|
-
super({ name });
|
|
2578
|
+
super({ id: config.id, name, disableInit: config.disableInit });
|
|
2881
2579
|
try {
|
|
2882
2580
|
if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
|
|
2883
2581
|
throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
|
|
@@ -2887,27 +2585,24 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
2887
2585
|
`DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`
|
|
2888
2586
|
);
|
|
2889
2587
|
}
|
|
2890
|
-
const dynamoClient = new DynamoDBClient({
|
|
2891
|
-
region: config.region || "us-east-1",
|
|
2892
|
-
endpoint: config.endpoint,
|
|
2893
|
-
credentials: config.credentials
|
|
2894
|
-
});
|
|
2895
2588
|
this.tableName = config.tableName;
|
|
2896
|
-
this.
|
|
2589
|
+
this.ttlConfig = config.ttl;
|
|
2590
|
+
if (isClientConfig(config)) {
|
|
2591
|
+
this.client = config.client;
|
|
2592
|
+
} else {
|
|
2593
|
+
const dynamoClient = new DynamoDBClient({
|
|
2594
|
+
region: config.region || "us-east-1",
|
|
2595
|
+
endpoint: config.endpoint,
|
|
2596
|
+
credentials: config.credentials
|
|
2597
|
+
});
|
|
2598
|
+
this.client = DynamoDBDocumentClient.from(dynamoClient);
|
|
2599
|
+
}
|
|
2897
2600
|
this.service = getElectroDbService(this.client, this.tableName);
|
|
2898
|
-
const
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
});
|
|
2903
|
-
const traces = new TracesStorageDynamoDB({ service: this.service, operations });
|
|
2904
|
-
const workflows = new WorkflowStorageDynamoDB({ service: this.service });
|
|
2905
|
-
const memory = new MemoryStorageDynamoDB({ service: this.service });
|
|
2906
|
-
const scores = new ScoresStorageDynamoDB({ service: this.service });
|
|
2601
|
+
const domainConfig = { service: this.service, ttl: this.ttlConfig };
|
|
2602
|
+
const workflows = new WorkflowStorageDynamoDB(domainConfig);
|
|
2603
|
+
const memory = new MemoryStorageDynamoDB(domainConfig);
|
|
2604
|
+
const scores = new ScoresStorageDynamoDB(domainConfig);
|
|
2907
2605
|
this.stores = {
|
|
2908
|
-
operations,
|
|
2909
|
-
legacyEvals: new LegacyEvalsDynamoDB({ service: this.service, tableName: this.tableName }),
|
|
2910
|
-
traces,
|
|
2911
2606
|
workflows,
|
|
2912
2607
|
memory,
|
|
2913
2608
|
scores
|
|
@@ -2915,7 +2610,7 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
2915
2610
|
} catch (error) {
|
|
2916
2611
|
throw new MastraError(
|
|
2917
2612
|
{
|
|
2918
|
-
id: "
|
|
2613
|
+
id: createStorageErrorId("DYNAMODB", "CONSTRUCTOR", "FAILED"),
|
|
2919
2614
|
domain: ErrorDomain.STORAGE,
|
|
2920
2615
|
category: ErrorCategory.USER
|
|
2921
2616
|
},
|
|
@@ -2923,16 +2618,6 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
2923
2618
|
);
|
|
2924
2619
|
}
|
|
2925
2620
|
}
|
|
2926
|
-
get supports() {
|
|
2927
|
-
return {
|
|
2928
|
-
selectByIncludeResourceScope: true,
|
|
2929
|
-
resourceWorkingMemory: true,
|
|
2930
|
-
hasColumn: false,
|
|
2931
|
-
createTable: false,
|
|
2932
|
-
deleteMessages: false,
|
|
2933
|
-
getScoresBySpan: true
|
|
2934
|
-
};
|
|
2935
|
-
}
|
|
2936
2621
|
/**
|
|
2937
2622
|
* Validates that the required DynamoDB table exists and is accessible.
|
|
2938
2623
|
* This does not check the table structure - it assumes the table
|
|
@@ -2951,7 +2636,7 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
2951
2636
|
}
|
|
2952
2637
|
throw new MastraError(
|
|
2953
2638
|
{
|
|
2954
|
-
id: "
|
|
2639
|
+
id: createStorageErrorId("DYNAMODB", "VALIDATE_TABLE_EXISTS", "FAILED"),
|
|
2955
2640
|
domain: ErrorDomain.STORAGE,
|
|
2956
2641
|
category: ErrorCategory.THIRD_PARTY,
|
|
2957
2642
|
details: { tableName: this.tableName }
|
|
@@ -2974,7 +2659,7 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
2974
2659
|
} catch (error) {
|
|
2975
2660
|
throw new MastraError(
|
|
2976
2661
|
{
|
|
2977
|
-
id: "
|
|
2662
|
+
id: createStorageErrorId("DYNAMODB", "INIT", "FAILED"),
|
|
2978
2663
|
domain: ErrorDomain.STORAGE,
|
|
2979
2664
|
category: ErrorCategory.THIRD_PARTY,
|
|
2980
2665
|
details: { tableName: this.tableName }
|
|
@@ -3000,143 +2685,10 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
3000
2685
|
throw err;
|
|
3001
2686
|
});
|
|
3002
2687
|
}
|
|
3003
|
-
async createTable({ tableName, schema }) {
|
|
3004
|
-
return this.stores.operations.createTable({ tableName, schema });
|
|
3005
|
-
}
|
|
3006
|
-
async alterTable(_args) {
|
|
3007
|
-
return this.stores.operations.alterTable(_args);
|
|
3008
|
-
}
|
|
3009
|
-
async clearTable({ tableName }) {
|
|
3010
|
-
return this.stores.operations.clearTable({ tableName });
|
|
3011
|
-
}
|
|
3012
|
-
async dropTable({ tableName }) {
|
|
3013
|
-
return this.stores.operations.dropTable({ tableName });
|
|
3014
|
-
}
|
|
3015
|
-
async insert({ tableName, record }) {
|
|
3016
|
-
return this.stores.operations.insert({ tableName, record });
|
|
3017
|
-
}
|
|
3018
|
-
async batchInsert({ tableName, records }) {
|
|
3019
|
-
return this.stores.operations.batchInsert({ tableName, records });
|
|
3020
|
-
}
|
|
3021
|
-
async load({ tableName, keys }) {
|
|
3022
|
-
return this.stores.operations.load({ tableName, keys });
|
|
3023
|
-
}
|
|
3024
|
-
// Thread operations
|
|
3025
|
-
async getThreadById({ threadId }) {
|
|
3026
|
-
return this.stores.memory.getThreadById({ threadId });
|
|
3027
|
-
}
|
|
3028
|
-
async getThreadsByResourceId(args) {
|
|
3029
|
-
return this.stores.memory.getThreadsByResourceId(args);
|
|
3030
|
-
}
|
|
3031
|
-
async saveThread({ thread }) {
|
|
3032
|
-
return this.stores.memory.saveThread({ thread });
|
|
3033
|
-
}
|
|
3034
|
-
async updateThread({
|
|
3035
|
-
id,
|
|
3036
|
-
title,
|
|
3037
|
-
metadata
|
|
3038
|
-
}) {
|
|
3039
|
-
return this.stores.memory.updateThread({ id, title, metadata });
|
|
3040
|
-
}
|
|
3041
|
-
async deleteThread({ threadId }) {
|
|
3042
|
-
return this.stores.memory.deleteThread({ threadId });
|
|
3043
|
-
}
|
|
3044
|
-
async getMessages({
|
|
3045
|
-
threadId,
|
|
3046
|
-
resourceId,
|
|
3047
|
-
selectBy,
|
|
3048
|
-
format
|
|
3049
|
-
}) {
|
|
3050
|
-
return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
|
|
3051
|
-
}
|
|
3052
|
-
async getMessagesById({
|
|
3053
|
-
messageIds,
|
|
3054
|
-
format
|
|
3055
|
-
}) {
|
|
3056
|
-
return this.stores.memory.getMessagesById({ messageIds, format });
|
|
3057
|
-
}
|
|
3058
|
-
async saveMessages(args) {
|
|
3059
|
-
return this.stores.memory.saveMessages(args);
|
|
3060
|
-
}
|
|
3061
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
3062
|
-
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
3063
|
-
}
|
|
3064
|
-
async getMessagesPaginated(args) {
|
|
3065
|
-
return this.stores.memory.getMessagesPaginated(args);
|
|
3066
|
-
}
|
|
3067
|
-
async updateMessages(_args) {
|
|
3068
|
-
return this.stores.memory.updateMessages(_args);
|
|
3069
|
-
}
|
|
3070
|
-
// Trace operations
|
|
3071
|
-
async getTraces(args) {
|
|
3072
|
-
return this.stores.traces.getTraces(args);
|
|
3073
|
-
}
|
|
3074
|
-
async batchTraceInsert({ records }) {
|
|
3075
|
-
return this.stores.traces.batchTraceInsert({ records });
|
|
3076
|
-
}
|
|
3077
|
-
async getTracesPaginated(_args) {
|
|
3078
|
-
return this.stores.traces.getTracesPaginated(_args);
|
|
3079
|
-
}
|
|
3080
|
-
// Workflow operations
|
|
3081
|
-
async updateWorkflowResults({
|
|
3082
|
-
workflowName,
|
|
3083
|
-
runId,
|
|
3084
|
-
stepId,
|
|
3085
|
-
result,
|
|
3086
|
-
runtimeContext
|
|
3087
|
-
}) {
|
|
3088
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
|
|
3089
|
-
}
|
|
3090
|
-
async updateWorkflowState({
|
|
3091
|
-
workflowName,
|
|
3092
|
-
runId,
|
|
3093
|
-
opts
|
|
3094
|
-
}) {
|
|
3095
|
-
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
3096
|
-
}
|
|
3097
|
-
async persistWorkflowSnapshot({
|
|
3098
|
-
workflowName,
|
|
3099
|
-
runId,
|
|
3100
|
-
resourceId,
|
|
3101
|
-
snapshot
|
|
3102
|
-
}) {
|
|
3103
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
3104
|
-
}
|
|
3105
|
-
async loadWorkflowSnapshot({
|
|
3106
|
-
workflowName,
|
|
3107
|
-
runId
|
|
3108
|
-
}) {
|
|
3109
|
-
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
3110
|
-
}
|
|
3111
|
-
async getWorkflowRuns(args) {
|
|
3112
|
-
return this.stores.workflows.getWorkflowRuns(args);
|
|
3113
|
-
}
|
|
3114
|
-
async getWorkflowRunById(args) {
|
|
3115
|
-
return this.stores.workflows.getWorkflowRunById(args);
|
|
3116
|
-
}
|
|
3117
|
-
async getResourceById({ resourceId }) {
|
|
3118
|
-
return this.stores.memory.getResourceById({ resourceId });
|
|
3119
|
-
}
|
|
3120
|
-
async saveResource({ resource }) {
|
|
3121
|
-
return this.stores.memory.saveResource({ resource });
|
|
3122
|
-
}
|
|
3123
|
-
async updateResource({
|
|
3124
|
-
resourceId,
|
|
3125
|
-
workingMemory,
|
|
3126
|
-
metadata
|
|
3127
|
-
}) {
|
|
3128
|
-
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
3129
|
-
}
|
|
3130
|
-
// Eval operations
|
|
3131
|
-
async getEvalsByAgentName(agentName, type) {
|
|
3132
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
3133
|
-
}
|
|
3134
|
-
async getEvals(options) {
|
|
3135
|
-
return this.stores.legacyEvals.getEvals(options);
|
|
3136
|
-
}
|
|
3137
2688
|
/**
|
|
3138
2689
|
* Closes the DynamoDB client connection and cleans up resources.
|
|
3139
|
-
*
|
|
2690
|
+
*
|
|
2691
|
+
* This will close the DynamoDB client, including pre-configured clients.
|
|
3140
2692
|
*/
|
|
3141
2693
|
async close() {
|
|
3142
2694
|
this.logger.debug("Closing DynamoDB client for store:", { name: this.name });
|
|
@@ -3146,7 +2698,7 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
3146
2698
|
} catch (error) {
|
|
3147
2699
|
throw new MastraError(
|
|
3148
2700
|
{
|
|
3149
|
-
id: "
|
|
2701
|
+
id: createStorageErrorId("DYNAMODB", "CLOSE", "FAILED"),
|
|
3150
2702
|
domain: ErrorDomain.STORAGE,
|
|
3151
2703
|
category: ErrorCategory.THIRD_PARTY
|
|
3152
2704
|
},
|
|
@@ -3154,50 +2706,8 @@ var DynamoDBStore = class extends MastraStorage {
|
|
|
3154
2706
|
);
|
|
3155
2707
|
}
|
|
3156
2708
|
}
|
|
3157
|
-
/**
|
|
3158
|
-
* SCORERS - Not implemented
|
|
3159
|
-
*/
|
|
3160
|
-
async getScoreById({ id: _id }) {
|
|
3161
|
-
return this.stores.scores.getScoreById({ id: _id });
|
|
3162
|
-
}
|
|
3163
|
-
async saveScore(_score) {
|
|
3164
|
-
return this.stores.scores.saveScore(_score);
|
|
3165
|
-
}
|
|
3166
|
-
async getScoresByRunId({
|
|
3167
|
-
runId: _runId,
|
|
3168
|
-
pagination: _pagination
|
|
3169
|
-
}) {
|
|
3170
|
-
return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
|
|
3171
|
-
}
|
|
3172
|
-
async getScoresByEntityId({
|
|
3173
|
-
entityId: _entityId,
|
|
3174
|
-
entityType: _entityType,
|
|
3175
|
-
pagination: _pagination
|
|
3176
|
-
}) {
|
|
3177
|
-
return this.stores.scores.getScoresByEntityId({
|
|
3178
|
-
entityId: _entityId,
|
|
3179
|
-
entityType: _entityType,
|
|
3180
|
-
pagination: _pagination
|
|
3181
|
-
});
|
|
3182
|
-
}
|
|
3183
|
-
async getScoresByScorerId({
|
|
3184
|
-
scorerId,
|
|
3185
|
-
source,
|
|
3186
|
-
entityId,
|
|
3187
|
-
entityType,
|
|
3188
|
-
pagination
|
|
3189
|
-
}) {
|
|
3190
|
-
return this.stores.scores.getScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
|
|
3191
|
-
}
|
|
3192
|
-
async getScoresBySpan({
|
|
3193
|
-
traceId,
|
|
3194
|
-
spanId,
|
|
3195
|
-
pagination
|
|
3196
|
-
}) {
|
|
3197
|
-
return this.stores.scores.getScoresBySpan({ traceId, spanId, pagination });
|
|
3198
|
-
}
|
|
3199
2709
|
};
|
|
3200
2710
|
|
|
3201
|
-
export { DynamoDBStore };
|
|
2711
|
+
export { DynamoDBStore, MemoryStorageDynamoDB, ScoresStorageDynamoDB, WorkflowStorageDynamoDB, calculateTtl, getTtlAttributeName, getTtlProps, isTtlEnabled };
|
|
3202
2712
|
//# sourceMappingURL=index.js.map
|
|
3203
2713
|
//# sourceMappingURL=index.js.map
|