@mastra/convex 1.0.11 → 1.1.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +138 -0
  2. package/README.md +76 -4
  3. package/dist/cache/client.d.ts +21 -0
  4. package/dist/cache/client.d.ts.map +1 -0
  5. package/dist/cache/index.d.ts +35 -0
  6. package/dist/cache/index.d.ts.map +1 -0
  7. package/dist/cache/types.d.ts +46 -0
  8. package/dist/cache/types.d.ts.map +1 -0
  9. package/dist/{chunk-FTVDAP6U.cjs → chunk-CV23JOCS.cjs} +44 -2
  10. package/dist/chunk-CV23JOCS.cjs.map +1 -0
  11. package/dist/chunk-EEELVBWO.cjs +893 -0
  12. package/dist/chunk-EEELVBWO.cjs.map +1 -0
  13. package/dist/chunk-FZDLZ4S3.js +887 -0
  14. package/dist/chunk-FZDLZ4S3.js.map +1 -0
  15. package/dist/{chunk-G5FLGAPE.js → chunk-JPWDG4L3.js} +42 -3
  16. package/dist/chunk-JPWDG4L3.js.map +1 -0
  17. package/dist/docs/SKILL.md +1 -1
  18. package/dist/docs/assets/SOURCE_MAP.json +44 -15
  19. package/dist/docs/references/reference-storage-convex.md +74 -12
  20. package/dist/docs/references/reference-vectors-convex.md +129 -7
  21. package/dist/index.cjs +515 -36
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +471 -23
  26. package/dist/index.js.map +1 -1
  27. package/dist/schema.cjs +29 -17
  28. package/dist/schema.d.ts +76 -0
  29. package/dist/schema.d.ts.map +1 -1
  30. package/dist/schema.js +1 -1
  31. package/dist/server/cache.d.ts +5 -0
  32. package/dist/server/cache.d.ts.map +1 -0
  33. package/dist/server/index.cjs +44 -16
  34. package/dist/server/index.d.ts +3 -1
  35. package/dist/server/index.d.ts.map +1 -1
  36. package/dist/server/index.js +2 -2
  37. package/dist/server/native-vector.d.ts +17 -0
  38. package/dist/server/native-vector.d.ts.map +1 -0
  39. package/dist/storage/client.d.ts +5 -0
  40. package/dist/storage/client.d.ts.map +1 -1
  41. package/dist/vector/native.d.ts +111 -0
  42. package/dist/vector/native.d.ts.map +1 -0
  43. package/package.json +5 -5
  44. package/dist/chunk-C6QDNSBM.cjs +0 -425
  45. package/dist/chunk-C6QDNSBM.cjs.map +0 -1
  46. package/dist/chunk-FTVDAP6U.cjs.map +0 -1
  47. package/dist/chunk-G5FLGAPE.js.map +0 -1
  48. package/dist/chunk-NXNW2MK5.js +0 -423
  49. package/dist/chunk-NXNW2MK5.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ export { ConvexServerCache, ConvexCacheClient, type ConvexServerCacheConfig, type ConvexCacheClientConfig, } from './cache/index.js';
1
2
  export { ConvexStore, type ConvexStoreConfig } from './storage/index.js';
2
3
  export { ConvexVector, type ConvexVectorConfig } from './vector/index.js';
4
+ export { ConvexNativeVector, type ConvexNativeVectorConfig, type ConvexNativeVectorFilter, type ConvexNativeVectorIndexConfig, } from './vector/native.js';
3
5
  export * from './server/index.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACjE,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,GAC7B,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,GACnC,MAAM,iBAAiB,CAAC;AACzB,cAAc,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- export { mastraStorage } from './chunk-NXNW2MK5.js';
