@mastra/convex 1.2.1-alpha.0 → 1.2.1-alpha.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,4 +1,4 @@
1
- export { mastraCache, mastraNativeVectorAction, mastraNativeVectorMutation, mastraNativeVectorQuery, mastraStorage } from './chunk-5T45UI6I.js';
1
+ export { mastraCache, mastraNativeVectorAction, mastraNativeVectorMutation, mastraNativeVectorQuery, mastraStorage } from './chunk-77UWNT5X.js';
2
2
  export { TABLE_BACKGROUND_TASKS, TABLE_CHANNEL_CONFIG, TABLE_CHANNEL_INSTALLATIONS, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCORERS, TABLE_THREADS, TABLE_WORKFLOW_SNAPSHOT, defineMastraNativeVectorTable, mastraBackgroundTasksTable, mastraCacheListItemsTable, mastraCacheTable, mastraChannelConfigTable, mastraChannelInstallationsTable, mastraDocumentsTable, mastraMessagesTable, mastraResourcesTable, mastraScheduleTriggersTable, mastraSchedulesTable, mastraScoresTable, mastraThreadsTable, mastraVectorIndexesTable, mastraVectorsTable, mastraWorkflowSnapshotsTable } from './chunk-MC75WADX.js';
3
3
  import { MastraServerCache } from '@mastra/core/cache';
4
4
  import { MastraCompositeStore, createVectorErrorId, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, createStorageErrorId, normalizePerPage, calculatePagination, filterByDateRange, safelyParseJSON, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, ScoresStorage, TABLE_SCORERS, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, SchedulesStorage, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEDULES, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS } from '@mastra/core/storage';
@@ -221,7 +221,8 @@ var ConvexAdminClient = class {
221
221
  }
222
222
  return {
223
223
  result: storageResponse.result,
224
- hasMore: storageResponse.hasMore
224
+ hasMore: storageResponse.hasMore,
225
+ continuationCursor: storageResponse.continuationCursor
225
226
  };
226
227
  }
227
228
  async callStorage(request) {
@@ -274,6 +275,7 @@ var ConvexAdminClient = class {
274
275
  return result;
275
276
  }
276
277
  };
278
+ var LOAD_MANY_REQUEST_BATCH_SIZE = 10;
277
279
  function resolveConvexConfig(config) {
278
280
  if ("client" in config) {
279
281
  return config.client;
@@ -349,6 +351,38 @@ var ConvexDB = class extends MastraBase {
349
351
  record: this.normalizePatch(record)
350
352
  });
351
353
  }
