@mastra/dynamodb 1.0.0-beta.1 → 1.0.0-beta.2

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.js CHANGED
@@ -1,7 +1,7 @@
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 { MastraStorage, StoreOperations, WorkflowsStorage, normalizePerPage, MemoryStorage, calculatePagination, ScoresStorage, TABLE_SPANS, TABLE_RESOURCES, TABLE_TRACES, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
4
+ import { MastraStorage, StoreOperations, WorkflowsStorage, normalizePerPage, MemoryStorage, calculatePagination, ScoresStorage, SCORERS_SCHEMA, TABLE_SPANS, TABLE_RESOURCES, TABLE_TRACES, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
5
5
  import { Entity, Service } from 'electrodb';
6
6
  import { MessageList } from '@mastra/core/agent';
7
7
  import { saveScorePayloadSchema } from '@mastra/core/evals';
@@ -423,6 +423,10 @@ var scoreEntity = new Entity({
423
423
  return value;
424
424
  }
425
425
  },
426
+ preprocessPrompt: {
427
+ type: "string",
428
+ required: false
429
+ },
426
430
  preprocessStepResult: {
427
431
  type: "string",
428
432
  required: false,
@@ -1128,15 +1132,16 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1128
1132
  }
1129
1133
  async listMessages(args) {
1130
1134
  const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
1131
- if (!threadId.trim()) {
1135
+ const threadIds = Array.isArray(threadId) ? threadId : [threadId];
1136
+ if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
1132
1137
  throw new MastraError(
1133
1138
  {
1134
1139
  id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_THREAD_ID",
1135
1140
  domain: ErrorDomain.STORAGE,
1136
1141
  category: ErrorCategory.THIRD_PARTY,
1137
- details: { threadId }
1142
+ details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
1138
1143
  },
1139
- new Error("threadId must be a non-empty string")
1144
+ new Error("threadId must be a non-empty string or array of non-empty strings")
1140
1145
  );
1141
1146
  }
1142
1147
  const perPage = normalizePerPage(perPageInput, 40);
@@ -1209,7 +1214,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1209
1214
  let includeMessages = [];
1210
1215
  if (include && include.length > 0) {
1211
1216
  const selectBy = { include };
1212
- includeMessages = await this._getIncludedMessages(threadId, selectBy);
1217
+ includeMessages = await this._getIncludedMessages(selectBy);
1213
1218
  for (const includeMsg of includeMessages) {
1214
1219
  if (!messageIds.has(includeMsg.id)) {
1215
1220
  paginatedMessages.push(includeMsg);
@@ -1247,7 +1252,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1247
1252
  domain: ErrorDomain.STORAGE,
1248
1253
  category: ErrorCategory.THIRD_PARTY,
1249
1254
  details: {
1250
- threadId,
1255
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
1251
1256
  resourceId: resourceId ?? ""
1252
1257
  }
1253
1258
  },
@@ -1386,19 +1391,23 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1386
1391
  }
1387
1392
  }
1388
1393
  // Helper method to get included messages with context
1389
- async _getIncludedMessages(threadId, selectBy) {
1390
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1394
+ async _getIncludedMessages(selectBy) {
1391
1395
  if (!selectBy?.include?.length) {
1392
1396
  return [];
1393
1397
  }
1394
1398
  const includeMessages = [];
1395
1399
  for (const includeItem of selectBy.include) {
1396
1400
  try {
1397
- const { id, threadId: targetThreadId, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
1398
- const searchThreadId = targetThreadId || threadId;
1401
+ const { id, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
1402
+ const targetResult = await this.service.entities.message.get({ entity: "message", id }).go();
1403
+ if (!targetResult.data) {
1404
+ this.logger.warn("Target message not found", { id });
1405
+ continue;
1406
+ }
1407
+ const targetMessageData = targetResult.data;
1408
+ const searchThreadId = targetMessageData.threadId;
1399
1409
  this.logger.debug("Getting included messages for", {
1400
1410
  id,
1401
- targetThreadId,
1402
1411
  searchThreadId,
1403
1412
  withPreviousMessages,
1404
1413
  withNextMessages
@@ -1421,7 +1430,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1421
1430
  });
1422
1431
  const targetIndex = allMessages.findIndex((msg) => msg.id === id);
1423
1432
  if (targetIndex === -1) {
1424
- this.logger.warn("Target message not found", { id, threadId: searchThreadId });
1433
+ this.logger.warn("Target message not found in thread", { id, threadId: searchThreadId });
1425
1434
  continue;
1426
1435
  }
1427
1436
  this.logger.debug("Found target message at index", { id, targetIndex, totalMessages: allMessages.length });
@@ -1954,14 +1963,28 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
1954
1963
  super();
1955
1964
  this.service = service;
1956
1965
  }
1957
- // Helper function to parse score data (handle JSON fields)
1966
+ /**
1967
+ * DynamoDB-specific score row transformation.
1968
+ *
1969
+ * Note: This implementation does NOT use coreTransformScoreRow because:
1970
+ * 1. ElectroDB already parses JSON fields via its entity getters
1971
+ * 2. DynamoDB stores empty strings for null values (which need special handling)
1972
+ * 3. 'entity' is a reserved ElectroDB key, so we use 'entityData' column
1973
+ */
1958
1974
  parseScoreData(data) {
1975
+ const result = {};
1976
+ for (const key of Object.keys(SCORERS_SCHEMA)) {
1977
+ if (["traceId", "resourceId", "threadId", "spanId"].includes(key)) {
1978
+ result[key] = data[key] === "" ? null : data[key];
1979
+ continue;
1980
+ }
1981
+ result[key] = data[key];
1982
+ }
1983
+ result.entity = data.entityData ?? null;
1959
1984
  return {
1960
- ...data,
1961
- // Convert date strings back to Date objects for consistency
1985
+ ...result,
1962
1986
  createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
1963
1987
  updatedAt: data.updatedAt ? new Date(data.updatedAt) : /* @__PURE__ */ new Date()
1964
- // JSON fields are already transformed by the entity's getters
1965
1988
  };
1966
1989
  }
1967
1990
  async getScoreById({ id }) {
@@ -2000,35 +2023,33 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2000
2023
  }
2001
2024
  const now = /* @__PURE__ */ new Date();
2002
2025
  const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2003
- const scoreData = {
2004
- entity: "score",
2005
- id: scoreId,
2006
- scorerId: validatedScore.scorerId,
2007
- traceId: validatedScore.traceId || "",
2008
- spanId: validatedScore.spanId || "",
2009
- runId: validatedScore.runId,
2010
- scorer: typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer),
2011
- preprocessStepResult: typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult),
2012
- analyzeStepResult: typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult),
2013
- score: validatedScore.score,
2014
- reason: validatedScore.reason,
2015
- preprocessPrompt: validatedScore.preprocessPrompt,
2016
- generateScorePrompt: validatedScore.generateScorePrompt,
2017
- generateReasonPrompt: validatedScore.generateReasonPrompt,
2018
- analyzePrompt: validatedScore.analyzePrompt,
2019
- input: typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input),
2020
- output: typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output),
2021
- additionalContext: typeof validatedScore.additionalContext === "string" ? validatedScore.additionalContext : JSON.stringify(validatedScore.additionalContext),
2022
- requestContext: typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext),
2023
- entityType: validatedScore.entityType,
2024
- entityData: typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity),
2025
- entityId: validatedScore.entityId,
2026
- source: validatedScore.source,
2027
- resourceId: validatedScore.resourceId || "",
2028
- threadId: validatedScore.threadId || "",
2029
- createdAt: now.toISOString(),
2030
- updatedAt: now.toISOString()
2031
- };
2026
+ const scorer = typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer);
2027
+ const preprocessStepResult = typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult);
2028
+ const analyzeStepResult = typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult);
2029
+ const input = typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input);
2030
+ const output = typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output);
2031
+ const requestContext = typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext);
2032
+ const entity = typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity);
2033
+ const scoreData = Object.fromEntries(
2034
+ Object.entries({
2035
+ ...validatedScore,
2036
+ entity: "score",
2037
+ id: scoreId,
2038
+ scorer,
2039
+ preprocessStepResult,
2040
+ analyzeStepResult,
2041
+ input,
2042
+ output,
2043
+ requestContext,
2044
+ entityData: entity,
2045
+ traceId: validatedScore.traceId || "",
2046
+ resourceId: validatedScore.resourceId || "",
2047
+ threadId: validatedScore.threadId || "",
2048
+ spanId: validatedScore.spanId || "",
2049
+ createdAt: now.toISOString(),
2050
+ updatedAt: now.toISOString()
2051
+ }).filter(([_, value]) => value !== void 0 && value !== null)
2052
+ );
2032
2053
  try {
2033
2054
  await this.service.entities.score.upsert(scoreData).go();
2034
2055
  const savedScore = {