@mastra/dynamodb 1.0.3 → 1.0.4-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -82,7 +82,128 @@ var baseAttributes = {
82
82
  }
83
83
  };
84
84
 
85
- // src/entities/eval.ts
85
+ // src/entities/background-task.ts
86
+ var jsonSetGet = {
87
+ set: (value) => {
88
+ if (value == null) return value;
89
+ if (typeof value === "string") return value;
90
+ return JSON.stringify(value);
91
+ },
92
+ get: (value) => {
93
+ if (!value) return value;
94
+ if (typeof value !== "string") return value;
95
+ try {
96
+ if (value.startsWith("{") || value.startsWith("[")) {
97
+ return JSON.parse(value);
98
+ }
99
+ } catch {
100
+ }
101
+ return value;
102
+ }
103
+ };
104
+ var backgroundTaskEntity = new electrodb.Entity({
105
+ model: {
106
+ entity: "background_task",
107
+ version: "1",
108
+ service: "mastra"
109
+ },
110
+ attributes: {
111
+ entity: {
112
+ type: "string",
113
+ required: true
114
+ },
115
+ ...baseAttributes,
116
+ id: {
117
+ type: "string",
118
+ required: true
119
+ },
120
+ status: {
121
+ type: "string",
122
+ required: true
123
+ },
124
+ toolName: {
125
+ type: "string",
126
+ required: true
127
+ },
128
+ toolCallId: {
129
+ type: "string",
130
+ required: true
131
+ },
132
+ agentId: {
133
+ type: "string",
134
+ required: true
135
+ },
136
+ runId: {
137
+ type: "string",
138
+ required: true
139
+ },
140
+ threadId: {
141
+ type: "string",
142
+ required: false
143
+ },
144
+ resourceId: {
145
+ type: "string",
146
+ required: false
147
+ },
148
+ args: {
149
+ type: "string",
150
+ required: true,
151
+ ...jsonSetGet
152
+ },
153
+ result: {
154
+ type: "string",
155
+ required: false,
156
+ ...jsonSetGet
157
+ },
158
+ error: {
159
+ type: "string",
160
+ required: false,
161
+ ...jsonSetGet
162
+ },
163
+ retryCount: {
164
+ type: "number",
165
+ required: true
166
+ },
167
+ maxRetries: {
168
+ type: "number",
169
+ required: true
170
+ },
171
+ timeoutMs: {
172
+ type: "number",
173
+ required: true
174
+ },
175
+ // Separate ISO strings for date columns — use these for GSI sort keys
176
+ startedAtIso: {
177
+ type: "string",
178
+ required: false
179
+ },
180
+ completedAtIso: {
181
+ type: "string",
182
+ required: false
183
+ }
184
+ },
185
+ indexes: {
186
+ primary: {
187
+ pk: { field: "pk", composite: ["entity", "id"] },
188
+ sk: { field: "sk", composite: ["entity"] }
189
+ },
190
+ byAgent: {
191
+ index: "gsi1",
192
+ pk: { field: "gsi1pk", composite: ["entity", "agentId"] },
193
+ sk: { field: "gsi1sk", composite: ["createdAt"] }
194
+ },
195
+ byRun: {
196
+ index: "gsi2",
197
+ pk: { field: "gsi2pk", composite: ["entity", "runId"] },
198
+ sk: { field: "gsi2sk", composite: ["createdAt"] }
199
+ },
200
+ byStatus: {
201
+ index: "gsi3",
202
+ pk: { field: "gsi3pk", composite: ["entity", "status"] },
203
+ sk: { field: "gsi3sk", composite: ["createdAt"] }
204
+ }
205
+ }
206
+ });
86
207
  var evalEntity = new electrodb.Entity({
87
208
  model: {
88
209
  entity: "eval",
@@ -972,7 +1093,8 @@ function getElectroDbService(client, tableName) {
972
1093
  trace: traceEntity,
973
1094
  workflow_snapshot: workflowSnapshotEntity,
974
1095
  resource: resourceEntity,
975
- score: scoreEntity
1096
+ score: scoreEntity,
1097
+ background_task: backgroundTaskEntity
976
1098
  },
977
1099
  {
978
1100
  client,
@@ -995,38 +1117,13 @@ function resolveDynamoDBConfig(config) {
995
1117
  ttl: config.ttl
996
1118
  };
997
1119
  }
998
-
999
- // src/storage/ttl.ts
1000
- function calculateTtl(entityName, ttlConfig, customTtlSeconds) {
1001
- const entityConfig = ttlConfig?.[entityName];
1002
- if (!entityConfig?.enabled) {
1003
- return void 0;
1004
- }
1005
- const ttlSeconds = customTtlSeconds ?? entityConfig.defaultTtlSeconds;
1006
- if (ttlSeconds === void 0 || ttlSeconds <= 0) {
1007
- return void 0;
1008
- }
1009
- return Math.floor(Date.now() / 1e3) + ttlSeconds;
1010
- }
1011
- function getTtlAttributeName(entityName, ttlConfig) {
1012
- const entityConfig = ttlConfig?.[entityName];
1013
- return entityConfig?.attributeName ?? "ttl";
1014
- }
1015
- function isTtlEnabled(entityName, ttlConfig) {
1016
- return ttlConfig?.[entityName]?.enabled === true;
1017
- }
1018
- function getTtlProps(entityName, ttlConfig, customTtlSeconds) {
1019
- const ttlValue = calculateTtl(entityName, ttlConfig, customTtlSeconds);
1020
- if (ttlValue === void 0) return {};
1021
- const attributeName = getTtlAttributeName(entityName, ttlConfig);
1022
- return { [attributeName]: ttlValue };
1023
- }
1024
1120
  var ENTITY_MAP = {
1025
1121
  [storage.TABLE_THREADS]: "thread",
1026
1122
  [storage.TABLE_MESSAGES]: "message",
1027
1123
  [storage.TABLE_RESOURCES]: "resource",
1028
1124
  [storage.TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1029
- [storage.TABLE_SCORERS]: "score"
1125
+ [storage.TABLE_SCORERS]: "score",
1126
+ [storage.TABLE_BACKGROUND_TASKS]: "background_task"
1030
1127
  };
1031
1128
  function getDeleteKey(entityName, item) {
1032
1129
  const key = { entity: entityName };
@@ -1035,6 +1132,7 @@ function getDeleteKey(entityName, item) {
1035
1132
  case "message":
1036
1133
  case "resource":
1037
1134
  case "score":
1135
+ case "background_task":
1038
1136
  key.id = item.id;
1039
1137
  break;
1040
1138
  case "workflow_snapshot":
@@ -1064,6 +1162,296 @@ async function deleteTableData(service, tableName) {
1064
1162
  }
1065
1163
  }
1066
1164
 
1165
+ // src/storage/domains/background-tasks/index.ts
1166
+ var ENTITY = "background_task";
1167
+ function serializeJson(v) {
1168
+ if (typeof v === "object" && v != null) return JSON.stringify(v);
1169
+ return v ?? void 0;
1170
+ }
1171
+ function toElectroRecord(task) {
1172
+ return {
1173
+ entity: ENTITY,
1174
+ id: task.id,
1175
+ status: task.status,
1176
+ toolName: task.toolName,
1177
+ toolCallId: task.toolCallId,
1178
+ agentId: task.agentId,
1179
+ runId: task.runId,
1180
+ threadId: task.threadId ?? void 0,
1181
+ resourceId: task.resourceId ?? void 0,
1182
+ args: serializeJson(task.args),
1183
+ result: serializeJson(task.result),
1184
+ error: serializeJson(task.error),
1185
+ retryCount: task.retryCount,
1186
+ maxRetries: task.maxRetries,
1187
+ timeoutMs: task.timeoutMs,
1188
+ createdAt: task.createdAt.toISOString(),
1189
+ startedAtIso: task.startedAt?.toISOString(),
1190
+ completedAtIso: task.completedAt?.toISOString()
1191
+ };
1192
+ }
1193
+ function fromElectroRecord(data) {
1194
+ const parseJson = (v) => {
1195
+ if (v == null || v === "") return void 0;
1196
+ if (typeof v === "string") {
1197
+ try {
1198
+ if (v.startsWith("{") || v.startsWith("[")) return JSON.parse(v);
1199
+ } catch {
1200
+ return v;
1201
+ }
1202
+ }
1203
+ return v;
1204
+ };
1205
+ const asDate = (v) => v ? new Date(String(v)) : void 0;
1206
+ return {
1207
+ id: String(data.id),
1208
+ status: String(data.status),
1209
+ toolName: String(data.toolName),
1210
+ toolCallId: String(data.toolCallId),
1211
+ args: parseJson(data.args) ?? {},
1212
+ agentId: String(data.agentId),
1213
+ threadId: data.threadId != null && data.threadId !== "" ? String(data.threadId) : void 0,
1214
+ resourceId: data.resourceId != null && data.resourceId !== "" ? String(data.resourceId) : void 0,
1215
+ runId: String(data.runId),
1216
+ result: parseJson(data.result),
1217
+ error: parseJson(data.error),
1218
+ retryCount: Number(data.retryCount ?? 0),
1219
+ maxRetries: Number(data.maxRetries ?? 0),
1220
+ timeoutMs: Number(data.timeoutMs ?? 3e5),
1221
+ createdAt: asDate(data.createdAt) ?? /* @__PURE__ */ new Date(),
1222
+ startedAt: asDate(data.startedAtIso),
1223
+ completedAt: asDate(data.completedAtIso)
1224
+ };
1225
+ }
1226
+ var BackgroundTasksStorageDynamoDB = class extends storage.BackgroundTasksStorage {
1227
+ service;
1228
+ constructor(config) {
1229
+ super();
1230
+ const resolved = resolveDynamoDBConfig(config);
1231
+ this.service = resolved.service;
1232
+ }
1233
+ async dangerouslyClearAll() {
1234
+ await deleteTableData(this.service, storage.TABLE_BACKGROUND_TASKS);
1235
+ }
1236
+ async createTask(task) {
1237
+ try {
1238
+ await this.service.entities.background_task.create(toElectroRecord(task)).go();
1239
+ } catch (error$1) {
1240
+ throw new error.MastraError(
1241
+ {
1242
+ id: storage.createStorageErrorId("DYNAMODB", "BACKGROUND_TASKS_CREATE", "FAILED"),
1243
+ domain: error.ErrorDomain.STORAGE,
1244
+ category: error.ErrorCategory.THIRD_PARTY,
1245
+ details: { taskId: task.id }
1246
+ },
1247
+ error$1
1248
+ );
1249
+ }
1250
+ }
1251
+ async updateTask(taskId, update) {
1252
+ try {
1253
+ const setFields = {};
1254
+ const removeFields = [];
1255
+ if ("status" in update && update.status !== void 0) {
1256
+ setFields.status = update.status;
1257
+ }
1258
+ if ("retryCount" in update && update.retryCount !== void 0) {
1259
+ setFields.retryCount = update.retryCount;
1260
+ }
1261
+ if ("result" in update) {
1262
+ if (update.result === void 0 || update.result === null) {
1263
+ removeFields.push("result");
1264
+ } else {
1265
+ setFields.result = serializeJson(update.result);
1266
+ }
1267
+ }
1268
+ if ("error" in update) {
1269
+ if (update.error === void 0 || update.error === null) {
1270
+ removeFields.push("error");
1271
+ } else {
1272
+ setFields.error = serializeJson(update.error);
1273
+ }
1274
+ }
1275
+ if ("startedAt" in update) {
1276
+ if (update.startedAt === void 0 || update.startedAt === null) {
1277
+ removeFields.push("startedAtIso");
1278
+ } else {
1279
+ setFields.startedAtIso = update.startedAt.toISOString();
1280
+ }
1281
+ }
1282
+ if ("completedAt" in update) {
1283
+ if (update.completedAt === void 0 || update.completedAt === null) {
1284
+ removeFields.push("completedAtIso");
1285
+ } else {
1286
+ setFields.completedAtIso = update.completedAt.toISOString();
1287
+ }
1288
+ }
1289
+ if (Object.keys(setFields).length === 0 && removeFields.length === 0) return;
1290
+ let op = this.service.entities.background_task.patch({ entity: ENTITY, id: taskId });
1291
+ if (Object.keys(setFields).length > 0) op = op.set(setFields);
1292
+ if (removeFields.length > 0) op = op.remove(removeFields);
1293
+ await op.go();
1294
+ } catch (error$1) {
1295
+ throw new error.MastraError(
1296
+ {
1297
+ id: storage.createStorageErrorId("DYNAMODB", "BACKGROUND_TASKS_UPDATE", "FAILED"),
1298
+ domain: error.ErrorDomain.STORAGE,
1299
+ category: error.ErrorCategory.THIRD_PARTY,
1300
+ details: { taskId }
1301
+ },
1302
+ error$1
1303
+ );
1304
+ }
1305
+ }
1306
+ async getTask(taskId) {
1307
+ try {
1308
+ const result = await this.service.entities.background_task.get({ entity: ENTITY, id: taskId }).go();
1309
+ if (!result.data) return null;
1310
+ return fromElectroRecord(result.data);
1311
+ } catch (error$1) {
1312
+ throw new error.MastraError(
1313
+ {
1314
+ id: storage.createStorageErrorId("DYNAMODB", "BACKGROUND_TASKS_GET", "FAILED"),
1315
+ domain: error.ErrorDomain.STORAGE,
1316
+ category: error.ErrorCategory.THIRD_PARTY,
1317
+ details: { taskId }
1318
+ },
1319
+ error$1
1320
+ );
1321
+ }
1322
+ }
1323
+ async listTasks(filter) {
1324
+ try {
1325
+ let rawResults = [];
1326
+ if (filter.runId) {
1327
+ const res = await this.service.entities.background_task.query.byRun({ entity: ENTITY, runId: filter.runId }).go({ pages: "all" });
1328
+ rawResults = res.data;
1329
+ } else if (filter.agentId) {
1330
+ const res = await this.service.entities.background_task.query.byAgent({ entity: ENTITY, agentId: filter.agentId }).go({ pages: "all" });
1331
+ rawResults = res.data;
1332
+ } else if (filter.status && !Array.isArray(filter.status)) {
1333
+ const res = await this.service.entities.background_task.query.byStatus({ entity: ENTITY, status: filter.status }).go({ pages: "all" });
1334
+ rawResults = res.data;
1335
+ } else {
1336
+ const res = await this.service.entities.background_task.scan.go({ pages: "all" });
1337
+ rawResults = res.data;
1338
+ }
1339
+ let tasks = rawResults.map(fromElectroRecord);
1340
+ if (filter.status) {
1341
+ const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
1342
+ tasks = tasks.filter((t) => statuses.includes(t.status));
1343
+ }
1344
+ if (filter.agentId) tasks = tasks.filter((t) => t.agentId === filter.agentId);
1345
+ if (filter.threadId) tasks = tasks.filter((t) => t.threadId === filter.threadId);
1346
+ if (filter.resourceId) tasks = tasks.filter((t) => t.resourceId === filter.resourceId);
1347
+ if (filter.toolName) tasks = tasks.filter((t) => t.toolName === filter.toolName);
1348
+ if (filter.runId) tasks = tasks.filter((t) => t.runId === filter.runId);
1349
+ const dateCol = filter.dateFilterBy ?? "createdAt";
1350
+ if (filter.fromDate) {
1351
+ tasks = tasks.filter((t) => {
1352
+ const val = t[dateCol];
1353
+ return val != null && val >= filter.fromDate;
1354
+ });
1355
+ }
1356
+ if (filter.toDate) {
1357
+ tasks = tasks.filter((t) => {
1358
+ const val = t[dateCol];
1359
+ return val != null && val < filter.toDate;
1360
+ });
1361
+ }
1362
+ const orderBy = filter.orderBy ?? "createdAt";
1363
+ const dir = filter.orderDirection === "desc" ? -1 : 1;
1364
+ tasks.sort((a, b) => ((a[orderBy]?.getTime() ?? 0) - (b[orderBy]?.getTime() ?? 0)) * dir);
1365
+ const total = tasks.length;
1366
+ if (filter.page != null && filter.perPage != null) {
1367
+ const start = filter.page * filter.perPage;
1368
+ tasks = tasks.slice(start, start + filter.perPage);
1369
+ } else if (filter.perPage != null) {
1370
+ tasks = tasks.slice(0, filter.perPage);
1371
+ }
1372
+ return { tasks, total };
1373
+ } catch (error$1) {
1374
+ throw new error.MastraError(
1375
+ {
1376
+ id: storage.createStorageErrorId("DYNAMODB", "BACKGROUND_TASKS_LIST", "FAILED"),
1377
+ domain: error.ErrorDomain.STORAGE,
1378
+ category: error.ErrorCategory.THIRD_PARTY
1379
+ },
1380
+ error$1
1381
+ );
1382
+ }
1383
+ }
1384
+ async deleteTask(taskId) {
1385
+ try {
1386
+ await this.service.entities.background_task.delete({ entity: ENTITY, id: taskId }).go();
1387
+ } catch (error$1) {
1388
+ throw new error.MastraError(
1389
+ {
1390
+ id: storage.createStorageErrorId("DYNAMODB", "BACKGROUND_TASKS_DELETE", "FAILED"),
1391
+ domain: error.ErrorDomain.STORAGE,
1392
+ category: error.ErrorCategory.THIRD_PARTY,
1393
+ details: { taskId }
1394
+ },
1395
+ error$1
1396
+ );
1397
+ }
1398
+ }
1399
+ async deleteTasks(filter) {
1400
+ const { tasks } = await this.listTasks(filter);
1401
+ if (tasks.length === 0) return;
1402
+ try {
1403
+ const batchSize = 25;
1404
+ for (let i = 0; i < tasks.length; i += batchSize) {
1405
+ const batch = tasks.slice(i, i + batchSize).map((t) => ({ entity: ENTITY, id: t.id }));
1406
+ await this.service.entities.background_task.delete(batch).go();
1407
+ }
1408
+ } catch (error$1) {
1409
+ throw new error.MastraError(
1410
+ {
1411
+ id: storage.createStorageErrorId("DYNAMODB", "BACKGROUND_TASKS_DELETE_MANY", "FAILED"),
1412
+ domain: error.ErrorDomain.STORAGE,
1413
+ category: error.ErrorCategory.THIRD_PARTY
1414
+ },
1415
+ error$1
1416
+ );
1417
+ }
1418
+ }
1419
+ async getRunningCount() {
1420
+ const { total } = await this.listTasks({ status: "running" });
1421
+ return total;
1422
+ }
1423
+ async getRunningCountByAgent(agentId) {
1424
+ const { total } = await this.listTasks({ status: "running", agentId });
1425
+ return total;
1426
+ }
1427
+ };
1428
+
1429
+ // src/storage/ttl.ts
1430
+ function calculateTtl(entityName, ttlConfig, customTtlSeconds) {
1431
+ const entityConfig = ttlConfig?.[entityName];
1432
+ if (!entityConfig?.enabled) {
1433
+ return void 0;
1434
+ }
1435
+ const ttlSeconds = customTtlSeconds ?? entityConfig.defaultTtlSeconds;
1436
+ if (ttlSeconds === void 0 || ttlSeconds <= 0) {
1437
+ return void 0;
1438
+ }
1439
+ return Math.floor(Date.now() / 1e3) + ttlSeconds;
1440
+ }
1441
+ function getTtlAttributeName(entityName, ttlConfig) {
1442
+ const entityConfig = ttlConfig?.[entityName];
1443
+ return entityConfig?.attributeName ?? "ttl";
1444
+ }
1445
+ function isTtlEnabled(entityName, ttlConfig) {
1446
+ return ttlConfig?.[entityName]?.enabled === true;
1447
+ }
1448
+ function getTtlProps(entityName, ttlConfig, customTtlSeconds) {
1449
+ const ttlValue = calculateTtl(entityName, ttlConfig, customTtlSeconds);
1450
+ if (ttlValue === void 0) return {};
1451
+ const attributeName = getTtlAttributeName(entityName, ttlConfig);
1452
+ return { [attributeName]: ttlValue };
1453
+ }
1454
+
1067
1455
  // src/storage/domains/memory/index.ts
1068
1456
  var MemoryStorageDynamoDB = class extends storage.MemoryStorage {
1069
1457
  service;
@@ -2616,10 +3004,12 @@ var DynamoDBStore = class extends storage.MastraCompositeStore {
2616
3004
  const workflows = new WorkflowStorageDynamoDB(domainConfig);
2617
3005
  const memory = new MemoryStorageDynamoDB(domainConfig);
2618
3006
  const scores = new ScoresStorageDynamoDB(domainConfig);
3007
+ const backgroundTasks = new BackgroundTasksStorageDynamoDB(domainConfig);
2619
3008
  this.stores = {
2620
3009
  workflows,
2621
3010
  memory,
2622
- scores
3011
+ scores,
3012
+ backgroundTasks
2623
3013
  };
2624
3014
  } catch (error$1) {
2625
3015
  throw new error.MastraError(
@@ -2722,6 +3112,7 @@ var DynamoDBStore = class extends storage.MastraCompositeStore {
2722
3112
  }
2723
3113
  };
2724
3114
 
3115
+ exports.BackgroundTasksStorageDynamoDB = BackgroundTasksStorageDynamoDB;
2725
3116
  exports.DynamoDBStore = DynamoDBStore;
2726
3117
  exports.MemoryStorageDynamoDB = MemoryStorageDynamoDB;
2727
3118
  exports.ScoresStorageDynamoDB = ScoresStorageDynamoDB;