354
+ async updateThread({
355
+ id,
356
+ title,
357
+ metadata,
358
+ updatedAt
359
+ }) {
360
+ return this.client.callStorage({
361
+ op: "updateThread",
362
+ tableName: TABLE_THREADS,
363
+ id,
364
+ title,
365
+ metadata,
366
+ updatedAt: updatedAt.toISOString()
367
+ });
368
+ }
369
+ async updateResource({
370
+ resourceId,
371
+ workingMemory,
372
+ metadata,
373
+ createdAt,
374
+ updatedAt
375
+ }) {
376
+ return this.client.callStorage({
377
+ op: "updateResource",
378
+ tableName: TABLE_RESOURCES,
379
+ resourceId,
380
+ ...workingMemory !== void 0 ? { workingMemory } : {},
381
+ ...metadata !== void 0 ? { metadata } : {},
382
+ createdAt: createdAt.toISOString(),
383
+ updatedAt: updatedAt.toISOString()
384
+ });
385
+ }
352
386
  async load({ tableName, keys }) {
353
387
  const result = await this.client.callStorage({
354
388
  op: "load",
@@ -357,6 +391,21 @@ var ConvexDB = class extends MastraBase {
357
391
  });
358
392
  return result;
359
393
  }
394
+ async loadMany(tableName, ids) {
395
+ const uniqueIds = [...new Set(ids)];
396
+ if (uniqueIds.length === 0) return [];
397
+ const rows = [];
398
+ for (let index = 0; index < uniqueIds.length; index += LOAD_MANY_REQUEST_BATCH_SIZE) {
399
+ rows.push(
400
+ ...await this.client.callStorage({
401
+ op: "loadMany",
402
+ tableName,
403
+ ids: uniqueIds.slice(index, index + LOAD_MANY_REQUEST_BATCH_SIZE)
404
+ })
405
+ );
406
+ }
407
+ return rows;
408
+ }
360
409
  async queryTable(tableName, filters, indexHint, limit) {
361
410
  return this.client.callStorage({
362
411
  op: "queryTable",
@@ -835,6 +884,23 @@ var ChannelsConvex = class extends ChannelsStorage {
835
884
  await this.#db.deleteMany(TABLE_CHANNEL_CONFIG, [platform]);
836
885
  }
837
886
  };
887
+ function parseStoredThread(row) {
888
+ return {
889
+ ...row,
890
+ metadata: typeof row.metadata === "string" ? safelyParseJSON(row.metadata) : row.metadata,
891
+ createdAt: new Date(row.createdAt),
892
+ updatedAt: new Date(row.updatedAt)
893
+ };
894
+ }
895
+ function parseStoredResource(record) {
896
+ const metadata = typeof record.metadata === "string" ? safelyParseJSON(record.metadata) : record.metadata;
897
+ return {
898
+ ...record,
899
+ metadata: metadata ?? {},
900
+ createdAt: new Date(record.createdAt),
901
+ updatedAt: new Date(record.updatedAt)
902
+ };
903
+ }
838
904
  var MemoryConvex = class extends MemoryStorage {
839
905
  #db;
840
906
  constructor(config) {
@@ -858,12 +924,7 @@ var MemoryConvex = class extends MemoryStorage {
858
924
  keys: { id: threadId }
859
925
  });
860
926
  if (!row || resourceId !== void 0 && row.resourceId !== resourceId) return null;
861
- return {
862
- ...row,
863
- metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata,
864
- createdAt: new Date(row.createdAt),
865
- updatedAt: new Date(row.updatedAt)
866
- };
927
+ return parseStoredThread(row);
867
928
  }
868
929
  async saveThread({ thread }) {
869
930
  await this.#db.insert({
@@ -880,8 +941,13 @@ var MemoryConvex = class extends MemoryStorage {
880
941
  title,
881
942
  metadata
882
943
  }) {
883
- const existing = await this.getThreadById({ threadId: id });
884
- if (!existing) {
944
+ const updated = await this.#db.updateThread({
945
+ id,
946
+ title,
947
+ metadata,
948
+ updatedAt: /* @__PURE__ */ new Date()
949
+ });
950
+ if (!updated) {
885
951
  throw new MastraError({
886
952
  id: createStorageErrorId("CONVEX", "UPDATE_THREAD", "THREAD_NOT_FOUND"),
887
953
  domain: ErrorDomain.STORAGE,
@@ -889,17 +955,7 @@ var MemoryConvex = class extends MemoryStorage {
889
955
  text: `Thread ${id} not found`
890
956
  });
891
957
  }
892
- const updated = {
893
- ...existing,
894
- title,
895
- metadata: {
896
- ...existing.metadata,
897
- ...metadata
898
- },
899
- updatedAt: /* @__PURE__ */ new Date()
900
- };
901
- await this.saveThread({ thread: updated });
902
- return updated;
958
+ return parseStoredThread(updated);
903
959
  }
904
960
  async deleteThread({ threadId }) {
905
961
  const messages = await this.#db.queryTable(TABLE_MESSAGES, [
@@ -927,6 +983,19 @@ var MemoryConvex = class extends MemoryStorage {
927
983
  );
928
984
  }
929
985
  const perPage = normalizePerPage(perPageInput, 100);
986
+ try {
987
+ this.validateMetadataKeys(filter?.metadata);
988
+ } catch (error) {
989
+ throw new MastraError(
990
+ {
991
+ id: createStorageErrorId("CONVEX", "LIST_THREADS", "INVALID_METADATA_KEY"),
992
+ domain: ErrorDomain.STORAGE,
993
+ category: ErrorCategory.USER,
994
+ details: { metadataKeys: filter?.metadata ? Object.keys(filter.metadata).join(", ") : "" }
995
+ },
996
+ error instanceof Error ? error : new Error("Invalid metadata key")
997
+ );
998
+ }
930
999
  const { field, direction } = this.parseOrderBy(orderBy);
931
1000
  const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
932
1001
  const queryFilters = [];
@@ -934,15 +1003,10 @@ var MemoryConvex = class extends MemoryStorage {
934
1003
  queryFilters.push({ field: "resourceId", value: filter.resourceId });
935
1004
  }
936
1005
  const rows = await this.#db.queryTable(TABLE_THREADS, queryFilters);
937
- let threads = rows.map((row) => ({
938
- ...row,
939
- metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata,
940
- createdAt: new Date(row.createdAt),
941
- updatedAt: new Date(row.updatedAt)
942
- }));
1006
+ let threads = rows.map((row) => parseStoredThread(row));
943
1007
  if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
944
1008
  threads = threads.filter((thread) => {
945
- if (!thread.metadata) return false;
1009
+ if (!thread.metadata || typeof thread.metadata !== "object" || Array.isArray(thread.metadata)) return false;
946
1010
  return Object.entries(filter.metadata).every(([key, value]) => thread.metadata[key] === value);
947
1011
  });
948
1012
  }
@@ -1047,8 +1111,8 @@ var MemoryConvex = class extends MemoryStorage {
1047
1111
  if (messageIds.length === 0) {
1048
1112
  return { messages: [] };
1049
1113
  }
1050
- const rows = await this.#db.queryTable(TABLE_MESSAGES, void 0);
1051
- const filtered = rows.filter((row) => messageIds.includes(row.id)).map((row) => this.parseStoredMessage(row));
1114
+ const rows = await this.#db.loadMany(TABLE_MESSAGES, messageIds);
1115
+ const filtered = rows.map((row) => this.parseStoredMessage(row));
1052
1116
  const list = new MessageList().add(filtered, "memory");
1053
1117
  return { messages: list.get.all.db() };
1054
1118
  }
@@ -1079,19 +1143,11 @@ var MemoryConvex = class extends MemoryStorage {
1079
1143
  const threadIds = [...new Set(messages.map((m) => m.threadId).filter(Boolean))];
1080
1144
  const now = /* @__PURE__ */ new Date();
1081
1145
  for (const threadId of threadIds) {
1082
- const thread = await this.getThreadById({ threadId });
1083
- if (thread) {
1084
- await this.#db.insert({
1085
- tableName: TABLE_THREADS,
1086
- record: {
1087
- ...thread,
1088
- id: thread.id,
1089
- updatedAt: now.toISOString(),
1090
- createdAt: thread.createdAt instanceof Date ? thread.createdAt.toISOString() : thread.createdAt,
1091
- metadata: thread.metadata ?? {}
1092
- }
1093
- });
1094
- }
1146
+ await this.#db.patch({
1147
+ tableName: TABLE_THREADS,
1148
+ id: threadId,
1149
+ record: { updatedAt: now.toISOString() }
1150
+ });
1095
1151
  }