2
- export { TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCORERS, TABLE_THREADS, TABLE_WORKFLOW_SNAPSHOT, mastraDocumentsTable, mastraMessagesTable, mastraResourcesTable, mastraScoresTable, mastraThreadsTable, mastraVectorIndexesTable, mastraVectorsTable, mastraWorkflowSnapshotsTable } from './chunk-G5FLGAPE.js';
1
+ export { mastraCache, mastraNativeVectorAction, mastraNativeVectorMutation, mastraNativeVectorQuery, mastraStorage } from './chunk-FZDLZ4S3.js';
2
+ export { TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCORERS, TABLE_THREADS, TABLE_WORKFLOW_SNAPSHOT, defineMastraNativeVectorTable, mastraCacheListItemsTable, mastraCacheTable, mastraDocumentsTable, mastraMessagesTable, mastraResourcesTable, mastraScoresTable, mastraThreadsTable, mastraVectorIndexesTable, mastraVectorsTable, mastraWorkflowSnapshotsTable } from './chunk-JPWDG4L3.js';
3
+ import { MastraServerCache } from '@mastra/core/cache';
3
4
  import { MastraCompositeStore, createVectorErrorId, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, createStorageErrorId, normalizePerPage, calculatePagination, filterByDateRange, safelyParseJSON, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, ScoresStorage, TABLE_SCORERS, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS } from '@mastra/core/storage';
4
5
  import crypto from 'crypto';
5
6
  import { MastraBase } from '@mastra/core/base';
@@ -7,6 +8,186 @@ import { MessageList } from '@mastra/core/agent';
7
8
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
8
9
  import { MastraVector } from '@mastra/core/vector';
9
10
 
