@mastra/convex 1.2.0 → 1.2.1-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
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkORSDZTO4_cjs = require('./chunk-ORSDZTO4.cjs');
3
+ var chunkZFDTGYKC_cjs = require('./chunk-ZFDTGYKC.cjs');
4
4
  var chunkSFRHJGSM_cjs = require('./chunk-SFRHJGSM.cjs');
5
5
  var cache = require('@mastra/core/cache');
6
6
  var storage = require('@mastra/core/storage');
@@ -227,7 +227,8 @@ var ConvexAdminClient = class {
227
227
  }
228
228
  return {
229
229
  result: storageResponse.result,
230
- hasMore: storageResponse.hasMore
230
+ hasMore: storageResponse.hasMore,
231
+ continuationCursor: storageResponse.continuationCursor
231
232
  };
232
233
  }
233
234
  async callStorage(request) {
@@ -355,6 +356,38 @@ var ConvexDB = class extends base.MastraBase {
355
356
  record: this.normalizePatch(record)
356
357
  });
357
358
  }
359
+ async updateThread({
360
+ id,
361
+ title,
362
+ metadata,
363
+ updatedAt
364
+ }) {
365
+ return this.client.callStorage({
366
+ op: "updateThread",
367
+ tableName: storage.TABLE_THREADS,
368
+ id,
369
+ title,
370
+ metadata,
371
+ updatedAt: updatedAt.toISOString()
372
+ });
373
+ }
374
+ async updateResource({
375
+ resourceId,
376
+ workingMemory,
377
+ metadata,
378
+ createdAt,
379
+ updatedAt
380
+ }) {
381
+ return this.client.callStorage({
382
+ op: "updateResource",
383
+ tableName: storage.TABLE_RESOURCES,
384
+ resourceId,
385
+ ...workingMemory !== void 0 ? { workingMemory } : {},
386
+ ...metadata !== void 0 ? { metadata } : {},
387
+ createdAt: createdAt.toISOString(),
388
+ updatedAt: updatedAt.toISOString()
389
+ });
390
+ }
358
391
  async load({ tableName, keys }) {
359
392
  const result = await this.client.callStorage({
360
393
  op: "load",
@@ -380,6 +413,44 @@ var ConvexDB = class extends base.MastraBase {
380
413
  ids
381
414
  });
382
415
  }
416
+ async mergeWorkflowStepResult({
417
+ workflowName,
418
+ runId,
419
+ stepId,
420
+ result,
421
+ requestContext
422
+ }) {
423
+ const context = await this.client.callStorage({
424
+ op: "mergeWorkflowStepResult",
425
+ tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
426
+ workflowName,
427
+ runId,
428
+ stepId,
429
+ result: JSON.stringify(result),
430
+ requestContext: JSON.stringify(requestContext)
431
+ });
432
+ if (!context) {
433
+ throw new Error(`Convex workflow step merge returned no context for runId ${runId}`);
434
+ }
435
+ return JSON.parse(context);
436
+ }
437
+ async mergeWorkflowState({
438
+ workflowName,
439
+ runId,
440
+ opts
441
+ }) {
442
+ const snapshot = await this.client.callStorage({
443
+ op: "mergeWorkflowState",
444
+ tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
445
+ workflowName,
446
+ runId,
447
+ opts: JSON.stringify(opts)
448
+ });
449
+ if (!snapshot) {
450
+ throw new Error(`Convex workflow state merge returned no snapshot for runId ${runId}`);
451
+ }
452
+ return JSON.parse(snapshot);
453
+ }
383
454
  async createSchedule(record) {
384
455
  if (!record.id) {
385
456
  throw new Error(`Schedule is missing an id`);
@@ -803,6 +874,23 @@ var ChannelsConvex = class extends storage.ChannelsStorage {
803
874
  await this.#db.deleteMany(storage.TABLE_CHANNEL_CONFIG, [platform]);
804
875
  }
805
876
  };
877
+ function parseStoredThread(row) {
878
+ return {
879
+ ...row,
880
+ metadata: typeof row.metadata === "string" ? storage.safelyParseJSON(row.metadata) : row.metadata,
881
+ createdAt: new Date(row.createdAt),
882
+ updatedAt: new Date(row.updatedAt)
883
+ };
884
+ }
885
+ function parseStoredResource(record) {
886
+ const metadata = typeof record.metadata === "string" ? storage.safelyParseJSON(record.metadata) : record.metadata;
887
+ return {
888
+ ...record,
889
+ metadata: metadata ?? {},
890
+ createdAt: new Date(record.createdAt),
891
+ updatedAt: new Date(record.updatedAt)
892
+ };
893
+ }
806
894
  var MemoryConvex = class extends storage.MemoryStorage {
807
895
  #db;
808
896
  constructor(config) {
@@ -826,12 +914,7 @@ var MemoryConvex = class extends storage.MemoryStorage {
826
914
  keys: { id: threadId }
827
915
  });
828
916
  if (!row || resourceId !== void 0 && row.resourceId !== resourceId) return null;
829
- return {
830
- ...row,
831
- metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata,
832
- createdAt: new Date(row.createdAt),
833
- updatedAt: new Date(row.updatedAt)
834
- };
917
+ return parseStoredThread(row);
835
918
  }
836
919
  async saveThread({ thread }) {
837
920
  await this.#db.insert({
@@ -848,8 +931,13 @@ var MemoryConvex = class extends storage.MemoryStorage {
848
931
  title,
849
932
  metadata
850
933
  }) {
851
- const existing = await this.getThreadById({ threadId: id });
852
- if (!existing) {
934
+ const updated = await this.#db.updateThread({
935
+ id,
936
+ title,
937
+ metadata,
938
+ updatedAt: /* @__PURE__ */ new Date()
939
+ });
940
+ if (!updated) {
853
941
  throw new error.MastraError({
854
942
  id: storage.createStorageErrorId("CONVEX", "UPDATE_THREAD", "THREAD_NOT_FOUND"),
855
943
  domain: error.ErrorDomain.STORAGE,
@@ -857,17 +945,7 @@ var MemoryConvex = class extends storage.MemoryStorage {
857
945
  text: `Thread ${id} not found`
858
946
  });
859
947
  }
860
- const updated = {
861
- ...existing,
862
- title,
863
- metadata: {
864
- ...existing.metadata,
865
- ...metadata
866
- },
867
- updatedAt: /* @__PURE__ */ new Date()
868
- };
869
- await this.saveThread({ thread: updated });
870
- return updated;
948
+ return parseStoredThread(updated);
871
949
  }
872
950
  async deleteThread({ threadId }) {
873
951
  const messages = await this.#db.queryTable(storage.TABLE_MESSAGES, [
@@ -895,6 +973,19 @@ var MemoryConvex = class extends storage.MemoryStorage {
895
973
  );
896
974
  }
897
975
  const perPage = storage.normalizePerPage(perPageInput, 100);
976
+ try {
977
+ this.validateMetadataKeys(filter?.metadata);
978
+ } catch (error$1) {
979
+ throw new error.MastraError(
980
+ {
981
+ id: storage.createStorageErrorId("CONVEX", "LIST_THREADS", "INVALID_METADATA_KEY"),
982
+ domain: error.ErrorDomain.STORAGE,
983
+ category: error.ErrorCategory.USER,
984
+ details: { metadataKeys: filter?.metadata ? Object.keys(filter.metadata).join(", ") : "" }
985
+ },
986
+ error$1 instanceof Error ? error$1 : new Error("Invalid metadata key")
987
+ );
988
+ }
898
989
  const { field, direction } = this.parseOrderBy(orderBy);
899
990
  const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
900
991
  const queryFilters = [];
@@ -902,15 +993,10 @@ var MemoryConvex = class extends storage.MemoryStorage {
902
993
  queryFilters.push({ field: "resourceId", value: filter.resourceId });
903
994
  }
904
995
  const rows = await this.#db.queryTable(storage.TABLE_THREADS, queryFilters);
905
- let threads = rows.map((row) => ({
906
- ...row,
907
- metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata,
908
- createdAt: new Date(row.createdAt),
909
- updatedAt: new Date(row.updatedAt)
910
- }));
996
+ let threads = rows.map((row) => parseStoredThread(row));
911
997
  if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
912
998
  threads = threads.filter((thread) => {
913
- if (!thread.metadata) return false;
999
+ if (!thread.metadata || typeof thread.metadata !== "object" || Array.isArray(thread.metadata)) return false;
914
1000
  return Object.entries(filter.metadata).every(([key, value]) => thread.metadata[key] === value);
915
1001
  });
916
1002
  }
@@ -1047,19 +1133,11 @@ var MemoryConvex = class extends storage.MemoryStorage {
1047
1133
  const threadIds = [...new Set(messages.map((m) => m.threadId).filter(Boolean))];
1048
1134
  const now = /* @__PURE__ */ new Date();
1049
1135
  for (const threadId of threadIds) {
1050
- const thread = await this.getThreadById({ threadId });
1051
- if (thread) {
1052
- await this.#db.insert({
1053
- tableName: storage.TABLE_THREADS,
1054
- record: {
1055
- ...thread,
1056
- id: thread.id,
1057
- updatedAt: now.toISOString(),
1058
- createdAt: thread.createdAt instanceof Date ? thread.createdAt.toISOString() : thread.createdAt,
1059
- metadata: thread.metadata ?? {}
1060
- }
1061
- });
1062
- }
1136
+ await this.#db.patch({
1137
+ tableName: storage.TABLE_THREADS,
1138
+ id: threadId,
1139
+ record: { updatedAt: now.toISOString() }
1140
+ });
1063
1141
  }