1096
1152
  const list = new MessageList().add(messages, "memory");
1097
1153
  return { messages: list.get.all.db() };
@@ -1100,11 +1156,15 @@ var MemoryConvex = class extends MemoryStorage {
1100
1156
  messages
1101
1157
  }) {
1102
1158
  if (messages.length === 0) return [];
1103
- const existing = await this.#db.queryTable(TABLE_MESSAGES, void 0);
1159
+ const existingRows = await this.#db.loadMany(
1160
+ TABLE_MESSAGES,
1161
+ messages.map((message) => message.id)
1162
+ );
1163
+ const existing = new Map(existingRows.map((row) => [row.id, row]));
1104
1164
  const updated = [];
1105
1165
  const affectedThreadIds = /* @__PURE__ */ new Set();
1106
1166
  for (const update of messages) {
1107
- const current = existing.find((row) => row.id === update.id);
1167
+ const current = existing.get(update.id);
1108
1168
  if (!current) continue;
1109
1169
  affectedThreadIds.add(current.thread_id);
1110
1170
  if (update.threadId) {
@@ -1137,19 +1197,11 @@ var MemoryConvex = class extends MemoryStorage {
1137
1197
  }
1138
1198
  const now = /* @__PURE__ */ new Date();
1139
1199
  for (const threadId of affectedThreadIds) {
1140
- const thread = await this.getThreadById({ threadId });
1141
- if (thread) {
1142
- await this.#db.insert({
1143
- tableName: TABLE_THREADS,
1144
- record: {
1145
- ...thread,
1146
- id: thread.id,
1147
- updatedAt: now.toISOString(),
1148
- createdAt: thread.createdAt instanceof Date ? thread.createdAt.toISOString() : thread.createdAt,
1149
- metadata: thread.metadata ?? {}
1150
- }
1151
- });
1152
- }
1200
+ await this.#db.patch({
1201
+ tableName: TABLE_THREADS,
1202
+ id: threadId,
1203
+ record: { updatedAt: now.toISOString() }
1204
+ });
1153
1205
  }