11
+ // src/cache/client.ts
12
+ var DEFAULT_CACHE_FUNCTION = "mastra/cache:handle";
13
+ var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
14
+ var trimTrailingSlashes = (value) => {
15
+ let end = value.length;
16
+ while (end > 0 && value.charCodeAt(end - 1) === 47) {
17
+ end -= 1;
18
+ }
19
+ return value.slice(0, end);
20
+ };
21
+ var ConvexCacheClient = class {
22
+ deploymentUrl;
23
+ adminAuthToken;
24
+ cacheFunction;
25
+ requestTimeoutMs;
26
+ constructor({ deploymentUrl, adminAuthToken, cacheFunction, requestTimeoutMs }) {
27
+ const normalizedDeploymentUrl = deploymentUrl.trim();
28
+ const normalizedAdminAuthToken = adminAuthToken.trim();
29
+ const normalizedCacheFunction = cacheFunction?.trim();
30
+ if (!normalizedDeploymentUrl) {
31
+ throw new Error("ConvexCacheClient: deploymentUrl is required.");
32
+ }
33
+ if (!normalizedAdminAuthToken) {
34
+ throw new Error("ConvexCacheClient: adminAuthToken is required.");
35
+ }
36
+ if (requestTimeoutMs !== void 0 && requestTimeoutMs < 0) {
37
+ throw new Error("ConvexCacheClient: requestTimeoutMs must be greater than or equal to 0.");
38
+ }
39
+ this.deploymentUrl = trimTrailingSlashes(normalizedDeploymentUrl);
40
+ this.adminAuthToken = normalizedAdminAuthToken;
41
+ this.cacheFunction = normalizedCacheFunction || DEFAULT_CACHE_FUNCTION;
42
+ this.requestTimeoutMs = requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
43
+ }
44
+ async callCacheRaw(request) {
45
+ const controller = this.requestTimeoutMs > 0 ? new AbortController() : void 0;
46
+ const timeoutId = controller ? setTimeout(() => controller.abort(), this.requestTimeoutMs) : void 0;
47
+ let response;
48
+ try {
49
+ response = await fetch(`${this.deploymentUrl}/api/mutation`, {
50
+ method: "POST",
51
+ headers: {
52
+ "Content-Type": "application/json",
53
+ Authorization: `Convex ${this.adminAuthToken}`
54
+ },
55
+ body: JSON.stringify({
56
+ path: this.cacheFunction,
57
+ args: request,
58
+ format: "json"
59
+ }),
60
+ signal: controller?.signal
61
+ });
62
+ } catch (error) {
63
+ if (controller?.signal.aborted) {
64
+ throw new Error(`Convex cache request timed out after ${this.requestTimeoutMs} ms.`);
65
+ }
66
+ throw error;
67
+ } finally {
68
+ if (timeoutId) clearTimeout(timeoutId);
69
+ }
70
+ if (!response.ok) {
71
+ const text = await response.text();
72
+ throw new Error(`Convex API error: ${response.status} ${text}`);
73
+ }
74
+ const result = await response.json();
75
+ if (result.status === "error") {
76
+ const error = new Error(result.errorMessage || "Unknown Convex error");
77
+ error.code = result.errorCode ?? result.code;
78
+ error.details = result.details;
79
+ throw error;
80
+ }
81
+ const cacheResponse = result.value;
82
+ if (!cacheResponse?.ok) {
83
+ const errResponse = cacheResponse;
84
+ const error = new Error(errResponse?.error || "Unknown Convex cache error");
85
+ error.code = errResponse?.code;
86
+ error.details = errResponse?.details;
87
+ throw error;
88
+ }
89
+ return {
90
+ result: cacheResponse.result,
91
+ hasMore: cacheResponse.hasMore
92
+ };
93
+ }
94
+ async callCache(request) {
95
+ const { result } = await this.callCacheRaw(request);
96
+ return result;
97
+ }
98
+ };
99
+
100
+ // src/cache/index.ts
101
+ var DEFAULT_KEY_PREFIX = "mastra:cache:";
102
+ var DEFAULT_TTL_MS = 3e5;
103
+ var MAX_CACHE_OPERATION_BATCHES = 1e3;
104
+ var isClientConfig = (config) => "client" in config;
105
+ var ConvexServerCache = class extends MastraServerCache {
106
+ client;
107
+ keyPrefix;
108
+ ttlMs;
109
+ constructor(config) {
110
+ super({ name: "ConvexServerCache" });
111
+ this.client = isClientConfig(config) ? config.client : new ConvexCacheClient(config);
112
+ this.keyPrefix = config.keyPrefix ?? DEFAULT_KEY_PREFIX;
113
+ this.ttlMs = config.ttlMs ?? DEFAULT_TTL_MS;
114
+ }
115
+ getKey(key) {
116
+ return `${this.keyPrefix}${key}`;
117
+ }
118
+ getExpiresAt(ttlMs) {
119
+ const effectiveTtlMs = ttlMs ?? this.ttlMs;
120
+ return effectiveTtlMs > 0 ? Date.now() + effectiveTtlMs : null;
121
+ }
122
+ async callUntilSettled(request) {
123
+ for (let batch = 0; batch < MAX_CACHE_OPERATION_BATCHES; batch += 1) {
124
+ const response = await this.client.callCacheRaw({
125
+ ...request()
126
+ });
127
+ if (!response.hasMore) return response.result;
128
+ }
129
+ throw new Error(`ConvexServerCache operation exceeded ${MAX_CACHE_OPERATION_BATCHES} batches.`);
130
+ }
131
+ async get(key) {
132
+ return this.callUntilSettled(() => ({
133
+ op: "get",
134
+ key: this.getKey(key)
135
+ }));
136
+ }
137
+ async set(key, value, ttlMs) {
138
+ await this.callUntilSettled(() => ({
139
+ op: "set",
140
+ key: this.getKey(key),
141
+ keyPrefix: this.keyPrefix,
142
+ value,
143
+ expiresAt: this.getExpiresAt(ttlMs)
144
+ }));
145
+ }
146
+ async listLength(key) {
147
+ return this.callUntilSettled(() => ({
148
+ op: "listLength",
149
+ key: this.getKey(key)
150
+ }));
151
+ }
152
+ async listPush(key, value) {
153
+ await this.callUntilSettled(() => ({
154
+ op: "listPush",
155
+ key: this.getKey(key),
156
+ keyPrefix: this.keyPrefix,
157
+ value,
158
+ expiresAt: this.getExpiresAt()
159
+ }));
160
+ }
161
+ async listFromTo(key, from, to = -1) {
162
+ return this.callUntilSettled(() => ({
163
+ op: "listFromTo",
164
+ key: this.getKey(key),
165
+ from,
166
+ to
167
+ }));
168
+ }
169
+ async delete(key) {
170
+ await this.callUntilSettled(() => ({
171
+ op: "delete",
172
+ key: this.getKey(key)
173
+ }));
174
+ }
175
+ async clear() {
176
+ await this.callUntilSettled(() => ({
177
+ op: "clear",
178
+ keyPrefix: this.keyPrefix
179
+ }));
180
+ }
181
+ async increment(key) {
182
+ return this.callUntilSettled(() => ({
183
+ op: "increment",
184
+ key: this.getKey(key),
185
+ keyPrefix: this.keyPrefix,
186
+ expiresAt: this.getExpiresAt()
187
+ }));
188
+ }
189
+ };
190
+
10
191
  // src/storage/client.ts
11
192
  var DEFAULT_STORAGE_FUNCTION = "mastra/storage:handle";
