@mastra/dynamodb 1.1.2 → 1.1.3

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 { BackgroundTasksStorage, createStorageErrorId, MemoryStorage, normalizePerPage, calculatePagination, filterByDateRange, ScoresStorage, SCORERS_SCHEMA, WorkflowsStorage, MastraCompositeStore, TABLE_BACKGROUND_TASKS, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_RESOURCES, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
4
+ import { BackgroundTasksStorage, createStorageErrorId, MemoryStorage, normalizePerPage, calculatePagination, ScoresStorage, SCORERS_SCHEMA, WorkflowsStorage, MastraCompositeStore, TABLE_BACKGROUND_TASKS, 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
7
  import { saveScorePayloadSchema } from '@mastra/core/evals';
@@ -1798,29 +1798,80 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1798
1798
  hasMore: false
1799
1799
  };
1800
1800
  }
1801
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1802
- const results = await query.go();
1803
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
1804
- if (resourceId) {
1805
- allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
1806
- }
1807
- allThreadMessages = filterByDateRange(
1808
- allThreadMessages,
1809
- (msg) => new Date(msg.createdAt),
1810
- filter?.dateRange
1811
- );
1812
- allThreadMessages.sort((a, b) => {
1813
- const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1814
- const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1815
- if (aValue === bValue) {
1816
- return a.id.localeCompare(b.id);
1801
+ const order = direction === "DESC" ? "desc" : "asc";
1802
+ const parseQueryMessages = (data) => data.map((item) => this.parseMessageData(item)).filter((msg) => "content" in msg && typeof msg.content === "object");
1803
+ const toIso = (value) => value instanceof Date ? value.toISOString() : String(value);
1804
+ const applyQueryFilters = (q) => {
1805
+ let query = q;
1806
+ const dateRange = filter?.dateRange;
1807
+ const startIso = dateRange?.start ? toIso(dateRange.start) : void 0;
1808
+ const endIso = dateRange?.end ? toIso(dateRange.end) : void 0;
1809
+ const startExclusive = dateRange?.startExclusive ?? false;
1810
+ const endExclusive = dateRange?.endExclusive ?? false;
1811
+ const startOp = startExclusive ? "gt" : "gte";
1812
+ const endOp = endExclusive ? "lt" : "lte";
1813
+ if (startIso && endIso) {
1814
+ query = query.between({ createdAt: startIso }, { createdAt: endIso });
1815
+ if (startExclusive || endExclusive) {
1816
+ query = query.where(({ createdAt }, { gt, lt }) => {
1817
+ if (startExclusive && endExclusive) {
1818
+ return `${gt(createdAt, startIso)} AND ${lt(createdAt, endIso)}`;
1819
+ }
1820
+ if (startExclusive) {
1821
+ return gt(createdAt, startIso);
1822
+ }
1823
+ return lt(createdAt, endIso);
1824
+ });
1825
+ }
1826
+ } else if (startIso) {
1827
+ query = query[startOp]({ createdAt: startIso });
1828
+ } else if (endIso) {
1829
+ query = query[endOp]({ createdAt: endIso });
1817
1830
  }
1818
- return direction === "ASC" ? aValue - bValue : bValue - aValue;
1819
- });
1820
- const total = allThreadMessages.length;
1821
- const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
1822
- const paginatedCount = paginatedMessages.length;
1823
- if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
1831
+ if (resourceId) {
1832
+ query = query.where(({ resourceId: rid }, { eq }) => eq(rid, resourceId));
1833
+ }
1834
+ return query;
1835
+ };
1836
+ let paginatedMessages = [];
1837
+ let total = 0;
1838
+ const filteredMessageIds = /* @__PURE__ */ new Set();
1839
+ if (threadIds.length > 1) {
1840
+ const threadResults = await Promise.all(
1841
+ threadIds.map(async (tid) => {
1842
+ const q = applyQueryFilters(
1843
+ this.service.entities.message.query.byThread({ entity: "message", threadId: tid })
1844
+ );
1845
+ const countResult = await q.go({ pages: "all", attributes: ["id"] });
1846
+ const results = await q.go({ pages: "all", order });
1847
+ return { ids: countResult.data.map((item) => item.id), messages: parseQueryMessages(results.data) };
1848
+ })
1849
+ );
1850
+ for (const r of threadResults) {
1851
+ for (const id of r.ids) filteredMessageIds.add(id);
1852
+ }
1853
+ total = threadResults.reduce((sum, r) => sum + r.ids.length, 0);
1854
+ const merged = threadResults.flatMap((r) => r.messages);
1855
+ const sorted = this._sortMessages(merged, field, direction);
1856
+ paginatedMessages = perPageInput === false ? sorted : sorted.slice(offset, offset + perPage);
1857
+ } else {
1858
+ const baseQuery = this.service.entities.message.query.byThread({ entity: "message", threadId: threadIds[0] });
1859
+ const query = applyQueryFilters(baseQuery);
1860
+ const countResult = await query.go({ pages: "all", attributes: ["id"] });
1861
+ total = countResult.data.length;
1862
+ for (const item of countResult.data) filteredMessageIds.add(item.id);
1863
+ if (perPageInput === false) {
1864
+ const results = await query.go({ pages: "all", order });
1865
+ paginatedMessages = parseQueryMessages(results.data);
1866
+ } else {
1867
+ const results = await query.go({ count: offset + perPage, order });
1868
+ paginatedMessages = parseQueryMessages(results.data).slice(offset, offset + perPage);
1869
+ }
1870
+ if (field !== "createdAt") {
1871
+ paginatedMessages = this._sortMessages(paginatedMessages, field, direction);
1872
+ }
1873
+ }
1874
+ if (total === 0 && paginatedMessages.length === 0 && (!include || include.length === 0)) {
1824
1875
  return {
1825
1876
  messages: [],
1826
1877
  total: 0,
@@ -1843,12 +1894,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1843
1894
  const list = new MessageList().add(paginatedMessages, "memory");
1844
1895
  let finalMessages = list.get.all.db();
1845
1896
  finalMessages = this._sortMessages(finalMessages, field, direction);
1846
- const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1847
- const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
1848
- let hasMore = false;
1849
- if (perPageInput !== false && !allThreadMessagesReturned) {
1850
- hasMore = offset + paginatedCount < total;
1851
- }
1897
+ const returnedFilteredMessageIds = new Set(
1898
+ finalMessages.filter((m) => filteredMessageIds.has(m.id)).map((m) => m.id)
1899
+ );
1900
+ const allFilteredMessagesReturned = returnedFilteredMessageIds.size >= total;
1901
+ const hasMore = perPageInput !== false && !allFilteredMessagesReturned && offset + perPage < total;
1852
1902
  return {
1853
1903
  messages: finalMessages,
1854
1904
  total,
@@ -2053,43 +2103,29 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
2053
2103
  const targetMap = /* @__PURE__ */ new Map();
2054
2104
  for (const { id, data } of targetResults) {
2055
2105
  if (data) {
2056
- targetMap.set(id, { threadId: data.threadId });
2106
+ const createdAt = typeof data.createdAt === "string" ? data.createdAt : new Date(data.createdAt).toISOString();
2107
+ targetMap.set(id, { threadId: data.threadId, createdAt });
2057
2108
  }
2058
2109
  }
2059
2110
  if (targetMap.size === 0) return [];
2060
- const threadCache = /* @__PURE__ */ new Map();
2061
- const uniqueThreadIds = [...new Set([...targetMap.values()].map((t) => t.threadId))];
2062
- await Promise.all(
2063
- uniqueThreadIds.map(async (threadId) => {
2064
- try {
2065
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
2066
- const results = await query.go();
2067
- const messages = results.data.map((data) => this.parseMessageData(data)).filter(
2068
- (msg) => "content" in msg && typeof msg.content === "object"
2069
- );
2070
- messages.sort((a, b) => {
2071
- const timeA = a.createdAt.getTime();
2072
- const timeB = b.createdAt.getTime();
2073
- if (timeA === timeB) return a.id.localeCompare(b.id);
2074
- return timeA - timeB;
2075
- });
2076
- threadCache.set(threadId, messages);
2077
- } catch {
2078
- }
2079
- })
2111
+ const parseQueryMessages = (data) => data.map((item) => this.parseMessageData(item)).filter(
2112
+ (msg) => "content" in msg && typeof msg.content === "object"
2080
2113
  );
2081
2114
  const includeMessages = [];
2082
2115
  for (const includeItem of include) {
2083
2116
  const { id, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
2084
2117
  const target = targetMap.get(id);
2085
2118
  if (!target) continue;
2086
- const allMessages = threadCache.get(target.threadId);
2087
- if (!allMessages) continue;
2088
- const targetIndex = allMessages.findIndex((msg) => msg.id === id);
2089
- if (targetIndex === -1) continue;
2090
- const startIndex = Math.max(0, targetIndex - withPreviousMessages);
2091
- const endIndex = Math.min(allMessages.length, targetIndex + withNextMessages + 1);
2092
- includeMessages.push(...allMessages.slice(startIndex, endIndex));
2119
+ try {
2120
+ const prevResult = await this.service.entities.message.query.byThread({ entity: "message", threadId: target.threadId }).lte({ createdAt: target.createdAt }).go({ order: "desc", count: withPreviousMessages + 1 });
2121
+ const prevMessages = parseQueryMessages(prevResult.data).reverse();
2122
+ includeMessages.push(...prevMessages);
2123
+ if (withNextMessages > 0) {
2124
+ const nextResult = await this.service.entities.message.query.byThread({ entity: "message", threadId: target.threadId }).gt({ createdAt: target.createdAt }).go({ order: "asc", count: withNextMessages });
2125
+ includeMessages.push(...parseQueryMessages(nextResult.data));
2126
+ }
2127
+ } catch {
2128
+ }
2093
2129
  }
2094
2130
  const seen = /* @__PURE__ */ new Set();
2095
2131
  return includeMessages.filter((msg) => {