1154
1206
  return updated;
1155
1207
  }
@@ -1177,41 +1229,22 @@ var MemoryConvex = class extends MemoryStorage {
1177
1229
  keys: { id: resourceId }
1178
1230
  });
1179
1231
  if (!record) return null;
1180
- return {
1181
- ...record,
1182
- metadata: typeof record.metadata === "string" ? safelyParseJSON(record.metadata) : record.metadata,
1183
- createdAt: new Date(record.createdAt),
1184
- updatedAt: new Date(record.updatedAt)
1185
- };
1232
+ return parseStoredResource(record);
1186
1233
  }
1187
1234
  async updateResource({
1188
1235
  resourceId,
1189
1236
  workingMemory,
1190
1237
  metadata
1191
1238
  }) {
1192
- const existing = await this.getResourceById({ resourceId });
1193
1239
  const now = /* @__PURE__ */ new Date();
1194
- if (!existing) {
1195
- const created = {
1196
- id: resourceId,
1197
- workingMemory,
1198
- metadata: metadata ?? {},
1199
- createdAt: now,
1200
- updatedAt: now
1201
- };
1202
- return this.saveResource({ resource: created });
1203
- }
1204
- const updated = {
1205
- ...existing,
1206
- workingMemory: workingMemory ?? existing.workingMemory,
1207
- metadata: {
1208
- ...existing.metadata,
1209
- ...metadata
1210
- },
1240
+ const updated = await this.#db.updateResource({
1241
+ resourceId,
1242
+ workingMemory,
1243
+ metadata,
1244
+ createdAt: now,
1211
1245
  updatedAt: now
1212
- };
1213
- await this.saveResource({ resource: updated });
1214
- return updated;
1246
+ });
1247
+ return parseStoredResource(updated);
1215
1248
  }