1064
1142
  const list = new agent.MessageList().add(messages, "memory");
1065
1143
  return { messages: list.get.all.db() };
@@ -1105,19 +1183,11 @@ var MemoryConvex = class extends storage.MemoryStorage {
1105
1183
  }
1106
1184
  const now = /* @__PURE__ */ new Date();
1107
1185
  for (const threadId of affectedThreadIds) {
1108
- const thread = await this.getThreadById({ threadId });
1109
- if (thread) {
1110
- await this.#db.insert({
1111
- tableName: storage.TABLE_THREADS,
1112
- record: {
1113
- ...thread,
1114
- id: thread.id,
1115
- updatedAt: now.toISOString(),
1116
- createdAt: thread.createdAt instanceof Date ? thread.createdAt.toISOString() : thread.createdAt,
1117
- metadata: thread.metadata ?? {}
1118
- }
1119
- });
1120
- }
1186
+ await this.#db.patch({
1187
+ tableName: storage.TABLE_THREADS,
1188
+ id: threadId,
1189
+ record: { updatedAt: now.toISOString() }
1190
+ });
1121
1191
  }
1122
1192
  return updated;
1123
1193
  }
@@ -1145,41 +1215,22 @@ var MemoryConvex = class extends storage.MemoryStorage {
1145
1215
  keys: { id: resourceId }
1146
1216
  });
