@mastra/pg 1.0.0-beta.2 → 1.0.0-beta.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/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.0.0-beta.3
4
+
5
+ ### Patch Changes
6
+
7
+ - fix(pg): qualify vector type to fix schema lookup ([#10786](https://github.com/mastra-ai/mastra/pull/10786))
8
+
9
+ - feat(storage): support querying messages from multiple threads ([#10663](https://github.com/mastra-ai/mastra/pull/10663))
10
+ - Fixed TypeScript errors where `threadId: string | string[]` was being passed to places expecting `Scalar` type
11
+ - Added proper multi-thread support for `listMessages` across all adapters when `threadId` is an array
12
+ - Updated `_getIncludedMessages` to look up message threadId by ID (since message IDs are globally unique)
13
+ - **upstash**: Added `msg-idx:{messageId}` index for O(1) message lookups (backwards compatible with fallback to scan for old messages, with automatic backfill)
14
+
15
+ - fix: ensure score responses match saved payloads for Mastra Stores. ([#10557](https://github.com/mastra-ai/mastra/pull/10557))
16
+
17
+ - Unify transformScoreRow functions across storage adapters ([#10648](https://github.com/mastra-ai/mastra/pull/10648))
18
+
19
+ Added a unified `transformScoreRow` function in `@mastra/core/storage` that provides schema-driven row transformation for score data. This eliminates code duplication across 10 storage adapters while maintaining store-specific behavior through configurable options:
20
+ - `preferredTimestampFields`: Preferred source fields for timestamps (PostgreSQL, Cloudflare D1)
21
+ - `convertTimestamps`: Convert timestamp strings to Date objects (MSSQL, MongoDB, ClickHouse)
22
+ - `nullValuePattern`: Skip values matching pattern (ClickHouse's `'_null_'`)
23
+ - `fieldMappings`: Map source column names to schema fields (LibSQL's `additionalLLMContext`)
24
+
25
+ Each store adapter now uses the unified function with appropriate options, reducing ~200 lines of duplicate transformation logic while ensuring consistent behavior across all storage backends.
26
+
27
+ - Updated dependencies [[`ac0d2f4`](https://github.com/mastra-ai/mastra/commit/ac0d2f4ff8831f72c1c66c2be809706d17f65789), [`1a0d3fc`](https://github.com/mastra-ai/mastra/commit/1a0d3fc811482c9c376cdf79ee615c23bae9b2d6), [`85a628b`](https://github.com/mastra-ai/mastra/commit/85a628b1224a8f64cd82ea7f033774bf22df7a7e), [`c237233`](https://github.com/mastra-ai/mastra/commit/c23723399ccedf7f5744b3f40997b79246bfbe64), [`15f9e21`](https://github.com/mastra-ai/mastra/commit/15f9e216177201ea6e3f6d0bfb063fcc0953444f), [`ff94dea`](https://github.com/mastra-ai/mastra/commit/ff94dea935f4e34545c63bcb6c29804732698809), [`5b2ff46`](https://github.com/mastra-ai/mastra/commit/5b2ff4651df70c146523a7fca773f8eb0a2272f8), [`db41688`](https://github.com/mastra-ai/mastra/commit/db4168806d007417e2e60b4f68656dca4e5f40c9), [`5ca599d`](https://github.com/mastra-ai/mastra/commit/5ca599d0bb59a1595f19f58473fcd67cc71cef58), [`bff1145`](https://github.com/mastra-ai/mastra/commit/bff114556b3cbadad9b2768488708f8ad0e91475), [`5c8ca24`](https://github.com/mastra-ai/mastra/commit/5c8ca247094e0cc2cdbd7137822fb47241f86e77), [`e191844`](https://github.com/mastra-ai/mastra/commit/e1918444ca3f80e82feef1dad506cd4ec6e2875f), [`22553f1`](https://github.com/mastra-ai/mastra/commit/22553f11c63ee5e966a9c034a349822249584691), [`7237163`](https://github.com/mastra-ai/mastra/commit/72371635dbf96a87df4b073cc48fc655afbdce3d), [`2500740`](https://github.com/mastra-ai/mastra/commit/2500740ea23da067d6e50ec71c625ab3ce275e64), [`873ecbb`](https://github.com/mastra-ai/mastra/commit/873ecbb517586aa17d2f1e99283755b3ebb2863f), [`4f9bbe5`](https://github.com/mastra-ai/mastra/commit/4f9bbe5968f42c86f4930b8193de3c3c17e5bd36), [`02e51fe`](https://github.com/mastra-ai/mastra/commit/02e51feddb3d4155cfbcc42624fd0d0970d032c0), [`8f3fa3a`](https://github.com/mastra-ai/mastra/commit/8f3fa3a652bb77da092f913ec51ae46e3a7e27dc), [`cd29ad2`](https://github.com/mastra-ai/mastra/commit/cd29ad23a255534e8191f249593849ed29160886), [`bdf4d8c`](https://github.com/mastra-ai/mastra/commit/bdf4d8cdc656d8a2c21d81834bfa3bfa70f56c16), [`854e3da`](https://github.com/mastra-ai/mastra/commit/854e3dad5daac17a91a20986399d3a51f54bf68b), [`ce18d38`](https://github.com/mastra-ai/mastra/commit/ce18d38678c65870350d123955014a8432075fd9), [`cccf9c8`](https://github.com/mastra-ai/mastra/commit/cccf9c8b2d2dfc1a5e63919395b83d78c89682a0), [`61a5705`](https://github.com/mastra-ai/mastra/commit/61a570551278b6743e64243b3ce7d73de915ca8a), [`db70a48`](https://github.com/mastra-ai/mastra/commit/db70a48aeeeeb8e5f92007e8ede52c364ce15287), [`f0fdc14`](https://github.com/mastra-ai/mastra/commit/f0fdc14ee233d619266b3d2bbdeea7d25cfc6d13), [`db18bc9`](https://github.com/mastra-ai/mastra/commit/db18bc9c3825e2c1a0ad9a183cc9935f6691bfa1), [`9b37b56`](https://github.com/mastra-ai/mastra/commit/9b37b565e1f2a76c24f728945cc740c2b09be9da), [`41a23c3`](https://github.com/mastra-ai/mastra/commit/41a23c32f9877d71810f37e24930515df2ff7a0f), [`5d171ad`](https://github.com/mastra-ai/mastra/commit/5d171ad9ef340387276b77c2bb3e83e83332d729), [`f03ae60`](https://github.com/mastra-ai/mastra/commit/f03ae60500fe350c9d828621006cdafe1975fdd8), [`d1e74a0`](https://github.com/mastra-ai/mastra/commit/d1e74a0a293866dece31022047f5dbab65a304d0), [`39e7869`](https://github.com/mastra-ai/mastra/commit/39e7869bc7d0ee391077ce291474d8a84eedccff), [`5761926`](https://github.com/mastra-ai/mastra/commit/57619260c4a2cdd598763abbacd90de594c6bc76), [`c900fdd`](https://github.com/mastra-ai/mastra/commit/c900fdd504c41348efdffb205cfe80d48c38fa33), [`604a79f`](https://github.com/mastra-ai/mastra/commit/604a79fecf276e26a54a3fe01bb94e65315d2e0e), [`887f0b4`](https://github.com/mastra-ai/mastra/commit/887f0b4746cdbd7cb7d6b17ac9f82aeb58037ea5), [`2562143`](https://github.com/mastra-ai/mastra/commit/256214336b4faa78646c9c1776612393790d8784), [`ef11a61`](https://github.com/mastra-ai/mastra/commit/ef11a61920fa0ed08a5b7ceedd192875af119749)]:
28
+ - @mastra/core@1.0.0-beta.6
29
+
3
30
  ## 1.0.0-beta.2
4
31
 
5
32
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -622,9 +622,6 @@ var PgVector = class extends vector.MastraVector {
622
622
  if (this.vectorExtensionSchema === "pg_catalog") {
623
623
  return "vector";
624
624
  }
625
- if (this.vectorExtensionSchema === (this.schema || "public")) {
626
- return "vector";
627
- }
628
625
  const validatedSchema = utils.parseSqlIdentifier(this.vectorExtensionSchema, "vector extension schema");
629
626
  return `${validatedSchema}.vector`;
630
627
  }
@@ -1914,6 +1911,20 @@ var MemoryPG = class extends storage.MemoryStorage {
1914
1911
  const threadTableName = getTableName({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName(this.schema) });
1915
1912
  await this.client.tx(async (t) => {
1916
1913
  await t.none(`DELETE FROM ${tableName} WHERE thread_id = $1`, [threadId]);
1914
+ const schemaName = this.schema || "public";
1915
+ const vectorTables = await t.manyOrNone(
1916
+ `
1917
+ SELECT tablename
1918
+ FROM pg_tables
1919
+ WHERE schemaname = $1
1920
+ AND (tablename = 'memory_messages' OR tablename LIKE 'memory_messages_%')
1921
+ `,
1922
+ [schemaName]
1923
+ );
1924
+ for (const { tablename } of vectorTables) {
1925
+ const vectorTableName = getTableName({ indexName: tablename, schemaName: getSchemaName(this.schema) });
1926
+ await t.none(`DELETE FROM ${vectorTableName} WHERE metadata->>'thread_id' = $1`, [threadId]);
1927
+ }
1917
1928
  await t.none(`DELETE FROM ${threadTableName} WHERE id = $1`, [threadId]);
1918
1929
  });
1919
1930
  } catch (error$1) {
@@ -1930,28 +1941,26 @@ var MemoryPG = class extends storage.MemoryStorage {
1930
1941
  );
1931
1942
  }
1932
1943
  }
1933
- async _getIncludedMessages({
1934
- threadId,
1935
- include
1936
- }) {
1937
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1938
- if (!include) return null;
1944
+ async _getIncludedMessages({ include }) {
1945
+ if (!include || include.length === 0) return null;
1939
1946
  const unionQueries = [];
1940
1947
  const params = [];
1941
1948
  let paramIdx = 1;
1942
1949
  const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
1943
1950
  for (const inc of include) {
1944
1951
  const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
1945
- const searchId = inc.threadId || threadId;
1946
1952
  unionQueries.push(
1947
1953
  `
1948
1954
  SELECT * FROM (
1949
- WITH ordered_messages AS (
1955
+ WITH target_thread AS (
1956
+ SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx}
1957
+ ),
1958
+ ordered_messages AS (
1950
1959
  SELECT
1951
1960
  *,
1952
1961
  ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
1953
1962
  FROM ${tableName}
1954
- WHERE thread_id = $${paramIdx}
1963
+ WHERE thread_id = (SELECT thread_id FROM target_thread)
1955
1964
  )
1956
1965
  SELECT
1957
1966
  m.id,
@@ -1963,24 +1972,24 @@ var MemoryPG = class extends storage.MemoryStorage {
1963
1972
  m.thread_id AS "threadId",
1964
1973
  m."resourceId"
1965
1974
  FROM ordered_messages m
1966
- WHERE m.id = $${paramIdx + 1}
1975
+ WHERE m.id = $${paramIdx}
1967
1976
  OR EXISTS (
1968
1977
  SELECT 1 FROM ordered_messages target
1969
- WHERE target.id = $${paramIdx + 1}
1978
+ WHERE target.id = $${paramIdx}
1970
1979
  AND (
1971
1980
  -- Get previous messages (messages that come BEFORE the target)
1972
- (m.row_num < target.row_num AND m.row_num >= target.row_num - $${paramIdx + 2})
1981
+ (m.row_num < target.row_num AND m.row_num >= target.row_num - $${paramIdx + 1})
1973
1982
  OR
1974
1983
  -- Get next messages (messages that come AFTER the target)
1975
- (m.row_num > target.row_num AND m.row_num <= target.row_num + $${paramIdx + 3})
1984
+ (m.row_num > target.row_num AND m.row_num <= target.row_num + $${paramIdx + 2})
1976
1985
  )
1977
1986
  )
1978
1987
  ) AS query_${paramIdx}
1979
1988
  `
1980
1989
  // Keep ASC for final sorting after fetching context
1981
1990
  );
1982
- params.push(searchId, id, withPreviousMessages, withNextMessages);
1983
- paramIdx += 4;
1991
+ params.push(id, withPreviousMessages, withNextMessages);
1992
+ paramIdx += 3;
1984
1993
  }
1985
1994
  const finalQuery = unionQueries.join(" UNION ALL ") + ' ORDER BY "createdAt" ASC';
1986
1995
  const includedRows = await this.client.manyOrNone(finalQuery, params);
@@ -2044,15 +2053,18 @@ var MemoryPG = class extends storage.MemoryStorage {
2044
2053
  }
2045
2054
  async listMessages(args) {
2046
2055
  const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
2047
- if (!threadId.trim()) {
2056
+ const threadIds = (Array.isArray(threadId) ? threadId : [threadId]).filter(
2057
+ (id) => typeof id === "string"
2058
+ );
2059
+ if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
2048
2060
  throw new error.MastraError(
2049
2061
  {
2050
2062
  id: "STORAGE_PG_LIST_MESSAGES_INVALID_THREAD_ID",
2051
2063
  domain: error.ErrorDomain.STORAGE,
2052
2064
  category: error.ErrorCategory.THIRD_PARTY,
2053
- details: { threadId }
2065
+ details: { threadId: Array.isArray(threadId) ? String(threadId) : String(threadId) }
2054
2066
  },
2055
- new Error("threadId must be a non-empty string")
2067
+ new Error("threadId must be a non-empty string or array of non-empty strings")
2056
2068
  );
2057
2069
  }
2058
2070
  if (page < 0) {
@@ -2062,7 +2074,7 @@ var MemoryPG = class extends storage.MemoryStorage {
2062
2074
  category: error.ErrorCategory.USER,
2063
2075
  text: "Page number must be non-negative",
2064
2076
  details: {
2065
- threadId,
2077
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
2066
2078
  page
2067
2079
  }
2068
2080
  });
@@ -2074,9 +2086,10 @@ var MemoryPG = class extends storage.MemoryStorage {
2074
2086
  const orderByStatement = `ORDER BY "${field}" ${direction}`;
2075
2087
  const selectStatement = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId"`;
2076
2088
  const tableName = getTableName({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName(this.schema) });
2077
- const conditions = [`thread_id = $1`];
2078
- const queryParams = [threadId];
2079
- let paramIndex = 2;
2089
+ const threadPlaceholders = threadIds.map((_, i) => `$${i + 1}`).join(", ");
2090
+ const conditions = [`thread_id IN (${threadPlaceholders})`];
2091
+ const queryParams = [...threadIds];
2092
+ let paramIndex = threadIds.length + 1;
2080
2093
  if (resourceId) {
2081
2094
  conditions.push(`"resourceId" = $${paramIndex++}`);
2082
2095
  queryParams.push(resourceId);
@@ -2108,7 +2121,7 @@ var MemoryPG = class extends storage.MemoryStorage {
2108
2121
  }
2109
2122
  const messageIds = new Set(messages.map((m) => m.id));
2110
2123
  if (include && include.length > 0) {
2111
- const includeMessages = await this._getIncludedMessages({ threadId, include });
2124
+ const includeMessages = await this._getIncludedMessages({ include });
2112
2125
  if (includeMessages) {
2113
2126
  for (const includeMsg of includeMessages) {
2114
2127
  if (!messageIds.has(includeMsg.id)) {
@@ -2135,7 +2148,10 @@ var MemoryPG = class extends storage.MemoryStorage {
2135
2148
  }
2136
2149
  return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
2137
2150
  });
2138
- const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
2151
+ const threadIdSet = new Set(threadIds);
2152
+ const returnedThreadMessageIds = new Set(
2153
+ finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
2154
+ );
2139
2155
  const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
2140
2156
  const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
2141
2157
  return {
@@ -2152,7 +2168,7 @@ var MemoryPG = class extends storage.MemoryStorage {
2152
2168
  domain: error.ErrorDomain.STORAGE,
2153
2169
  category: error.ErrorCategory.THIRD_PARTY,
2154
2170
  details: {
2155
- threadId,
2171
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
2156
2172
  resourceId: resourceId ?? ""
2157
2173
  }
2158
2174
  },
@@ -3607,20 +3623,12 @@ var StoreOperationsPG = class extends storage.StoreOperations {
3607
3623
  }
3608
3624
  };
3609
3625
  function transformScoreRow(row) {
3610
- return {
3611
- ...row,
3612
- input: storage.safelyParseJSON(row.input),
3613
- scorer: storage.safelyParseJSON(row.scorer),
3614
- preprocessStepResult: storage.safelyParseJSON(row.preprocessStepResult),
3615
- analyzeStepResult: storage.safelyParseJSON(row.analyzeStepResult),
3616
- metadata: storage.safelyParseJSON(row.metadata),
3617
- output: storage.safelyParseJSON(row.output),
3618
- additionalContext: storage.safelyParseJSON(row.additionalContext),
3619
- requestContext: storage.safelyParseJSON(row.requestContext),
3620
- entity: storage.safelyParseJSON(row.entity),
3621
- createdAt: row.createdAtZ || row.createdAt,
3622
- updatedAt: row.updatedAtZ || row.updatedAt
3623
- };
3626
+ return storage.transformScoreRow(row, {
3627
+ preferredTimestampFields: {
3628
+ createdAt: "createdAtZ",
3629
+ updatedAt: "updatedAtZ"
3630
+ }
3631
+ });
3624
3632
  }
3625
3633
  var ScoresPG = class extends storage.ScoresStorage {
3626
3634
  client;
@@ -3767,8 +3775,6 @@ var ScoresPG = class extends storage.ScoresStorage {
3767
3775
  scorer: scorer ? JSON.stringify(scorer) : null,
3768
3776
  preprocessStepResult: preprocessStepResult ? JSON.stringify(preprocessStepResult) : null,
3769
3777
  analyzeStepResult: analyzeStepResult ? JSON.stringify(analyzeStepResult) : null,
3770
- metadata: metadata ? JSON.stringify(metadata) : null,
3771
- additionalContext: additionalContext ? JSON.stringify(additionalContext) : null,
3772
3778
  requestContext: requestContext ? JSON.stringify(requestContext) : null,
3773
3779
  entity: entity ? JSON.stringify(entity) : null,
3774
3780
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),