@mastra/upstash 1.0.0-beta.0 → 1.0.0-beta.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
@@ -498,13 +498,11 @@ var StoreMemoryUpstash = class extends MemoryStorage {
498
498
  }
499
499
  return 0;
500
500
  };
501
- if (orderBy) {
502
- messagesData.sort((a, b) => {
503
- const aValue = getFieldValue(a);
504
- const bValue = getFieldValue(b);
505
- return direction === "ASC" ? aValue - bValue : bValue - aValue;
506
- });
507
- }
501
+ messagesData.sort((a, b) => {
502
+ const aValue = getFieldValue(a);
503
+ const bValue = getFieldValue(b);
504
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
505
+ });
508
506
  const total = messagesData.length;
509
507
  const start = offset;
510
508
  const end = perPageInput === false ? total : start + perPage;
@@ -525,23 +523,11 @@ var StoreMemoryUpstash = class extends MemoryStorage {
525
523
  }
526
524
  const list = new MessageList().add(allMessages, "memory");
527
525
  let finalMessages = list.get.all.db();
528
- if (orderBy) {
529
- finalMessages = finalMessages.sort((a, b) => {
530
- const aValue = getFieldValue(a);
531
- const bValue = getFieldValue(b);
532
- return direction === "ASC" ? aValue - bValue : bValue - aValue;
533
- });
534
- } else {
535
- const messageIdToPosition = /* @__PURE__ */ new Map();
536
- allMessageIds.forEach((id, index) => {
537
- messageIdToPosition.set(id, index);
538
- });
539
- finalMessages = finalMessages.sort((a, b) => {
540
- const aPos = messageIdToPosition.get(a.id) ?? Number.MAX_SAFE_INTEGER;
541
- const bPos = messageIdToPosition.get(b.id) ?? Number.MAX_SAFE_INTEGER;
542
- return aPos - bPos;
543
- });
544
- }
526
+ finalMessages = finalMessages.sort((a, b) => {
527
+ const aValue = getFieldValue(a);
528
+ const bValue = getFieldValue(b);
529
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
530
+ });
545
531
  const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
546
532
  const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
547
533
  const hasMore = perPageInput !== false && !allThreadMessagesReturned && end < total;
@@ -1009,7 +995,9 @@ var ScoresUpstash = class extends ScoresStorage {
1009
995
  id: "STORAGE_UPSTASH_STORAGE_GET_SCORE_BY_ID_FAILED",
1010
996
  domain: ErrorDomain.STORAGE,
1011
997
  category: ErrorCategory.THIRD_PARTY,
1012
- details: { id }
998
+ details: {
999
+ ...id && { id }
1000
+ }
1013
1001
  },
1014
1002
  error
1015
1003
  );
@@ -1378,7 +1366,8 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
1378
1366
  toDate,
1379
1367
  perPage,
1380
1368
  page,