1147
1217
  if (!record) return null;
1148
- return {
1149
- ...record,
1150
- metadata: typeof record.metadata === "string" ? storage.safelyParseJSON(record.metadata) : record.metadata,
1151
- createdAt: new Date(record.createdAt),
1152
- updatedAt: new Date(record.updatedAt)
1153
- };
1218
+ return parseStoredResource(record);
1154
1219
  }
1155
1220
  async updateResource({
1156
1221
  resourceId,
1157
1222
  workingMemory,
1158
1223
  metadata
1159
1224
  }) {
1160
- const existing = await this.getResourceById({ resourceId });
1161
1225
  const now = /* @__PURE__ */ new Date();
1162
- if (!existing) {
1163
- const created = {
1164
- id: resourceId,
1165
- workingMemory,
1166
- metadata: metadata ?? {},
1167
- createdAt: now,
1168
- updatedAt: now
1169
- };
1170
- return this.saveResource({ resource: created });
1171
- }
1172
- const updated = {
1173
- ...existing,
1174
- workingMemory: workingMemory ?? existing.workingMemory,
1175
- metadata: {
1176
- ...existing.metadata,
1177
- ...metadata
1178
- },
1226
+ const updated = await this.#db.updateResource({
1227
+ resourceId,
1228
+ workingMemory,
1229
+ metadata,
1230
+ createdAt: now,
1179
1231
  updatedAt: now
1180
- };
1181
- await this.saveResource({ resource: updated });
1182
- return updated;
1232
+ });
1233
+ return parseStoredResource(updated);
1183
1234
  }