12
193
  var ConvexAdminClient = class {
@@ -29,7 +210,39 @@ var ConvexAdminClient = class {
29
210
  * Use this for operations that may need multiple calls (e.g., clearTable).
30
211
  */
31
212
  async callStorageRaw(request) {
32
- const url = `${this.deploymentUrl}/api/mutation`;
213
+ const result = await this.callConvexFunction("mutation", this.storageFunction, request);
214
+ const storageResponse = result.value;
215
+ if (!storageResponse?.ok) {
216
+ const errResponse = storageResponse;
217
+ const error = new Error(errResponse?.error || "Unknown Convex storage error");
218
+ error.code = errResponse?.code;
219
+ error.details = errResponse?.details;
220
+ throw error;
221
+ }
222
+ return {
223
+ result: storageResponse.result,
224
+ hasMore: storageResponse.hasMore
225
+ };
226
+ }
227
+ async callStorage(request) {
228
+ const { result } = await this.callStorageRaw(request);
229
+ return result;
230
+ }
231
+ async callAction(path, args) {
232
+ return this.callFunction("action", path, args);
233
+ }
234
+ async callMutation(path, args) {
235
+ return this.callFunction("mutation", path, args);
236
+ }
237
+ async callQuery(path, args) {
238
+ return this.callFunction("query", path, args);
239
+ }
240
+ async callFunction(kind, path, args) {
241
+ const result = await this.callConvexFunction(kind, path, args);
242
+ return result.value;
243
+ }
244
+ async callConvexFunction(kind, path, args) {
245
+ const url = `${this.deploymentUrl}/api/${kind}`;
33
246
  const response = await fetch(url, {
34
247
  method: "POST",
35
248
  headers: {
@@ -37,8 +250,8 @@ var ConvexAdminClient = class {
37
250
  Authorization: `Convex ${this.adminAuthToken}`
38
251
  },
39
252
  body: JSON.stringify({
40
- path: this.storageFunction,
41
- args: request,
253
+ path,
254
+ args,
42
255
  format: "json"
43
256
  })
44
257
  });
@@ -49,24 +262,15 @@ var ConvexAdminClient = class {
49
262
  const result = await response.json();
50
263
  if (result.status === "error") {
51
264
  const error = new Error(result.errorMessage || "Unknown Convex error");
52
- error.code = result.errorCode;
265
+ error.details = result.errorData;
53
266
  throw error;
54
267
  }
55
- const storageResponse = result.value;
56
- if (!storageResponse?.ok) {
57
- const errResponse = storageResponse;
58
- const error = new Error(errResponse?.error || "Unknown Convex storage error");
59
- error.code = errResponse?.code;
60
- error.details = errResponse?.details;
61
- throw error;
268
+ if (result.status !== "success") {
269
+ throw new Error(`Convex ${kind} ${path} returned an invalid response`);
270
+ }
271
+ if (result.value === void 0) {
272
+ throw new Error(`Convex ${kind} ${path} returned no value`);
62
273
  }
63
- return {
64
- result: storageResponse.result,
65
- hasMore: storageResponse.hasMore
66
- };
67
- }
68
- async callStorage(request) {
69
- const { result } = await this.callStorageRaw(request);
70
274
  return result;
71
275
  }
72
276
  };
@@ -81,6 +285,7 @@ var ConvexDB = class extends MastraBase {
81
285
  super({ name: "convex-db" });
82
286
  this.client = client;
83
287
  }
288
+ client;
84
289
  async hasColumn(_table, _column) {
85
290
  return true;
86
291
  }
@@ -1060,13 +1265,13 @@ var WorkflowsConvex = class extends WorkflowsStorage {
1060
1265
  };
1061
1266
 
1062
1267
  // src/storage/index.ts
1063
- var isClientConfig = (config) => {
1268
+ var isClientConfig2 = (config) => {
1064
1269
  return "client" in config;
1065
1270
  };
1066
1271
  var ConvexStore = class extends MastraCompositeStore {
1067
1272
  constructor(config) {
1068
1273
  super({ id: config.id, name: config.name ?? "ConvexStore", disableInit: config.disableInit });
1069
- const client = isClientConfig(config) ? config.client : new ConvexAdminClient(config);
1274
+ const client = isClientConfig2(config) ? config.client : new ConvexAdminClient(config);
1070
1275
  const domainConfig = { client };
1071
1276
  const memory = new MemoryConvex(domainConfig);
1072
1277
  const workflows = new WorkflowsConvex(domainConfig);
@@ -1390,7 +1595,250 @@ function cosineSimilarity(a, b) {
1390
1595
  }
1391
1596
  return dot / (Math.sqrt(magA) * Math.sqrt(magB));
1392
1597
  }
1598
+ var DEFAULT_VECTOR_INDEX = "by_embedding";
1599
+ var DEFAULT_ID_FIELD = "id";
1600
+ var DEFAULT_ID_INDEX = "by_record_id";
1601
+ var DEFAULT_VECTOR_FIELD = "embedding";
1602
+ var DEFAULT_METADATA_FIELD = "metadata";
1603
+ var DEFAULT_NATIVE_ACTION = "mastra/nativeVector:query";
1604
+ var DEFAULT_NATIVE_QUERY = "mastra/nativeVector:read";
1605
+ var DEFAULT_NATIVE_MUTATION = "mastra/nativeVector:write";
1606
+ var MAX_CONVEX_VECTOR_RESULTS = 256;
1607
+ var NATIVE_VECTOR_UPSERT_BATCH_SIZE = 100;
1608
+ function isMetadataRecord(value) {
1609
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1610
+ }
1611
+ var ConvexNativeVector = class extends MastraVector {
1612
+ client;
1613
+ indexes;
1614
+ nativeVectorAction;
1615
+ nativeVectorQuery;
1616
+ nativeVectorMutation;
1617
+ describeCountLimit;
1618
+ constructor(config) {
1619
+ super({ id: config.id });
1620
+ this.client = new ConvexAdminClient(config);
1621
+ this.indexes = Object.fromEntries(
1622
+ Object.entries(config.indexes).map(([indexName, index]) => [
1623
+ indexName,
1624
+ {
1625
+ tableName: index.tableName,
1626
+ vectorIndexName: index.vectorIndexName ?? DEFAULT_VECTOR_INDEX,
1627
+ dimension: index.dimension,
1628
+ idField: index.idField ?? DEFAULT_ID_FIELD,
1629
+ idIndexName: index.idIndexName ?? DEFAULT_ID_INDEX,
1630
+ vectorField: index.vectorField ?? DEFAULT_VECTOR_FIELD,
1631
+ metadataField: index.metadataField ?? DEFAULT_METADATA_FIELD,
1632
+ filterFields: index.filterFields ?? []
1633
+ }
1634
+ ])
1635
+ );
1636
+ this.nativeVectorAction = config.nativeVectorAction ?? DEFAULT_NATIVE_ACTION;
1637
+ this.nativeVectorQuery = config.nativeVectorQuery ?? DEFAULT_NATIVE_QUERY;
1638
+ this.nativeVectorMutation = config.nativeVectorMutation ?? DEFAULT_NATIVE_MUTATION;
1639
+ this.describeCountLimit = config.describeCountLimit ?? 1e4;
1640
+ }
1641
+ async createIndex({ indexName, dimension, metric = "cosine" }) {
1642
+ const index = this.getIndex(indexName);
1643
+ if (index.dimension !== dimension) {
1644
+ throw new Error(
1645
+ `ConvexNativeVector.createIndex: deployed Convex index "${indexName}" has ${index.dimension} dimensions, but ${dimension} were requested`
1646
+ );
1647
+ }
1648
+ if (metric !== "cosine") {
1649
+ throw new Error("ConvexNativeVector.createIndex: Convex native vector search currently supports cosine only");
1650
+ }
1651
+ }
1652
+ async listIndexes() {
1653
+ return Object.keys(this.indexes);
1654
+ }
1655
+ async describeIndex({ indexName }) {
1656
+ const index = this.getIndex(indexName);
1657
+ const result = await this.client.callQuery(this.nativeVectorQuery, {
1658
+ op: "describe",
1659
+ config: index,
1660
+ countLimit: this.describeCountLimit
1661
+ });
1662
+ if (result.countIsLimited) {
1663
+ this.logger.warn(
1664
+ `ConvexNativeVector.describeIndex: count for "${indexName}" reached ${this.describeCountLimit}; reported count is capped.`
1665
+ );
1666
+ }
1667
+ return {
1668
+ dimension: index.dimension,
1669
+ count: result.count,
1670
+ metric: "cosine"
1671
+ };
1672
+ }
1673
+ async upsert({ indexName, vectors, ids, metadata, deleteFilter }) {
1674
+ if (deleteFilter) {
1675
+ throw new Error("ConvexNativeVector.upsert: deleteFilter is not supported. Delete by IDs before upserting.");
1676
+ }
1677
+ const index = this.getIndex(indexName);
1678
+ if (ids && ids.length !== vectors.length) {
1679
+ throw new Error(
1680
+ `ConvexNativeVector.upsert: ids length (${ids.length}) must match vectors length (${vectors.length})`
1681
+ );
1682
+ }
1683
+ if (metadata && metadata.length !== vectors.length) {
1684
+ throw new Error(
1685
+ `ConvexNativeVector.upsert: metadata length (${metadata.length}) must match vectors length (${vectors.length})`
1686
+ );
1687
+ }
1688
+ if (metadata && !metadata.every(isMetadataRecord)) {
1689
+ throw new Error("ConvexNativeVector.upsert: metadata entries must be objects when provided");
1690
+ }
1691
+ const vectorIds = ids ?? vectors.map(() => crypto.randomUUID());
1692
+ if (new Set(vectorIds).size !== vectorIds.length) {
1693
+ throw new Error("ConvexNativeVector.upsert: ids must be unique");
1694
+ }
1695
+ for (let start = 0; start < vectors.length; start += NATIVE_VECTOR_UPSERT_BATCH_SIZE) {
1696
+ const end = start + NATIVE_VECTOR_UPSERT_BATCH_SIZE;
1697
+ await this.client.callMutation(this.nativeVectorMutation, {
1698
+ op: "upsert",
1699
+ config: index,
1700
+ ids: vectorIds.slice(start, end),
1701
+ vectors: vectors.slice(start, end),
1702
+ ...metadata ? { metadata: metadata.slice(start, end) } : {}
1703
+ });
1704
+ }
1705
+ return vectorIds;
1706
+ }
1707
+ async query({
1708
+ indexName,
1709
+ queryVector,
1710
+ topK = 10,
1711
+ includeVector = false,
1712
+ filter
1713
+ }) {
1714
+ if (!queryVector) {
1715
+ throw new MastraError({
1716
+ id: createVectorErrorId("CONVEX_NATIVE", "QUERY", "MISSING_VECTOR"),
1717
+ text: "queryVector is required for Convex native vector queries.",
1718
+ domain: ErrorDomain.STORAGE,
1719
+ category: ErrorCategory.USER,
1720
+ details: { indexName }
1721
+ });
1722
+ }
1723
+ if (!Number.isFinite(topK) || !Number.isInteger(topK) || topK < 1 || topK > MAX_CONVEX_VECTOR_RESULTS) {
1724
+ throw new Error(`ConvexNativeVector.query: topK must be an integer between 1 and ${MAX_CONVEX_VECTOR_RESULTS}`);
1725
+ }
1726
+ const index = this.getIndex(indexName);
1727
+ const nativeFilter = this.toNativeFilter(filter, index);
1728
+ const searchResults = await this.client.callAction(this.nativeVectorAction, {
1729
+ config: index,
1730
+ vector: queryVector,
1731
+ limit: topK,
1732
+ ...nativeFilter ? { filter: nativeFilter } : {}
1733
+ });
1734
+ if (searchResults.length === 0) return [];
1735
+ const docs = await this.client.callQuery(this.nativeVectorQuery, {
1736
+ op: "getByConvexIds",
1737
+ config: index,
1738
+ ids: searchResults.map((result) => result.id),
1739
+ includeVector
1740
+ });
1741
+ const scoresByConvexId = new Map(searchResults.map((result) => [result.id, result.score]));
1742
+ return docs.flatMap((doc) => {
1743
+ if (!doc?._id) return [];
1744
+ return [
1745
+ {
1746
+ id: String(doc[index.idField]),
1747
+ score: scoresByConvexId.get(String(doc._id)) ?? 0,
1748
+ metadata: doc[index.metadataField],
1749
+ ...includeVector ? { vector: doc[index.vectorField] } : {}
1750
+ }
1751
+ ];
1752
+ });
1753
+ }
1754
+ async updateVector(params) {
1755
+ if ("filter" in params && params.filter !== void 0) {
1756
+ throw new Error("ConvexNativeVector.updateVector: filter-based updates are not supported. Update by ID instead.");
1757
+ }
1758
+ if (params.update.metadata !== void 0 && !isMetadataRecord(params.update.metadata)) {
1759
+ throw new Error("ConvexNativeVector.updateVector: metadata must be an object when provided");
1760
+ }
1761
+ const index = this.getIndex(params.indexName);
1762
+ await this.client.callMutation(this.nativeVectorMutation, {
1763
+ op: "updateById",
1764
+ config: index,
1765
+ id: params.id,
1766
+ vector: params.update.vector,
1767
+ metadata: params.update.metadata
1768
+ });
1769
+ }
1770
+ async deleteVector({ indexName, id }) {
1771
+ const index = this.getIndex(indexName);
1772
+ await this.client.callMutation(this.nativeVectorMutation, {
1773
+ op: "deleteByIds",
1774
+ config: index,
1775
+ ids: [id]
1776
+ });
1777
+ }
1778
+ async deleteVectors(params) {
1779
+ if (params.filter !== void 0) {
1780
+ throw new Error(
1781
+ "ConvexNativeVector.deleteVectors: filter-based deletes are not supported. Delete by IDs instead."
1782
+ );
1783
+ }
1784
+ if (!params.ids || params.ids.length === 0) {
1785
+ throw new Error("ConvexNativeVector.deleteVectors: ids are required");
1786
+ }
1787
+ const index = this.getIndex(params.indexName);
1788
+ await this.client.callMutation(this.nativeVectorMutation, {
1789
+ op: "deleteByIds",
1790
+ config: index,
1791
+ ids: params.ids
1792
+ });
1793
+ }
1794
+ async deleteIndex({ indexName }) {
1795
+ this.getIndex(indexName);
1796
+ throw new Error("ConvexNativeVector.deleteIndex: Convex native vector indexes are managed in convex/schema.ts.");
1797
+ }
1798
+ getIndex(indexName) {
1799
+ const index = this.indexes[indexName];
1800
+ if (!index) {
1801
+ throw new Error(`ConvexNativeVector: index "${indexName}" is not configured`);
1802
+ }
1803
+ return index;
1804
+ }
1805
+ toNativeFilter(filter, index) {
1806
+ if (!filter || Object.keys(filter).length === 0) return void 0;
1807
+ if (this.isOrFilter(filter)) {
1808
+ const clauses = filter.$or.map((branch) => this.toSingleClause(branch, index));
1809
+ return { $or: clauses };
1810
+ }
1811
+ const fieldFilter = this.isMetadataFilter(filter) ? filter.metadata : filter;
1812
+ return this.toSingleClause(fieldFilter, index);
1813
+ }
1814
+ toSingleClause(filter, index) {
1815
+ const entries = Object.entries(filter).filter(([, value2]) => value2 !== void 0);
1816
+ if (entries.length !== 1) {
1817
+ throw new Error(
1818
+ "ConvexNativeVector.query: native Convex filters support one equality field or $or of equality fields"
1819
+ );
1820
+ }
1821
+ const [field, rawValue] = entries[0];
1822
+ if (!index.filterFields.includes(field)) {
1823
+ throw new Error(`ConvexNativeVector.query: field "${field}" is not configured as a Convex vector filter field`);
1824
+ }
1825
+ const value = typeof rawValue === "object" && rawValue !== null && "$eq" in rawValue ? rawValue.$eq : rawValue;
1826
+ if (!["string", "number", "boolean"].includes(typeof value) && value !== null) {
1827
+ throw new Error(
1828
+ "ConvexNativeVector.query: native Convex filters support string, number, boolean, and null values"
1829
+ );
1830
+ }
1831
+ return { field, value };
1832
+ }
1833
+ isOrFilter(filter) {
1834
+ return Array.isArray(filter.$or);
1835
+ }
1836
+ isMetadataFilter(filter) {
1837
+ const metadata = filter.metadata;
1838
+ return typeof metadata === "object" && metadata !== null && !Array.isArray(metadata);
1839
+ }
1840
+ };
1393
1841
 
1394
- export { ConvexStore, ConvexVector };
1842
+ export { ConvexCacheClient, ConvexNativeVector, ConvexServerCache, ConvexStore, ConvexVector };
1395
1843
  //# sourceMappingURL=index.js.map
1396
1844
  //# sourceMappingURL=index.js.map