1381
- resourceId
1369
+ resourceId,
1370
+ status
1382
1371
  }) {
1383
1372
  try {
1384
1373
  if (page !== void 0 && page < 0) {
@@ -1422,6 +1411,18 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
1422
1411
  ).filter((record) => !workflowName || record.workflow_name === workflowName).map((w) => parseWorkflowRun(w)).filter((w) => {
1423
1412
  if (fromDate && w.createdAt < fromDate) return false;
1424
1413
  if (toDate && w.createdAt > toDate) return false;
1414
+ if (status) {
1415
+ let snapshot = w.snapshot;
1416
+ if (typeof snapshot === "string") {
1417
+ try {
1418
+ snapshot = JSON.parse(snapshot);
1419
+ } catch (e) {
1420
+ console.warn(`Failed to parse snapshot for workflow ${w.workflowName}: ${e}`);
1421
+ return false;
1422
+ }
1423
+ }
1424
+ return snapshot.status === status;
1425
+ }
1425
1426
  return true;
1426
1427
  }).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
1427
1428
  const total = runs.length;
@@ -1554,15 +1555,8 @@ var UpstashStore = class extends MastraStorage {
1554
1555
  async loadWorkflowSnapshot(params) {
1555
1556
  return this.stores.workflows.loadWorkflowSnapshot(params);
1556
1557
  }
1557
- async listWorkflowRuns({
1558
- workflowName,
1559
- fromDate,
1560
- toDate,
1561
- perPage,
1562
- page,
1563
- resourceId
1564
- } = {}) {
1565
- return this.stores.workflows.listWorkflowRuns({ workflowName, fromDate, toDate, perPage, page, resourceId });
1558
+ async listWorkflowRuns(args = {}) {
1559
+ return this.stores.workflows.listWorkflowRuns(args);
1566
1560
  }
1567
1561
  async getWorkflowRunById({
1568
1562
  runId,
@@ -1993,6 +1987,11 @@ var UpstashVector = class extends MastraVector {
1993
1987
  try {
1994
1988
  await this.client.deleteNamespace(namespace);
1995
1989
  } catch (error) {
1990
+ const errorMessage = error?.message || "";
1991
+ if (errorMessage.includes("does not exist") || errorMessage.includes("not found")) {
1992
+ this.logger.info(`Namespace ${namespace} does not exist, treating as already deleted`);
1993
+ return;
1994
+ }
1996
1995
  throw new MastraError(
1997
1996
  {
1998
1997
  id: "STORAGE_UPSTASH_VECTOR_DELETE_INDEX_FAILED",
@@ -2005,47 +2004,124 @@ var UpstashVector = class extends MastraVector {
2005
2004
  }
2006
2005
  }
2007
2006
  /**
2008
- * Updates a vector by its ID with the provided vector and/or metadata.
2009
- * @param indexName - The name of the namespace containing the vector.
2010
- * @param id - The ID of the vector to update.
2011
- * @param update - An object containing the vector and/or metadata to update.
2012
- * @param update.vector - An optional array of numbers representing the new vector.
2013
- * @param update.metadata - An optional record containing the new metadata.
2007
+ * Updates a vector by its ID or multiple vectors matching a filter.
2008
+ * @param params - Parameters containing the id or filter for targeting the vector(s) to update
2009
+ * @param params.indexName - The name of the namespace containing the vector.
2010
+ * @param params.id - The ID of the vector to update (mutually exclusive with filter).
2011
+ * @param params.filter - Filter to match multiple vectors to update (mutually exclusive with id).
2012
+ * @param params.update - An object containing the vector and/or metadata to update.
2014
2013
  * @returns A promise that resolves when the update is complete.
2015
2014
  * @throws Will throw an error if no updates are provided or if the update operation fails.
2016
2015
  */
2017
- async updateVector({ indexName: namespace, id, update }) {
2018
- if (!update.vector && !update.metadata && !update.sparseVector) {
2016
+ async updateVector(params) {
2017
+ const { indexName: namespace, update } = params;
2018
+ const upstashUpdate = update;
2019
+ const sparseVector = upstashUpdate.sparseVector;
2020
+ if ("id" in params && params.id && "filter" in params && params.filter) {
2021
+ throw new MastraError({
2022
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_MUTUALLY_EXCLUSIVE",
2023
+ text: "Cannot specify both id and filter - they are mutually exclusive",
2024
+ domain: ErrorDomain.STORAGE,
2025
+ category: ErrorCategory.USER,
2026
+ details: { namespace }
2027
+ });
2028
+ }
2029
+ if (!("id" in params && params.id) && !("filter" in params && params.filter)) {
2019
2030
  throw new MastraError({
2020
- id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
2031
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_NO_TARGET",
2032
+ text: "Either id or filter must be provided",
2021
2033
  domain: ErrorDomain.STORAGE,
2022
- category: ErrorCategory.THIRD_PARTY,
2023
- details: { namespace, id },
2024
- text: "No update data provided"
2034
+ category: ErrorCategory.USER,
2035
+ details: { namespace }
2025
2036
  });
2026
2037
  }
2027
- if (!update.vector && !update.sparseVector && update.metadata) {
2038
+ if (!update.vector && !update.metadata && !sparseVector) {
2028
2039
  throw new MastraError({
2029
- id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
2040
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_NO_PAYLOAD",
2041
+ text: "No update data provided",
2030
2042
  domain: ErrorDomain.STORAGE,
2031
- category: ErrorCategory.THIRD_PARTY,
2032
- details: { namespace, id },
2033
- text: "Both vector and metadata must be provided for an update"
2043
+ category: ErrorCategory.USER,
2044
+ details: { namespace }
2045
+ });
2046
+ }
2047
+ if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
2048
+ throw new MastraError({
2049
+ id: "STORAGE_UPSTASH_VECTOR_UPDATE_EMPTY_FILTER",
2050
+ text: "Filter cannot be an empty filter object",
2051
+ domain: ErrorDomain.STORAGE,
2052
+ category: ErrorCategory.USER,
2053
+ details: { namespace }
2034
2054
  });
2035
2055
  }
2036
2056
  try {
2037
- const points = { id };
2038
- if (update.vector) points.vector = update.vector;
2039
- if (update.metadata) points.metadata = update.metadata;
2040
- if (update.sparseVector) points.sparseVector = update.sparseVector;
2041
- await this.client.upsert(points, { namespace });
2057
+ const ns = this.client.namespace(namespace);
2058
+ if ("id" in params && params.id) {
2059
+ const points = { id: params.id };
2060
+ if (!update.vector || !update.metadata) {
2061
+ try {
2062
+ const existing = await ns.fetch([params.id], {
2063
+ includeVectors: true,
2064
+ includeMetadata: true
2065
+ });
2066
+ if (existing && existing.length > 0 && existing[0]) {
2067
+ if (!update.vector && existing[0]?.vector) {
2068
+ points.vector = existing[0].vector;
2069
+ }
2070
+ if (!update.metadata && existing[0]?.metadata) {
2071
+ points.metadata = existing[0].metadata;
2072
+ }
2073
+ }
2074
+ } catch (fetchError) {
2075
+ this.logger.warn(`Failed to fetch existing vector ${params.id} for partial update: ${fetchError}`);
2076
+ }
2077
+ }
2078
+ if (update.vector) points.vector = update.vector;
2079
+ if (update.metadata) points.metadata = update.metadata;
2080
+ if (sparseVector) points.sparseVector = sparseVector;
2081
+ await ns.upsert(points);
2082
+ } else if ("filter" in params && params.filter) {
2083
+ const filterString = this.transformFilter(params.filter);
2084
+ if (filterString) {
2085
+ const stats = await this.describeIndex({ indexName: namespace });
2086
+ const dummyVector = new Array(stats.dimension).fill(1 / Math.sqrt(stats.dimension));
2087
+ const needsVectors = !update.vector;
2088
+ const results = await ns.query({
2089
+ vector: dummyVector,
2090
+ topK: 1e3,
2091
+ // Upstash's max query limit
2092
+ filter: filterString,
2093
+ includeVectors: needsVectors,
2094
+ includeMetadata: needsVectors
2095
+ });
2096
+ for (const result of results) {
2097
+ const points = { id: `${result.id}` };
2098
+ if (update.vector) {
2099
+ points.vector = update.vector;
2100
+ } else if (result.vector) {
2101
+ points.vector = result.vector;
2102
+ }
2103
+ if (update.metadata) {
2104
+ points.metadata = update.metadata;
2105
+ } else if (result.metadata) {
2106
+ points.metadata = result.metadata;
2107
+ }
2108
+ if (sparseVector) points.sparseVector = sparseVector;
2109
+ await ns.upsert(points);
2110
+ }
2111
+ }
2112
+ }
2042
2113
  } catch (error) {
2114
+ if (error instanceof MastraError) throw error;
2043
2115
  throw new MastraError(
2044
2116
  {
2045
2117
  id: "STORAGE_UPSTASH_VECTOR_UPDATE_VECTOR_FAILED",
2046
2118
  domain: ErrorDomain.STORAGE,
2047
2119
  category: ErrorCategory.THIRD_PARTY,
2048
- details: { namespace, id }
2120
+ details: {
2121
+ namespace,
2122
+ ..."id" in params && params.id && { id: params.id },
2123
+ ..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) }
2124
+ }
2049
2125
  },
2050
2126
  error
2051
2127
  );
@@ -2060,22 +2136,109 @@ var UpstashVector = class extends MastraVector {
2060
2136
  */
2061
2137
  async deleteVector({ indexName: namespace, id }) {
2062
2138
  try {
2063
- await this.client.delete(id, {
2064
- namespace
2065
- });
2139
+ const ns = this.client.namespace(namespace);
2140
+ await ns.delete(id);
2066
2141
  } catch (error) {
2067
2142
  const mastraError = new MastraError(
2068
2143
  {
2069
2144
  id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTOR_FAILED",
2070
2145
  domain: ErrorDomain.STORAGE,
2071
2146
  category: ErrorCategory.THIRD_PARTY,
2072
- details: { namespace, id }
2147
+ details: {
2148
+ namespace,
2149
+ ...id && { id }
2150
+ }
2073
2151
  },
2074
2152
  error
2075
2153
  );
2076
2154
  this.logger?.error(mastraError.toString());
2077
2155
  }
2078
2156
  }
2157
+ /**
2158
+ * Deletes multiple vectors by IDs or filter.
2159
+ * @param indexName - The name of the namespace containing the vectors.
2160
+ * @param ids - Array of vector IDs to delete (mutually exclusive with filter).
2161
+ * @param filter - Filter to match vectors to delete (mutually exclusive with ids).
2162
+ * @returns A promise that resolves when the deletion is complete.
2163
+ * @throws Will throw an error if both ids and filter are provided, or if neither is provided.
2164
+ */
2165
+ async deleteVectors({ indexName: namespace, filter, ids }) {
2166
+ if (ids && filter) {
2167
+ throw new MastraError({
2168
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_MUTUALLY_EXCLUSIVE",
2169
+ text: "Cannot specify both ids and filter - they are mutually exclusive",
2170
+ domain: ErrorDomain.STORAGE,
2171
+ category: ErrorCategory.USER,
2172
+ details: { namespace }
2173
+ });
2174
+ }
2175
+ if (!ids && !filter) {
2176
+ throw new MastraError({
2177
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_NO_TARGET",
2178
+ text: "Either filter or ids must be provided",
2179
+ domain: ErrorDomain.STORAGE,
2180
+ category: ErrorCategory.USER,
2181
+ details: { namespace }
2182
+ });
2183
+ }
2184
+ if (ids && ids.length === 0) {
2185
+ throw new MastraError({
2186
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_EMPTY_IDS",
2187
+ text: "Cannot delete with empty ids array",
2188
+ domain: ErrorDomain.STORAGE,
2189
+ category: ErrorCategory.USER,
2190
+ details: { namespace }
2191
+ });
2192
+ }
2193
+ if (filter && Object.keys(filter).length === 0) {
2194
+ throw new MastraError({
2195
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_EMPTY_FILTER",
2196
+ text: "Cannot delete with empty filter object",
2197
+ domain: ErrorDomain.STORAGE,
2198
+ category: ErrorCategory.USER,
2199
+ details: { namespace }
2200
+ });
2201
+ }
2202
+ try {
2203
+ const ns = this.client.namespace(namespace);
2204
+ if (ids) {
2205
+ await ns.delete(ids);
2206
+ } else if (filter) {
2207
+ const filterString = this.transformFilter(filter);
2208
+ if (filterString) {
2209
+ const stats = await this.describeIndex({ indexName: namespace });
2210
+ const dummyVector = new Array(stats.dimension).fill(1 / Math.sqrt(stats.dimension));
2211
+ const results = await ns.query({
2212
+ vector: dummyVector,
2213
+ topK: 1e3,
2214
+ // Upstash's max query limit
2215
+ filter: filterString,
2216
+ includeVectors: false,
2217
+ includeMetadata: false
2218
+ });
2219
+ const idsToDelete = results.map((r) => `${r.id}`);
2220
+ if (idsToDelete.length > 0) {
2221
+ await ns.delete(idsToDelete);
2222
+ }
2223
+ }
2224
+ }
2225
+ } catch (error) {
2226
+ if (error instanceof MastraError) throw error;
2227
+ throw new MastraError(
2228
+ {
2229
+ id: "STORAGE_UPSTASH_VECTOR_DELETE_VECTORS_FAILED",
2230
+ domain: ErrorDomain.STORAGE,
2231
+ category: ErrorCategory.THIRD_PARTY,
2232
+ details: {
2233
+ namespace,
2234
+ ...filter && { filter: JSON.stringify(filter) },
2235
+ ...ids && { idsCount: ids.length }
2236
+ }
2237
+ },
2238
+ error
2239
+ );
2240
+ }
2241
+ }
2079
2242
  };
2080
2243
 
2081
2244
  // src/vector/prompt.ts