1184
1235
  _sortMessages(messages, field, direction) {
1185
1236
  return messages.sort((a, b) => {
@@ -1640,22 +1691,18 @@ var WorkflowsConvex = class extends storage.WorkflowsStorage {
1640
1691
  this.#db = new ConvexDB(client);
1641
1692
  }
1642
1693
  supportsConcurrentUpdates() {
1643
- return false;
1694
+ return true;
1644
1695
  }
1645
1696
  async init() {
1646
1697
  }
1647
1698
  async dangerouslyClearAll() {
1648
1699
  await this.#db.clearTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT });
1649
1700
  }
1650
- async updateWorkflowResults(_args) {
1651
- throw new Error(
1652
- "updateWorkflowResults is not implemented for Convex storage. Convex does not support atomic read-modify-write operations needed for concurrent workflow updates."
1653
- );
1701
+ async updateWorkflowResults(args) {
1702
+ return this.#db.mergeWorkflowStepResult(args);
1654
1703
  }
1655
- async updateWorkflowState(_args) {
1656
- throw new Error(
1657
- "updateWorkflowState is not implemented for Convex storage. Convex does not support atomic read-modify-write operations needed for concurrent workflow updates."
1658
- );
1704
+ async updateWorkflowState(args) {
1705
+ return this.#db.mergeWorkflowState(args);
1659
1706
  }
1660
1707
  async persistWorkflowSnapshot({
1661
1708
  workflowName,
@@ -1816,6 +1863,7 @@ var ConvexStore = class extends storage.MastraCompositeStore {
1816
1863
  }
1817
1864
  };
1818
1865
  var INDEX_METADATA_TABLE = "mastra_vector_indexes";
1866
+ var VECTOR_QUERY_PAGE_SIZE = 256;
1819
1867
  var ConvexVector = class extends vector.MastraVector {
1820
1868
  client;
1821
1869
  constructor(config) {
@@ -1868,10 +1916,7 @@ var ConvexVector = class extends vector.MastraVector {
1868
1916
  if (!index) {
1869
1917
  throw new Error(`Index ${indexName} not found`);
1870
1918
  }
1871
- const vectors = await this.callStorage({
1872
- op: "queryTable",
1873
- tableName: this.vectorTable(indexName)
1874
- });
1919
+ const vectors = await this.queryAllVectors(indexName);
1875
1920
  return {
1876
1921
  dimension: index.dimension,
1877
1922
  count: vectors.length,
@@ -1908,10 +1953,7 @@ var ConvexVector = class extends vector.MastraVector {
1908
1953
  details: { indexName }
1909
1954
  });
1910
1955
  }
1911
- const vectors = await this.callStorage({
1912
- op: "queryTable",
1913
- tableName: this.vectorTable(indexName)
1914
- });
1956
+ const vectors = await this.queryAllVectors(indexName);
1915
1957
  const filtered = filter && !this.isEmptyFilter(filter) ? vectors.filter((record) => this.matchesFilter(record.metadata, filter)) : vectors;
1916
1958
  const scored = filtered.map((record) => ({
1917
1959
  id: record.id,
@@ -1932,10 +1974,7 @@ var ConvexVector = class extends vector.MastraVector {
1932
1974
  if (this.isEmptyFilter(filter)) {
1933
1975
  throw new Error("ConvexVector.updateVector: cannot update with empty filter");
1934
1976
  }
1935
- const vectors = await this.callStorage({
1936
- op: "queryTable",
1937
- tableName: this.vectorTable(params.indexName)
1938
- });
1977
+ const vectors = await this.queryAllVectors(params.indexName);
1939
1978
  const matching = vectors.filter((record) => this.matchesFilter(record.metadata, filter));
1940
1979
  for (const existing2 of matching) {
1941
1980
  const updated2 = {
@@ -2004,10 +2043,7 @@ var ConvexVector = class extends vector.MastraVector {
2004
2043
  if (this.isEmptyFilter(filter)) {
2005
2044
  throw new Error("ConvexVector.deleteVectors: cannot delete with empty filter");
2006
2045
  }
2007
- const vectors = await this.callStorage({
2008
- op: "queryTable",
2009
- tableName: this.vectorTable(indexName)
2010
- });
2046
+ const vectors = await this.queryAllVectors(indexName);
2011
2047
  const matchingIds = vectors.filter((record) => this.matchesFilter(record.metadata, filter)).map((record) => record.id);
2012
2048
  if (matchingIds.length > 0) {
2013
2049
  await this.callStorage({
@@ -2095,6 +2131,27 @@ var ConvexVector = class extends vector.MastraVector {
2095
2131
  async callStorage(request) {
2096
2132
  return this.client.callStorage(request);
2097
2133
  }
2134
+ async queryAllVectors(indexName) {
2135
+ const vectors = [];
2136
+ let cursor = null;
2137
+ let hasMore = true;
2138
+ while (hasMore) {
2139
+ const response = await this.client.callStorageRaw({
2140
+ op: "queryTable",
2141
+ tableName: this.vectorTable(indexName),
2142
+ pageSize: VECTOR_QUERY_PAGE_SIZE,
2143
+ cursor
2144
+ });
2145
+ vectors.push(...response.result);
2146
+ const nextCursor = response.continuationCursor ?? null;
2147
+ hasMore = response.hasMore ?? false;
2148
+ if (hasMore && (!nextCursor || nextCursor === cursor)) {
2149
+ throw new Error("ConvexVector: paginated vector query did not return a valid continuation cursor");
2150
+ }
2151
+ cursor = nextCursor;
2152
+ }
2153
+ return vectors;
2154
+ }
2098
2155
  /**
2099
2156
  * Call storage repeatedly until hasMore is false.
2100
2157
  * Use for bulk operations like clearTable that may need multiple batches.
@@ -2372,23 +2429,23 @@ var ConvexNativeVector = class extends vector.MastraVector {
2372
2429
 
2373
2430
  Object.defineProperty(exports, "mastraCache", {
2374
2431
  enumerable: true,
2375
- get: function () { return chunkORSDZTO4_cjs.mastraCache; }
2432
+ get: function () { return chunkZFDTGYKC_cjs.mastraCache; }
2376
2433
  });
2377
2434
  Object.defineProperty(exports, "mastraNativeVectorAction", {
2378
2435
  enumerable: true,
2379
- get: function () { return chunkORSDZTO4_cjs.mastraNativeVectorAction; }
2436
+ get: function () { return chunkZFDTGYKC_cjs.mastraNativeVectorAction; }
2380
2437
  });
2381
2438
  Object.defineProperty(exports, "mastraNativeVectorMutation", {
2382
2439
  enumerable: true,
2383
- get: function () { return chunkORSDZTO4_cjs.mastraNativeVectorMutation; }
2440
+ get: function () { return chunkZFDTGYKC_cjs.mastraNativeVectorMutation; }
2384
2441
  });
2385
2442
  Object.defineProperty(exports, "mastraNativeVectorQuery", {
2386
2443
  enumerable: true,
2387
- get: function () { return chunkORSDZTO4_cjs.mastraNativeVectorQuery; }
2444
+ get: function () { return chunkZFDTGYKC_cjs.mastraNativeVectorQuery; }
2388
2445
  });
2389
2446
  Object.defineProperty(exports, "mastraStorage", {
2390
2447
  enumerable: true,
2391
- get: function () { return chunkORSDZTO4_cjs.mastraStorage; }
2448
+ get: function () { return chunkZFDTGYKC_cjs.mastraStorage; }
2392
2449
  });
2393
2450
  Object.defineProperty(exports, "TABLE_BACKGROUND_TASKS", {
2394
2451
  enumerable: true,