1216
1249
  _sortMessages(messages, field, direction) {
1217
1250
  return messages.sort((a, b) => {
@@ -1844,6 +1877,7 @@ var ConvexStore = class extends MastraCompositeStore {
1844
1877
  }
1845
1878
  };
1846
1879
  var INDEX_METADATA_TABLE = "mastra_vector_indexes";
1880
+ var VECTOR_QUERY_PAGE_SIZE = 256;
1847
1881
  var ConvexVector = class extends MastraVector {
1848
1882
  client;
1849
1883
  constructor(config) {
@@ -1896,10 +1930,7 @@ var ConvexVector = class extends MastraVector {
1896
1930
  if (!index) {
1897
1931
  throw new Error(`Index ${indexName} not found`);
1898
1932
  }
1899
- const vectors = await this.callStorage({
1900
- op: "queryTable",
1901
- tableName: this.vectorTable(indexName)
1902
- });
1933
+ const vectors = await this.queryAllVectors(indexName);
1903
1934
  return {
1904
1935
  dimension: index.dimension,
1905
1936
  count: vectors.length,
@@ -1936,10 +1967,7 @@ var ConvexVector = class extends MastraVector {
1936
1967
  details: { indexName }
1937
1968
  });
1938
1969
  }
1939
- const vectors = await this.callStorage({
1940
- op: "queryTable",
1941
- tableName: this.vectorTable(indexName)
1942
- });
1970
+ const vectors = await this.queryAllVectors(indexName);
1943
1971
  const filtered = filter && !this.isEmptyFilter(filter) ? vectors.filter((record) => this.matchesFilter(record.metadata, filter)) : vectors;
1944
1972
  const scored = filtered.map((record) => ({
1945
1973
  id: record.id,
@@ -1960,10 +1988,7 @@ var ConvexVector = class extends MastraVector {
1960
1988
  if (this.isEmptyFilter(filter)) {
1961
1989
  throw new Error("ConvexVector.updateVector: cannot update with empty filter");
1962
1990
  }
1963
- const vectors = await this.callStorage({
1964
- op: "queryTable",
1965
- tableName: this.vectorTable(params.indexName)
1966
- });
1991
+ const vectors = await this.queryAllVectors(params.indexName);
1967
1992
  const matching = vectors.filter((record) => this.matchesFilter(record.metadata, filter));
1968
1993
  for (const existing2 of matching) {
1969
1994
  const updated2 = {
@@ -2032,10 +2057,7 @@ var ConvexVector = class extends MastraVector {
2032
2057
  if (this.isEmptyFilter(filter)) {
2033
2058
  throw new Error("ConvexVector.deleteVectors: cannot delete with empty filter");
2034
2059
  }
2035
- const vectors = await this.callStorage({
2036
- op: "queryTable",
2037
- tableName: this.vectorTable(indexName)
2038
- });
2060
+ const vectors = await this.queryAllVectors(indexName);
2039
2061
  const matchingIds = vectors.filter((record) => this.matchesFilter(record.metadata, filter)).map((record) => record.id);
2040
2062
  if (matchingIds.length > 0) {
2041
2063
  await this.callStorage({
@@ -2123,6 +2145,27 @@ var ConvexVector = class extends MastraVector {
2123
2145
  async callStorage(request) {
2124
2146
  return this.client.callStorage(request);
2125
2147
  }
2148
+ async queryAllVectors(indexName) {
2149
+ const vectors = [];
2150
+ let cursor = null;
2151
+ let hasMore = true;
2152
+ while (hasMore) {
2153
+ const response = await this.client.callStorageRaw({
2154
+ op: "queryTable",
2155
+ tableName: this.vectorTable(indexName),
2156
+ pageSize: VECTOR_QUERY_PAGE_SIZE,
2157
+ cursor
2158
+ });
2159
+ vectors.push(...response.result);
2160
+ const nextCursor = response.continuationCursor ?? null;
2161
+ hasMore = response.hasMore ?? false;
2162
+ if (hasMore && (!nextCursor || nextCursor === cursor)) {
2163
+ throw new Error("ConvexVector: paginated vector query did not return a valid continuation cursor");
2164
+ }
2165
+ cursor = nextCursor;
2166
+ }
2167
+ return vectors;
2168
+ }
2126
2169
  /**
2127
2170
  * Call storage repeatedly until hasMore is false.
2128
2171
  * Use for bulk operations like clearTable that may need multiple batches.