@mastra/upstash 1.0.0-beta.1 → 1.0.0-beta.11
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 +522 -0
- package/README.md +12 -0
- package/dist/docs/README.md +34 -0
- package/dist/docs/SKILL.md +35 -0
- package/dist/docs/SOURCE_MAP.json +6 -0
- package/dist/docs/memory/01-working-memory.md +390 -0
- package/dist/docs/rag/01-vector-databases.md +643 -0
- package/dist/docs/rag/02-retrieval.md +548 -0
- package/dist/docs/storage/01-reference.md +143 -0
- package/dist/docs/vectors/01-reference.md +233 -0
- package/dist/index.cjs +803 -534
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +796 -530
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +47 -0
- package/dist/storage/db/index.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +10 -8
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +6 -9
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/utils.d.ts +0 -2
- package/dist/storage/domains/utils.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +17 -19
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +76 -167
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +18 -9
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/types.d.ts +15 -3
- package/dist/vector/types.d.ts.map +1 -1
- package/package.json +11 -11
- package/dist/storage/domains/operations/index.d.ts +0 -40
- package/dist/storage/domains/operations/index.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, ensureDate, createStorageErrorId, normalizePerPage, calculatePagination, filterByDateRange, ScoresStorage, TABLE_SCORERS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, MastraStorage, createVectorErrorId, serializeDate, transformScoreRow as transformScoreRow$1 } from '@mastra/core/storage';
|
|
2
2
|
import { Redis } from '@upstash/redis';
|
|
3
3
|
import { MessageList } from '@mastra/core/agent';
|
|
4
4
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
@@ -9,13 +9,6 @@ import { Index } from '@upstash/vector';
|
|
|
9
9
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
10
10
|
|
|
11
11
|
// src/storage/index.ts
|
|
12
|
-
function ensureDate(value) {
|
|
13
|
-
if (!value) return null;
|
|
14
|
-
if (value instanceof Date) return value;
|
|
15
|
-
if (typeof value === "string") return new Date(value);
|
|
16
|
-
if (typeof value === "number") return new Date(value);
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
12
|
function getKey(tableName, keys) {
|
|
20
13
|
const keyParts = Object.entries(keys).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}:${value}`);
|
|
21
14
|
return `${tableName}:${keyParts.join(":")}`;
|
|
@@ -32,7 +25,7 @@ function processRecord(tableName, record) {
|
|
|
32
25
|
...record.resourceId ? { resourceId: record.resourceId } : {}
|
|
33
26
|
});
|
|
34
27
|
} else if (tableName === TABLE_SCORERS) {
|
|
35
|
-
key = getKey(tableName, {
|
|
28
|
+
key = getKey(tableName, { id: record.id });
|
|
36
29
|
} else {
|
|
37
30
|
key = getKey(tableName, { id: record.id });
|
|
38
31
|
}
|
|
@@ -44,6 +37,107 @@ function processRecord(tableName, record) {
|
|
|
44
37
|
return { key, processedRecord };
|
|
45
38
|
}
|
|
46
39
|
|
|
40
|
+
// src/storage/db/index.ts
|
|
41
|
+
function resolveUpstashConfig(config) {
|
|
42
|
+
if ("client" in config) {
|
|
43
|
+
return config.client;
|
|
44
|
+
}
|
|
45
|
+
return new Redis({
|
|
46
|
+
url: config.url,
|
|
47
|
+
token: config.token
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
var UpstashDB = class {
|
|
51
|
+
client;
|
|
52
|
+
constructor({ client }) {
|
|
53
|
+
this.client = client;
|
|
54
|
+
}
|
|
55
|
+
async insert({ tableName, record }) {
|
|
56
|
+
const { key, processedRecord } = processRecord(tableName, record);
|
|
57
|
+
try {
|
|
58
|
+
await this.client.set(key, processedRecord);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
throw new MastraError(
|
|
61
|
+
{
|
|
62
|
+
id: createStorageErrorId("UPSTASH", "INSERT", "FAILED"),
|
|
63
|
+
domain: ErrorDomain.STORAGE,
|
|
64
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
65
|
+
details: {
|
|
66
|
+
tableName
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
error
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async get({ tableName, keys }) {
|
|
74
|
+
const key = getKey(tableName, keys);
|
|
75
|
+
try {
|
|
76
|
+
const data = await this.client.get(key);
|
|
77
|
+
return data || null;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
throw new MastraError(
|
|
80
|
+
{
|
|
81
|
+
id: createStorageErrorId("UPSTASH", "LOAD", "FAILED"),
|
|
82
|
+
domain: ErrorDomain.STORAGE,
|
|
83
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
84
|
+
details: {
|
|
85
|
+
tableName
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
error
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async scanAndDelete(pattern, batchSize = 1e4) {
|
|
93
|
+
let cursor = "0";
|
|
94
|
+
let totalDeleted = 0;
|
|
95
|
+
do {
|
|
96
|
+
const [nextCursor, keys] = await this.client.scan(cursor, {
|
|
97
|
+
match: pattern,
|
|
98
|
+
count: batchSize
|
|
99
|
+
});
|
|
100
|
+
if (keys.length > 0) {
|
|
101
|
+
await this.client.del(...keys);
|
|
102
|
+
totalDeleted += keys.length;
|
|
103
|
+
}
|
|
104
|
+
cursor = nextCursor;
|
|
105
|
+
} while (cursor !== "0");
|
|
106
|
+
return totalDeleted;
|
|
107
|
+
}
|
|
108
|
+
async scanKeys(pattern, batchSize = 1e4) {
|
|
109
|
+
let cursor = "0";
|
|
110
|
+
let keys = [];
|
|
111
|
+
do {
|
|
112
|
+
const [nextCursor, batch] = await this.client.scan(cursor, {
|
|
113
|
+
match: pattern,
|
|
114
|
+
count: batchSize
|
|
115
|
+
});
|
|
116
|
+
keys.push(...batch);
|
|
117
|
+
cursor = nextCursor;
|
|
118
|
+
} while (cursor !== "0");
|
|
119
|
+
return keys;
|
|
120
|
+
}
|
|
121
|
+
async deleteData({ tableName }) {
|
|
122
|
+
const pattern = `${tableName}:*`;
|
|
123
|
+
try {
|
|
124
|
+
await this.scanAndDelete(pattern);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
throw new MastraError(
|
|
127
|
+
{
|
|
128
|
+
id: createStorageErrorId("UPSTASH", "CLEAR_TABLE", "FAILED"),
|
|
129
|
+
domain: ErrorDomain.STORAGE,
|
|
130
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
131
|
+
details: {
|
|
132
|
+
tableName
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
error
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
47
141
|
// src/storage/domains/memory/index.ts
|
|
48
142
|
function getThreadMessagesKey(threadId) {
|
|
49
143
|
return `thread:${threadId}:messages`;
|
|
@@ -52,17 +146,26 @@ function getMessageKey(threadId, messageId) {
|
|
|
52
146
|
const key = getKey(TABLE_MESSAGES, { threadId, id: messageId });
|
|
53
147
|
return key;
|
|
54
148
|
}
|
|
149
|
+
function getMessageIndexKey(messageId) {
|
|
150
|
+
return `msg-idx:${messageId}`;
|
|
151
|
+
}
|
|
55
152
|
var StoreMemoryUpstash = class extends MemoryStorage {
|
|
56
153
|
client;
|
|
57
|
-
|
|
58
|
-
constructor(
|
|
154
|
+
#db;
|
|
155
|
+
constructor(config) {
|
|
59
156
|
super();
|
|
157
|
+
const client = resolveUpstashConfig(config);
|
|
60
158
|
this.client = client;
|
|
61
|
-
this
|
|
159
|
+
this.#db = new UpstashDB({ client });
|
|
160
|
+
}
|
|
161
|
+
async dangerouslyClearAll() {
|
|
162
|
+
await this.#db.deleteData({ tableName: TABLE_THREADS });
|
|
163
|
+
await this.#db.deleteData({ tableName: TABLE_MESSAGES });
|
|
164
|
+
await this.#db.deleteData({ tableName: TABLE_RESOURCES });
|
|
62
165
|
}
|
|
63
166
|
async getThreadById({ threadId }) {
|
|
64
167
|
try {
|
|
65
|
-
const thread = await this.
|
|
168
|
+
const thread = await this.#db.get({
|
|
66
169
|
tableName: TABLE_THREADS,
|
|
67
170
|
keys: { id: threadId }
|
|
68
171
|
});
|
|
@@ -76,7 +179,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
76
179
|
} catch (error) {
|
|
77
180
|
throw new MastraError(
|
|
78
181
|
{
|
|
79
|
-
id: "
|
|
182
|
+
id: createStorageErrorId("UPSTASH", "GET_THREAD_BY_ID", "FAILED"),
|
|
80
183
|
domain: ErrorDomain.STORAGE,
|
|
81
184
|
category: ErrorCategory.THIRD_PARTY,
|
|
82
185
|
details: {
|
|
@@ -94,7 +197,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
94
197
|
if (page < 0) {
|
|
95
198
|
throw new MastraError(
|
|
96
199
|
{
|
|
97
|
-
id: "
|
|
200
|
+
id: createStorageErrorId("UPSTASH", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
98
201
|
domain: ErrorDomain.STORAGE,
|
|
99
202
|
category: ErrorCategory.USER,
|
|
100
203
|
details: { page }
|
|
@@ -106,7 +209,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
106
209
|
try {
|
|
107
210
|
let allThreads = [];
|
|
108
211
|
const pattern = `${TABLE_THREADS}:*`;
|
|
109
|
-
const keys = await this.
|
|
212
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
110
213
|
const pipeline = this.client.pipeline();
|
|
111
214
|
keys.forEach((key) => pipeline.get(key));
|
|
112
215
|
const results = await pipeline.exec();
|
|
@@ -136,7 +239,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
136
239
|
} catch (error) {
|
|
137
240
|
const mastraError = new MastraError(
|
|
138
241
|
{
|
|
139
|
-
id: "
|
|
242
|
+
id: createStorageErrorId("UPSTASH", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
|
|
140
243
|
domain: ErrorDomain.STORAGE,
|
|
141
244
|
category: ErrorCategory.THIRD_PARTY,
|
|
142
245
|
details: {
|
|
@@ -160,7 +263,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
160
263
|
}
|
|
161
264
|
async saveThread({ thread }) {
|
|
162
265
|
try {
|
|
163
|
-
await this.
|
|
266
|
+
await this.#db.insert({
|
|
164
267
|
tableName: TABLE_THREADS,
|
|
165
268
|
record: thread
|
|
166
269
|
});
|
|
@@ -168,7 +271,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
168
271
|
} catch (error) {
|
|
169
272
|
const mastraError = new MastraError(
|
|
170
273
|
{
|
|
171
|
-
id: "
|
|
274
|
+
id: createStorageErrorId("UPSTASH", "SAVE_THREAD", "FAILED"),
|
|
172
275
|
domain: ErrorDomain.STORAGE,
|
|
173
276
|
category: ErrorCategory.THIRD_PARTY,
|
|
174
277
|
details: {
|
|
@@ -190,7 +293,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
190
293
|
const thread = await this.getThreadById({ threadId: id });
|
|
191
294
|
if (!thread) {
|
|
192
295
|
throw new MastraError({
|
|
193
|
-
id: "
|
|
296
|
+
id: createStorageErrorId("UPSTASH", "UPDATE_THREAD", "FAILED"),
|
|
194
297
|
domain: ErrorDomain.STORAGE,
|
|
195
298
|
category: ErrorCategory.USER,
|
|
196
299
|
text: `Thread ${id} not found`,
|
|
@@ -213,7 +316,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
213
316
|
} catch (error) {
|
|
214
317
|
throw new MastraError(
|
|
215
318
|
{
|
|
216
|
-
id: "
|
|
319
|
+
id: createStorageErrorId("UPSTASH", "UPDATE_THREAD", "FAILED"),
|
|
217
320
|
domain: ErrorDomain.STORAGE,
|
|
218
321
|
category: ErrorCategory.THIRD_PARTY,
|
|
219
322
|
details: {
|
|
@@ -238,11 +341,11 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
238
341
|
pipeline.del(messageKey);
|
|
239
342
|
}
|
|
240
343
|
await pipeline.exec();
|
|
241
|
-
await this.
|
|
344
|
+
await this.#db.scanAndDelete(getMessageKey(threadId, "*"));
|
|
242
345
|
} catch (error) {
|
|
243
346
|
throw new MastraError(
|
|
244
347
|
{
|
|
245
|
-
id: "
|
|
348
|
+
id: createStorageErrorId("UPSTASH", "DELETE_THREAD", "FAILED"),
|
|
246
349
|
domain: ErrorDomain.STORAGE,
|
|
247
350
|
category: ErrorCategory.THIRD_PARTY,
|
|
248
351
|
details: {
|
|
@@ -268,7 +371,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
268
371
|
} catch (error) {
|
|
269
372
|
throw new MastraError(
|
|
270
373
|
{
|
|
271
|
-
id: "
|
|
374
|
+
id: createStorageErrorId("UPSTASH", "SAVE_MESSAGES", "INVALID_ARGS"),
|
|
272
375
|
domain: ErrorDomain.STORAGE,
|
|
273
376
|
category: ErrorCategory.USER
|
|
274
377
|
},
|
|
@@ -303,7 +406,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
303
406
|
const createdAtScore = new Date(message.createdAt).getTime();
|
|
304
407
|
const score = message._index !== void 0 ? message._index : createdAtScore;
|
|
305
408
|
const existingKeyPattern = getMessageKey("*", message.id);
|
|
306
|
-
const keys = await this.
|
|
409
|
+
const keys = await this.#db.scanKeys(existingKeyPattern);
|
|
307
410
|
if (keys.length > 0) {
|
|
308
411
|
const pipeline2 = this.client.pipeline();
|
|
309
412
|
keys.forEach((key2) => pipeline2.get(key2));
|
|
@@ -318,6 +421,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
318
421
|
}
|
|
319
422
|
}
|
|
320
423
|
pipeline.set(key, message);
|
|
424
|
+
pipeline.set(getMessageIndexKey(message.id), message.threadId);
|
|
321
425
|
pipeline.zadd(getThreadMessagesKey(message.threadId), {
|
|
322
426
|
score,
|
|
323
427
|
member: message.id
|
|
@@ -337,7 +441,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
337
441
|
} catch (error) {
|
|
338
442
|
throw new MastraError(
|
|
339
443
|
{
|
|
340
|
-
id: "
|
|
444
|
+
id: createStorageErrorId("UPSTASH", "SAVE_MESSAGES", "FAILED"),
|
|
341
445
|
domain: ErrorDomain.STORAGE,
|
|
342
446
|
category: ErrorCategory.THIRD_PARTY,
|
|
343
447
|
details: {
|
|
@@ -348,43 +452,60 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
348
452
|
);
|
|
349
453
|
}
|
|
350
454
|
}
|
|
351
|
-
|
|
352
|
-
|
|
455
|
+
/**
|
|
456
|
+
* Lookup threadId for a message - tries index first (O(1)), falls back to scan (backwards compatible)
|
|
457
|
+
*/
|
|
458
|
+
async _getThreadIdForMessage(messageId) {
|
|
459
|
+
const indexedThreadId = await this.client.get(getMessageIndexKey(messageId));
|
|
460
|
+
if (indexedThreadId) {
|
|
461
|
+
return indexedThreadId;
|
|
462
|
+
}
|
|
463
|
+
const existingKeyPattern = getMessageKey("*", messageId);
|
|
464
|
+
const keys = await this.#db.scanKeys(existingKeyPattern);
|
|
465
|
+
if (keys.length === 0) return null;
|
|
466
|
+
const messageData = await this.client.get(keys[0]);
|
|
467
|
+
if (!messageData) return null;
|
|
468
|
+
if (messageData.threadId) {
|
|
469
|
+
await this.client.set(getMessageIndexKey(messageId), messageData.threadId);
|
|
470
|
+
}
|
|
471
|
+
return messageData.threadId || null;
|
|
472
|
+
}
|
|
473
|
+
async _getIncludedMessages(include) {
|
|
474
|
+
if (!include?.length) return [];
|
|
353
475
|
const messageIds = /* @__PURE__ */ new Set();
|
|
354
476
|
const messageIdToThreadIds = {};
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
477
|
+
for (const item of include) {
|
|
478
|
+
const itemThreadId = await this._getThreadIdForMessage(item.id);
|
|
479
|
+
if (!itemThreadId) continue;
|
|
480
|
+
messageIds.add(item.id);
|
|
481
|
+
messageIdToThreadIds[item.id] = itemThreadId;
|
|
482
|
+
const itemThreadMessagesKey = getThreadMessagesKey(itemThreadId);
|
|
483
|
+
const rank = await this.client.zrank(itemThreadMessagesKey, item.id);
|
|
484
|
+
if (rank === null) continue;
|
|
485
|
+
if (item.withPreviousMessages) {
|
|
486
|
+
const start = Math.max(0, rank - item.withPreviousMessages);
|
|
487
|
+
const prevIds = rank === 0 ? [] : await this.client.zrange(itemThreadMessagesKey, start, rank - 1);
|
|
488
|
+
prevIds.forEach((id) => {
|
|
489
|
+
messageIds.add(id);
|
|
490
|
+
messageIdToThreadIds[id] = itemThreadId;
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
if (item.withNextMessages) {
|
|
494
|
+
const nextIds = await this.client.zrange(itemThreadMessagesKey, rank + 1, rank + item.withNextMessages);
|
|
495
|
+
nextIds.forEach((id) => {
|
|
496
|
+
messageIds.add(id);
|
|
497
|
+
messageIdToThreadIds[id] = itemThreadId;
|
|
498
|
+
});
|
|
378
499
|
}
|
|
379
|
-
const pipeline = this.client.pipeline();
|
|
380
|
-
Array.from(messageIds).forEach((id) => {
|
|
381
|
-
const tId = messageIdToThreadIds[id] || threadId;
|
|
382
|
-
pipeline.get(getMessageKey(tId, id));
|
|
383
|
-
});
|
|
384
|
-
const results = await pipeline.exec();
|
|
385
|
-
return results.filter((result) => result !== null);
|
|
386
500
|
}
|
|
387
|
-
return [];
|
|
501
|
+
if (messageIds.size === 0) return [];
|
|
502
|
+
const pipeline = this.client.pipeline();
|
|
503
|
+
Array.from(messageIds).forEach((id) => {
|
|
504
|
+
const tId = messageIdToThreadIds[id];
|
|
505
|
+
pipeline.get(getMessageKey(tId, id));
|
|
506
|
+
});
|
|
507
|
+
const results = await pipeline.exec();
|
|
508
|
+
return results.filter((result) => result !== null);
|
|
388
509
|
}
|
|
389
510
|
parseStoredMessage(storedMessage) {
|
|
390
511
|
const defaultMessageContent = { format: 2, parts: [{ type: "text", text: "" }] };
|
|
@@ -398,23 +519,55 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
398
519
|
async listMessagesById({ messageIds }) {
|
|
399
520
|
if (messageIds.length === 0) return { messages: [] };
|
|
400
521
|
try {
|
|
401
|
-
const
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
522
|
+
const rawMessages = [];
|
|
523
|
+
const indexPipeline = this.client.pipeline();
|
|
524
|
+
messageIds.forEach((id) => indexPipeline.get(getMessageIndexKey(id)));
|
|
525
|
+
const indexResults = await indexPipeline.exec();
|
|
526
|
+
const indexedIds = [];
|
|
527
|
+
const unindexedIds = [];
|
|
528
|
+
messageIds.forEach((id, i) => {
|
|
529
|
+
const threadId = indexResults[i];
|
|
530
|
+
if (threadId) {
|
|
531
|
+
indexedIds.push({ messageId: id, threadId });
|
|
532
|
+
} else {
|
|
533
|
+
unindexedIds.push(id);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
if (indexedIds.length > 0) {
|
|
537
|
+
const messagePipeline = this.client.pipeline();
|
|
538
|
+
indexedIds.forEach(({ messageId, threadId }) => messagePipeline.get(getMessageKey(threadId, messageId)));
|
|
539
|
+
const messageResults = await messagePipeline.exec();
|
|
540
|
+
rawMessages.push(...messageResults.filter((msg) => msg !== null));
|
|
541
|
+
}
|
|
542
|
+
if (unindexedIds.length > 0) {
|
|
543
|
+
const threadKeys = await this.client.keys("thread:*");
|
|
544
|
+
const result = await Promise.all(
|
|
545
|
+
threadKeys.map((threadKey) => {
|
|
546
|
+
const threadId = threadKey.split(":")[1];
|
|
547
|
+
if (!threadId) throw new Error(`Failed to parse thread ID from thread key "${threadKey}"`);
|
|
548
|
+
return this.client.mget(
|
|
549
|
+
unindexedIds.map((id) => getMessageKey(threadId, id))
|
|
550
|
+
);
|
|
551
|
+
})
|
|
552
|
+
);
|
|
553
|
+
const foundMessages = result.flat(1).filter((msg) => !!msg);
|
|
554
|
+
rawMessages.push(...foundMessages);
|
|
555
|
+
if (foundMessages.length > 0) {
|
|
556
|
+
const backfillPipeline = this.client.pipeline();
|
|
557
|
+
foundMessages.forEach((msg) => {
|
|
558
|
+
if (msg.threadId) {
|
|
559
|
+
backfillPipeline.set(getMessageIndexKey(msg.id), msg.threadId);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
await backfillPipeline.exec();
|
|
563
|
+
}
|
|
564
|
+
}
|
|
412
565
|
const list = new MessageList().add(rawMessages.map(this.parseStoredMessage), "memory");
|
|
413
566
|
return { messages: list.get.all.db() };
|
|
414
567
|
} catch (error) {
|
|
415
568
|
throw new MastraError(
|
|
416
569
|
{
|
|
417
|
-
id: "
|
|
570
|
+
id: createStorageErrorId("UPSTASH", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
418
571
|
domain: ErrorDomain.STORAGE,
|
|
419
572
|
category: ErrorCategory.THIRD_PARTY,
|
|
420
573
|
details: {
|
|
@@ -427,25 +580,25 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
427
580
|
}
|
|
428
581
|
async listMessages(args) {
|
|
429
582
|
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
430
|
-
|
|
583
|
+
const threadIds = Array.isArray(threadId) ? threadId : [threadId];
|
|
584
|
+
if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
|
|
431
585
|
throw new MastraError(
|
|
432
586
|
{
|
|
433
|
-
id: "
|
|
587
|
+
id: createStorageErrorId("UPSTASH", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
434
588
|
domain: ErrorDomain.STORAGE,
|
|
435
589
|
category: ErrorCategory.THIRD_PARTY,
|
|
436
|
-
details: { threadId }
|
|
590
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
437
591
|
},
|
|
438
|
-
new Error("threadId must be a non-empty string")
|
|
592
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
439
593
|
);
|
|
440
594
|
}
|
|
441
|
-
const threadMessagesKey = getThreadMessagesKey(threadId);
|
|
442
595
|
const perPage = normalizePerPage(perPageInput, 40);
|
|
443
596
|
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
444
597
|
try {
|
|
445
598
|
if (page < 0) {
|
|
446
599
|
throw new MastraError(
|
|
447
600
|
{
|
|
448
|
-
id: "
|
|
601
|
+
id: createStorageErrorId("UPSTASH", "LIST_MESSAGES", "INVALID_PAGE"),
|
|
449
602
|
domain: ErrorDomain.STORAGE,
|
|
450
603
|
category: ErrorCategory.USER,
|
|
451
604
|
details: { page }
|
|
@@ -455,11 +608,18 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
455
608
|
}
|
|
456
609
|
let includedMessages = [];
|
|
457
610
|
if (include && include.length > 0) {
|
|
458
|
-
const included = await this._getIncludedMessages(
|
|
611
|
+
const included = await this._getIncludedMessages(include);
|
|
459
612
|
includedMessages = included.map(this.parseStoredMessage);
|
|
460
613
|
}
|
|
461
|
-
const
|
|
462
|
-
|
|
614
|
+
const allMessageIdsWithThreads = [];
|
|
615
|
+
for (const tid of threadIds) {
|
|
616
|
+
const threadMessagesKey = getThreadMessagesKey(tid);
|
|
617
|
+
const messageIds2 = await this.client.zrange(threadMessagesKey, 0, -1);
|
|
618
|
+
for (const mid of messageIds2) {
|
|
619
|
+
allMessageIdsWithThreads.push({ threadId: tid, messageId: mid });
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (allMessageIdsWithThreads.length === 0) {
|
|
463
623
|
return {
|
|
464
624
|
messages: [],
|
|
465
625
|
total: 0,
|
|
@@ -469,21 +629,17 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
469
629
|
};
|
|
470
630
|
}
|
|
471
631
|
const pipeline = this.client.pipeline();
|
|
472
|
-
|
|
632
|
+
allMessageIdsWithThreads.forEach(({ threadId: tid, messageId }) => pipeline.get(getMessageKey(tid, messageId)));
|
|
473
633
|
const results = await pipeline.exec();
|
|
474
634
|
let messagesData = results.filter((msg) => msg !== null).map(this.parseStoredMessage);
|
|
475
635
|
if (resourceId) {
|
|
476
636
|
messagesData = messagesData.filter((msg) => msg.resourceId === resourceId);
|
|
477
637
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (dateRange?.end) {
|
|
484
|
-
const toDate = dateRange.end;
|
|
485
|
-
messagesData = messagesData.filter((msg) => new Date(msg.createdAt).getTime() <= toDate.getTime());
|
|
486
|
-
}
|
|
638
|
+
messagesData = filterByDateRange(
|
|
639
|
+
messagesData,
|
|
640
|
+
(msg) => new Date(msg.createdAt),
|
|
641
|
+
filter?.dateRange
|
|
642
|
+
);
|
|
487
643
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
488
644
|
const getFieldValue = (msg) => {
|
|
489
645
|
if (field === "createdAt") {
|
|
@@ -498,13 +654,11 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
498
654
|
}
|
|
499
655
|
return 0;
|
|
500
656
|
};
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
});
|
|
507
|
-
}
|
|
657
|
+
messagesData.sort((a, b) => {
|
|
658
|
+
const aValue = getFieldValue(a);
|
|
659
|
+
const bValue = getFieldValue(b);
|
|
660
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
661
|
+
});
|
|
508
662
|
const total = messagesData.length;
|
|
509
663
|
const start = offset;
|
|
510
664
|
const end = perPageInput === false ? total : start + perPage;
|
|
@@ -525,23 +679,11 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
525
679
|
}
|
|
526
680
|
const list = new MessageList().add(allMessages, "memory");
|
|
527
681
|
let finalMessages = list.get.all.db();
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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
|
-
}
|
|
682
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
683
|
+
const aValue = getFieldValue(a);
|
|
684
|
+
const bValue = getFieldValue(b);
|
|
685
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
686
|
+
});
|
|
545
687
|
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
546
688
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
547
689
|
const hasMore = perPageInput !== false && !allThreadMessagesReturned && end < total;
|
|
@@ -555,11 +697,11 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
555
697
|
} catch (error) {
|
|
556
698
|
const mastraError = new MastraError(
|
|
557
699
|
{
|
|
558
|
-
id: "
|
|
700
|
+
id: createStorageErrorId("UPSTASH", "LIST_MESSAGES", "FAILED"),
|
|
559
701
|
domain: ErrorDomain.STORAGE,
|
|
560
702
|
category: ErrorCategory.THIRD_PARTY,
|
|
561
703
|
details: {
|
|
562
|
-
threadId,
|
|
704
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
563
705
|
resourceId: resourceId ?? ""
|
|
564
706
|
}
|
|
565
707
|
},
|
|
@@ -656,7 +798,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
656
798
|
const messageIdToKey = {};
|
|
657
799
|
for (const messageId of messageIds) {
|
|
658
800
|
const pattern = getMessageKey("*", messageId);
|
|
659
|
-
const keys = await this.
|
|
801
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
660
802
|
for (const key of keys) {
|
|
661
803
|
const message = await this.client.get(key);
|
|
662
804
|
if (message && message.id === messageId) {
|
|
@@ -746,7 +888,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
746
888
|
} catch (error) {
|
|
747
889
|
throw new MastraError(
|
|
748
890
|
{
|
|
749
|
-
id: "
|
|
891
|
+
id: createStorageErrorId("UPSTASH", "UPDATE_MESSAGES", "FAILED"),
|
|
750
892
|
domain: ErrorDomain.STORAGE,
|
|
751
893
|
category: ErrorCategory.THIRD_PARTY,
|
|
752
894
|
details: {
|
|
@@ -764,13 +906,33 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
764
906
|
try {
|
|
765
907
|
const threadIds = /* @__PURE__ */ new Set();
|
|
766
908
|
const messageKeys = [];
|
|
767
|
-
|
|
909
|
+
const foundMessageIds = [];
|
|
910
|
+
const indexPipeline = this.client.pipeline();
|
|
911
|
+
messageIds.forEach((id) => indexPipeline.get(getMessageIndexKey(id)));
|
|
912
|
+
const indexResults = await indexPipeline.exec();
|
|
913
|
+
const indexedMessages = [];
|
|
914
|
+
const unindexedMessageIds = [];
|
|
915
|
+
messageIds.forEach((id, i) => {
|
|
916
|
+
const threadId = indexResults[i];
|
|
917
|
+
if (threadId) {
|
|
918
|
+
indexedMessages.push({ messageId: id, threadId });
|
|
919
|
+
} else {
|
|
920
|
+
unindexedMessageIds.push(id);
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
for (const { messageId, threadId } of indexedMessages) {
|
|
924
|
+
messageKeys.push(getMessageKey(threadId, messageId));
|
|
925
|
+
foundMessageIds.push(messageId);
|
|
926
|
+
threadIds.add(threadId);
|
|
927
|
+
}
|
|
928
|
+
for (const messageId of unindexedMessageIds) {
|
|
768
929
|
const pattern = getMessageKey("*", messageId);
|
|
769
|
-
const keys = await this.
|
|
930
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
770
931
|
for (const key of keys) {
|
|
771
932
|
const message = await this.client.get(key);
|
|
772
933
|
if (message && message.id === messageId) {
|
|
773
934
|
messageKeys.push(key);
|
|
935
|
+
foundMessageIds.push(messageId);
|
|
774
936
|
if (message.threadId) {
|
|
775
937
|
threadIds.add(message.threadId);
|
|
776
938
|
}
|
|
@@ -785,6 +947,9 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
785
947
|
for (const key of messageKeys) {
|
|
786
948
|
pipeline.del(key);
|
|
787
949
|
}
|
|
950
|
+
for (const messageId of foundMessageIds) {
|
|
951
|
+
pipeline.del(getMessageIndexKey(messageId));
|
|
952
|
+
}
|
|
788
953
|
if (threadIds.size > 0) {
|
|
789
954
|
for (const threadId of threadIds) {
|
|
790
955
|
const threadKey = getKey(TABLE_THREADS, { id: threadId });
|
|
@@ -802,7 +967,7 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
802
967
|
} catch (error) {
|
|
803
968
|
throw new MastraError(
|
|
804
969
|
{
|
|
805
|
-
id: "
|
|
970
|
+
id: createStorageErrorId("UPSTASH", "DELETE_MESSAGES", "FAILED"),
|
|
806
971
|
domain: ErrorDomain.STORAGE,
|
|
807
972
|
category: ErrorCategory.THIRD_PARTY,
|
|
808
973
|
details: { messageIds: messageIds.join(", ") }
|
|
@@ -822,182 +987,137 @@ var StoreMemoryUpstash = class extends MemoryStorage {
|
|
|
822
987
|
}
|
|
823
988
|
});
|
|
824
989
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
}
|
|
837
|
-
async alterTable({
|
|
838
|
-
tableName: _tableName,
|
|
839
|
-
schema: _schema,
|
|
840
|
-
ifNotExists: _ifNotExists
|
|
841
|
-
}) {
|
|
842
|
-
}
|
|
843
|
-
async clearTable({ tableName }) {
|
|
844
|
-
const pattern = `${tableName}:*`;
|
|
845
|
-
try {
|
|
846
|
-
await this.scanAndDelete(pattern);
|
|
847
|
-
} catch (error) {
|
|
848
|
-
throw new MastraError(
|
|
849
|
-
{
|
|
850
|
-
id: "STORAGE_UPSTASH_STORAGE_CLEAR_TABLE_FAILED",
|
|
851
|
-
domain: ErrorDomain.STORAGE,
|
|
852
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
853
|
-
details: {
|
|
854
|
-
tableName
|
|
855
|
-
}
|
|
856
|
-
},
|
|
857
|
-
error
|
|
858
|
-
);
|
|
990
|
+
async cloneThread(args) {
|
|
991
|
+
const { sourceThreadId, newThreadId: providedThreadId, resourceId, title, metadata, options } = args;
|
|
992
|
+
const sourceThread = await this.getThreadById({ threadId: sourceThreadId });
|
|
993
|
+
if (!sourceThread) {
|
|
994
|
+
throw new MastraError({
|
|
995
|
+
id: createStorageErrorId("UPSTASH", "CLONE_THREAD", "SOURCE_NOT_FOUND"),
|
|
996
|
+
domain: ErrorDomain.STORAGE,
|
|
997
|
+
category: ErrorCategory.USER,
|
|
998
|
+
text: `Source thread with id ${sourceThreadId} not found`,
|
|
999
|
+
details: { sourceThreadId }
|
|
1000
|
+
});
|
|
859
1001
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
{
|
|
871
|
-
id: "STORAGE_UPSTASH_STORAGE_INSERT_FAILED",
|
|
872
|
-
domain: ErrorDomain.STORAGE,
|
|
873
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
874
|
-
details: {
|
|
875
|
-
tableName
|
|
876
|
-
}
|
|
877
|
-
},
|
|
878
|
-
error
|
|
879
|
-
);
|
|
1002
|
+
const newThreadId = providedThreadId || crypto.randomUUID();
|
|
1003
|
+
const existingThread = await this.getThreadById({ threadId: newThreadId });
|
|
1004
|
+
if (existingThread) {
|
|
1005
|
+
throw new MastraError({
|
|
1006
|
+
id: createStorageErrorId("UPSTASH", "CLONE_THREAD", "THREAD_EXISTS"),
|
|
1007
|
+
domain: ErrorDomain.STORAGE,
|
|
1008
|
+
category: ErrorCategory.USER,
|
|
1009
|
+
text: `Thread with id ${newThreadId} already exists`,
|
|
1010
|
+
details: { newThreadId }
|
|
1011
|
+
});
|
|
880
1012
|
}
|
|
881
|
-
}
|
|
882
|
-
async batchInsert(input) {
|
|
883
|
-
const { tableName, records } = input;
|
|
884
|
-
if (!records.length) return;
|
|
885
|
-
const batchSize = 1e3;
|
|
886
1013
|
try {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
pipeline.set(key, processedRecord);
|
|
893
|
-
}
|
|
894
|
-
await pipeline.exec();
|
|
1014
|
+
const threadMessagesKey = getThreadMessagesKey(sourceThreadId);
|
|
1015
|
+
const messageIds = await this.client.zrange(threadMessagesKey, 0, -1);
|
|
1016
|
+
const pipeline = this.client.pipeline();
|
|
1017
|
+
for (const mid of messageIds) {
|
|
1018
|
+
pipeline.get(getMessageKey(sourceThreadId, mid));
|
|
895
1019
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1020
|
+
const results = await pipeline.exec();
|
|
1021
|
+
let sourceMessages = results.filter((msg) => msg !== null).map((msg) => ({
|
|
1022
|
+
...msg,
|
|
1023
|
+
createdAt: new Date(msg.createdAt)
|
|
1024
|
+
}));
|
|
1025
|
+
if (options?.messageFilter?.startDate || options?.messageFilter?.endDate) {
|
|
1026
|
+
sourceMessages = filterByDateRange(sourceMessages, (msg) => new Date(msg.createdAt), {
|
|
1027
|
+
start: options.messageFilter?.startDate,
|
|
1028
|
+
end: options.messageFilter?.endDate
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
if (options?.messageFilter?.messageIds && options.messageFilter.messageIds.length > 0) {
|
|
1032
|
+
const messageIdSet = new Set(options.messageFilter.messageIds);
|
|
1033
|
+
sourceMessages = sourceMessages.filter((msg) => messageIdSet.has(msg.id));
|
|
1034
|
+
}
|
|
1035
|
+
sourceMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
1036
|
+
if (options?.messageLimit && options.messageLimit > 0 && sourceMessages.length > options.messageLimit) {
|
|
1037
|
+
sourceMessages = sourceMessages.slice(-options.messageLimit);
|
|
1038
|
+
}
|
|
1039
|
+
const now = /* @__PURE__ */ new Date();
|
|
1040
|
+
const lastMessageId = sourceMessages.length > 0 ? sourceMessages[sourceMessages.length - 1].id : void 0;
|
|
1041
|
+
const cloneMetadata = {
|
|
1042
|
+
sourceThreadId,
|
|
1043
|
+
clonedAt: now,
|
|
1044
|
+
...lastMessageId && { lastMessageId }
|
|
1045
|
+
};
|
|
1046
|
+
const newThread = {
|
|
1047
|
+
id: newThreadId,
|
|
1048
|
+
resourceId: resourceId || sourceThread.resourceId,
|
|
1049
|
+
title: title || (sourceThread.title ? `Clone of ${sourceThread.title}` : void 0),
|
|
1050
|
+
metadata: {
|
|
1051
|
+
...metadata,
|
|
1052
|
+
clone: cloneMetadata
|
|
905
1053
|
},
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
const
|
|
914
|
-
|
|
1054
|
+
createdAt: now,
|
|
1055
|
+
updatedAt: now
|
|
1056
|
+
};
|
|
1057
|
+
const writePipeline = this.client.pipeline();
|
|
1058
|
+
const threadKey = getKey(TABLE_THREADS, { id: newThreadId });
|
|
1059
|
+
writePipeline.set(threadKey, processRecord(TABLE_THREADS, newThread).processedRecord);
|
|
1060
|
+
const clonedMessages = [];
|
|
1061
|
+
const targetResourceId = resourceId || sourceThread.resourceId;
|
|
1062
|
+
const newThreadMessagesKey = getThreadMessagesKey(newThreadId);
|
|
1063
|
+
for (let i = 0; i < sourceMessages.length; i++) {
|
|
1064
|
+
const sourceMsg = sourceMessages[i];
|
|
1065
|
+
const newMessageId = crypto.randomUUID();
|
|
1066
|
+
const { _index, ...restMsg } = sourceMsg;
|
|
1067
|
+
const newMessage = {
|
|
1068
|
+
...restMsg,
|
|
1069
|
+
id: newMessageId,
|
|
1070
|
+
threadId: newThreadId,
|
|
1071
|
+
resourceId: targetResourceId
|
|
1072
|
+
};
|
|
1073
|
+
const messageKey = getMessageKey(newThreadId, newMessageId);
|
|
1074
|
+
writePipeline.set(messageKey, newMessage);
|
|
1075
|
+
writePipeline.set(getMessageIndexKey(newMessageId), newThreadId);
|
|
1076
|
+
writePipeline.zadd(newThreadMessagesKey, {
|
|
1077
|
+
score: i,
|
|
1078
|
+
member: newMessageId
|
|
1079
|
+
});
|
|
1080
|
+
clonedMessages.push(newMessage);
|
|
1081
|
+
}
|
|
1082
|
+
await writePipeline.exec();
|
|
1083
|
+
return {
|
|
1084
|
+
thread: newThread,
|
|
1085
|
+
clonedMessages
|
|
1086
|
+
};
|
|
915
1087
|
} catch (error) {
|
|
1088
|
+
if (error instanceof MastraError) {
|
|
1089
|
+
throw error;
|
|
1090
|
+
}
|
|
916
1091
|
throw new MastraError(
|
|
917
1092
|
{
|
|
918
|
-
id: "
|
|
1093
|
+
id: createStorageErrorId("UPSTASH", "CLONE_THREAD", "FAILED"),
|
|
919
1094
|
domain: ErrorDomain.STORAGE,
|
|
920
1095
|
category: ErrorCategory.THIRD_PARTY,
|
|
921
|
-
details: {
|
|
922
|
-
tableName
|
|
923
|
-
}
|
|
1096
|
+
details: { sourceThreadId, newThreadId }
|
|
924
1097
|
},
|
|
925
1098
|
error
|
|
926
1099
|
);
|
|
927
1100
|
}
|
|
928
1101
|
}
|
|
929
|
-
async hasColumn(_tableName, _column) {
|
|
930
|
-
return true;
|
|
931
|
-
}
|
|
932
|
-
async scanKeys(pattern, batchSize = 1e4) {
|
|
933
|
-
let cursor = "0";
|
|
934
|
-
let keys = [];
|
|
935
|
-
do {
|
|
936
|
-
const [nextCursor, batch] = await this.client.scan(cursor, {
|
|
937
|
-
match: pattern,
|
|
938
|
-
count: batchSize
|
|
939
|
-
});
|
|
940
|
-
keys.push(...batch);
|
|
941
|
-
cursor = nextCursor;
|
|
942
|
-
} while (cursor !== "0");
|
|
943
|
-
return keys;
|
|
944
|
-
}
|
|
945
|
-
async scanAndDelete(pattern, batchSize = 1e4) {
|
|
946
|
-
let cursor = "0";
|
|
947
|
-
let totalDeleted = 0;
|
|
948
|
-
do {
|
|
949
|
-
const [nextCursor, keys] = await this.client.scan(cursor, {
|
|
950
|
-
match: pattern,
|
|
951
|
-
count: batchSize
|
|
952
|
-
});
|
|
953
|
-
if (keys.length > 0) {
|
|
954
|
-
await this.client.del(...keys);
|
|
955
|
-
totalDeleted += keys.length;
|
|
956
|
-
}
|
|
957
|
-
cursor = nextCursor;
|
|
958
|
-
} while (cursor !== "0");
|
|
959
|
-
return totalDeleted;
|
|
960
|
-
}
|
|
961
1102
|
};
|
|
962
|
-
function transformScoreRow(row) {
|
|
963
|
-
|
|
964
|
-
if (typeof v === "string") {
|
|
965
|
-
try {
|
|
966
|
-
return JSON.parse(v);
|
|
967
|
-
} catch {
|
|
968
|
-
return v;
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
return v;
|
|
972
|
-
};
|
|
973
|
-
return {
|
|
974
|
-
...row,
|
|
975
|
-
scorer: parseField(row.scorer),
|
|
976
|
-
preprocessStepResult: parseField(row.preprocessStepResult),
|
|
977
|
-
generateScorePrompt: row.generateScorePrompt,
|
|
978
|
-
generateReasonPrompt: row.generateReasonPrompt,
|
|
979
|
-
analyzeStepResult: parseField(row.analyzeStepResult),
|
|
980
|
-
metadata: parseField(row.metadata),
|
|
981
|
-
input: parseField(row.input),
|
|
982
|
-
output: parseField(row.output),
|
|
983
|
-
additionalContext: parseField(row.additionalContext),
|
|
984
|
-
requestContext: parseField(row.requestContext),
|
|
985
|
-
entity: parseField(row.entity),
|
|
986
|
-
createdAt: row.createdAt,
|
|
987
|
-
updatedAt: row.updatedAt
|
|
988
|
-
};
|
|
1103
|
+
function transformScoreRow(row) {
|
|
1104
|
+
return transformScoreRow$1(row);
|
|
989
1105
|
}
|
|
990
1106
|
var ScoresUpstash = class extends ScoresStorage {
|
|
991
1107
|
client;
|
|
992
|
-
|
|
993
|
-
constructor(
|
|
1108
|
+
#db;
|
|
1109
|
+
constructor(config) {
|
|
994
1110
|
super();
|
|
1111
|
+
const client = resolveUpstashConfig(config);
|
|
995
1112
|
this.client = client;
|
|
996
|
-
this
|
|
1113
|
+
this.#db = new UpstashDB({ client });
|
|
1114
|
+
}
|
|
1115
|
+
async dangerouslyClearAll() {
|
|
1116
|
+
await this.#db.deleteData({ tableName: TABLE_SCORERS });
|
|
997
1117
|
}
|
|
998
1118
|
async getScoreById({ id }) {
|
|
999
1119
|
try {
|
|
1000
|
-
const data = await this.
|
|
1120
|
+
const data = await this.#db.get({
|
|
1001
1121
|
tableName: TABLE_SCORERS,
|
|
1002
1122
|
keys: { id }
|
|
1003
1123
|
});
|
|
@@ -1006,10 +1126,12 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1006
1126
|
} catch (error) {
|
|
1007
1127
|
throw new MastraError(
|
|
1008
1128
|
{
|
|
1009
|
-
id: "
|
|
1129
|
+
id: createStorageErrorId("UPSTASH", "GET_SCORE_BY_ID", "FAILED"),
|
|
1010
1130
|
domain: ErrorDomain.STORAGE,
|
|
1011
1131
|
category: ErrorCategory.THIRD_PARTY,
|
|
1012
|
-
details: {
|
|
1132
|
+
details: {
|
|
1133
|
+
...id && { id }
|
|
1134
|
+
}
|
|
1013
1135
|
},
|
|
1014
1136
|
error
|
|
1015
1137
|
);
|
|
@@ -1023,7 +1145,7 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1023
1145
|
pagination = { page: 0, perPage: 20 }
|
|
1024
1146
|
}) {
|
|
1025
1147
|
const pattern = `${TABLE_SCORERS}:*`;
|
|
1026
|
-
const keys = await this.
|
|
1148
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
1027
1149
|
const { page, perPage: perPageInput } = pagination;
|
|
1028
1150
|
if (keys.length === 0) {
|
|
1029
1151
|
return {
|
|
@@ -1075,24 +1197,41 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1075
1197
|
} catch (error) {
|
|
1076
1198
|
throw new MastraError(
|
|
1077
1199
|
{
|
|
1078
|
-
id: "
|
|
1200
|
+
id: createStorageErrorId("UPSTASH", "SAVE_SCORE", "VALIDATION_FAILED"),
|
|
1079
1201
|
domain: ErrorDomain.STORAGE,
|
|
1080
|
-
category: ErrorCategory.
|
|
1202
|
+
category: ErrorCategory.USER,
|
|
1203
|
+
details: {
|
|
1204
|
+
scorer: typeof score.scorer?.id === "string" ? score.scorer.id : String(score.scorer?.id ?? "unknown"),
|
|
1205
|
+
entityId: score.entityId ?? "unknown",
|
|
1206
|
+
entityType: score.entityType ?? "unknown",
|
|
1207
|
+
traceId: score.traceId ?? "",
|
|
1208
|
+
spanId: score.spanId ?? ""
|
|
1209
|
+
}
|
|
1081
1210
|
},
|
|
1082
1211
|
error
|
|
1083
1212
|
);
|
|
1084
1213
|
}
|
|
1085
|
-
const
|
|
1214
|
+
const now = /* @__PURE__ */ new Date();
|
|
1215
|
+
const id = crypto.randomUUID();
|
|
1216
|
+
const createdAt = now;
|
|
1217
|
+
const updatedAt = now;
|
|
1218
|
+
const scoreWithId = {
|
|
1219
|
+
...validatedScore,
|
|
1220
|
+
id,
|
|
1221
|
+
createdAt,
|
|
1222
|
+
updatedAt
|
|
1223
|
+
};
|
|
1224
|
+
const { key, processedRecord } = processRecord(TABLE_SCORERS, scoreWithId);
|
|
1086
1225
|
try {
|
|
1087
1226
|
await this.client.set(key, processedRecord);
|
|
1088
|
-
return { score };
|
|
1227
|
+
return { score: { ...validatedScore, id, createdAt, updatedAt } };
|
|
1089
1228
|
} catch (error) {
|
|
1090
1229
|
throw new MastraError(
|
|
1091
1230
|
{
|
|
1092
|
-
id: "
|
|
1231
|
+
id: createStorageErrorId("UPSTASH", "SAVE_SCORE", "FAILED"),
|
|
1093
1232
|
domain: ErrorDomain.STORAGE,
|
|
1094
1233
|
category: ErrorCategory.THIRD_PARTY,
|
|
1095
|
-
details: { id
|
|
1234
|
+
details: { id }
|
|
1096
1235
|
},
|
|
1097
1236
|
error
|
|
1098
1237
|
);
|
|
@@ -1103,7 +1242,7 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1103
1242
|
pagination = { page: 0, perPage: 20 }
|
|
1104
1243
|
}) {
|
|
1105
1244
|
const pattern = `${TABLE_SCORERS}:*`;
|
|
1106
|
-
const keys = await this.
|
|
1245
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
1107
1246
|
const { page, perPage: perPageInput } = pagination;
|
|
1108
1247
|
if (keys.length === 0) {
|
|
1109
1248
|
return {
|
|
@@ -1147,7 +1286,7 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1147
1286
|
pagination = { page: 0, perPage: 20 }
|
|
1148
1287
|
}) {
|
|
1149
1288
|
const pattern = `${TABLE_SCORERS}:*`;
|
|
1150
|
-
const keys = await this.
|
|
1289
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
1151
1290
|
const { page, perPage: perPageInput } = pagination;
|
|
1152
1291
|
if (keys.length === 0) {
|
|
1153
1292
|
return {
|
|
@@ -1196,7 +1335,7 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1196
1335
|
pagination = { page: 0, perPage: 20 }
|
|
1197
1336
|
}) {
|
|
1198
1337
|
const pattern = `${TABLE_SCORERS}:*`;
|
|
1199
|
-
const keys = await this.
|
|
1338
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
1200
1339
|
const { page, perPage: perPageInput } = pagination;
|
|
1201
1340
|
if (keys.length === 0) {
|
|
1202
1341
|
return {
|
|
@@ -1240,52 +1379,129 @@ var ScoresUpstash = class extends ScoresStorage {
|
|
|
1240
1379
|
};
|
|
1241
1380
|
}
|
|
1242
1381
|
};
|
|
1243
|
-
function parseWorkflowRun(row) {
|
|
1244
|
-
let parsedSnapshot = row.snapshot;
|
|
1245
|
-
if (typeof parsedSnapshot === "string") {
|
|
1246
|
-
try {
|
|
1247
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1248
|
-
} catch (e) {
|
|
1249
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
return {
|
|
1253
|
-
workflowName: row.workflow_name,
|
|
1254
|
-
runId: row.run_id,
|
|
1255
|
-
snapshot: parsedSnapshot,
|
|
1256
|
-
createdAt: ensureDate(row.createdAt),
|
|
1257
|
-
updatedAt: ensureDate(row.updatedAt),
|
|
1258
|
-
resourceId: row.resourceId
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
1382
|
var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
1262
1383
|
client;
|
|
1263
|
-
|
|
1264
|
-
constructor(
|
|
1384
|
+
#db;
|
|
1385
|
+
constructor(config) {
|
|
1265
1386
|
super();
|
|
1387
|
+
const client = resolveUpstashConfig(config);
|
|
1266
1388
|
this.client = client;
|
|
1267
|
-
this
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1389
|
+
this.#db = new UpstashDB({ client });
|
|
1390
|
+
}
|
|
1391
|
+
parseWorkflowRun(row) {
|
|
1392
|
+
let parsedSnapshot = row.snapshot;
|
|
1393
|
+
if (typeof parsedSnapshot === "string") {
|
|
1394
|
+
try {
|
|
1395
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1396
|
+
} catch (e) {
|
|
1397
|
+
this.logger.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return {
|
|
1401
|
+
workflowName: row.workflow_name,
|
|
1402
|
+
runId: row.run_id,
|
|
1403
|
+
snapshot: parsedSnapshot,
|
|
1404
|
+
createdAt: ensureDate(row.createdAt),
|
|
1405
|
+
updatedAt: ensureDate(row.updatedAt),
|
|
1406
|
+
resourceId: row.resourceId
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
async dangerouslyClearAll() {
|
|
1410
|
+
await this.#db.deleteData({ tableName: TABLE_WORKFLOW_SNAPSHOT });
|
|
1411
|
+
}
|
|
1412
|
+
async updateWorkflowResults({
|
|
1413
|
+
workflowName,
|
|
1414
|
+
runId,
|
|
1415
|
+
stepId,
|
|
1416
|
+
result,
|
|
1417
|
+
requestContext
|
|
1275
1418
|
}) {
|
|
1276
|
-
|
|
1419
|
+
try {
|
|
1420
|
+
const existingSnapshot = await this.loadWorkflowSnapshot({
|
|
1421
|
+
namespace: "workflows",
|
|
1422
|
+
workflowName,
|
|
1423
|
+
runId
|
|
1424
|
+
});
|
|
1425
|
+
let snapshot;
|
|
1426
|
+
if (!existingSnapshot) {
|
|
1427
|
+
snapshot = {
|
|
1428
|
+
context: {},
|
|
1429
|
+
activePaths: [],
|
|
1430
|
+
timestamp: Date.now(),
|
|
1431
|
+
suspendedPaths: {},
|
|
1432
|
+
activeStepsPath: {},
|
|
1433
|
+
resumeLabels: {},
|
|
1434
|
+
serializedStepGraph: [],
|
|
1435
|
+
status: "pending",
|
|
1436
|
+
value: {},
|
|
1437
|
+
waitingPaths: {},
|
|
1438
|
+
runId,
|
|
1439
|
+
requestContext: {}
|
|
1440
|
+
};
|
|
1441
|
+
} else {
|
|
1442
|
+
snapshot = existingSnapshot;
|
|
1443
|
+
}
|
|
1444
|
+
snapshot.context[stepId] = result;
|
|
1445
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
1446
|
+
await this.persistWorkflowSnapshot({
|
|
1447
|
+
namespace: "workflows",
|
|
1448
|
+
workflowName,
|
|
1449
|
+
runId,
|
|
1450
|
+
snapshot
|
|
1451
|
+
});
|
|
1452
|
+
return snapshot.context;
|
|
1453
|
+
} catch (error) {
|
|
1454
|
+
if (error instanceof MastraError) throw error;
|
|
1455
|
+
throw new MastraError(
|
|
1456
|
+
{
|
|
1457
|
+
id: createStorageErrorId("UPSTASH", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
|
|
1458
|
+
domain: ErrorDomain.STORAGE,
|
|
1459
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1460
|
+
details: { workflowName, runId, stepId }
|
|
1461
|
+
},
|
|
1462
|
+
error
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1277
1465
|
}
|
|
1278
|
-
updateWorkflowState({
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1466
|
+
async updateWorkflowState({
|
|
1467
|
+
workflowName,
|
|
1468
|
+
runId,
|
|
1469
|
+
opts
|
|
1282
1470
|
}) {
|
|
1283
|
-
|
|
1471
|
+
try {
|
|
1472
|
+
const existingSnapshot = await this.loadWorkflowSnapshot({
|
|
1473
|
+
namespace: "workflows",
|
|
1474
|
+
workflowName,
|
|
1475
|
+
runId
|
|
1476
|
+
});
|
|
1477
|
+
if (!existingSnapshot || !existingSnapshot.context) {
|
|
1478
|
+
return void 0;
|
|
1479
|
+
}
|
|
1480
|
+
const updatedSnapshot = { ...existingSnapshot, ...opts };
|
|
1481
|
+
await this.persistWorkflowSnapshot({
|
|
1482
|
+
namespace: "workflows",
|
|
1483
|
+
workflowName,
|
|
1484
|
+
runId,
|
|
1485
|
+
snapshot: updatedSnapshot
|
|
1486
|
+
});
|
|
1487
|
+
return updatedSnapshot;
|
|
1488
|
+
} catch (error) {
|
|
1489
|
+
if (error instanceof MastraError) throw error;
|
|
1490
|
+
throw new MastraError(
|
|
1491
|
+
{
|
|
1492
|
+
id: createStorageErrorId("UPSTASH", "UPDATE_WORKFLOW_STATE", "FAILED"),
|
|
1493
|
+
domain: ErrorDomain.STORAGE,
|
|
1494
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1495
|
+
details: { workflowName, runId }
|
|
1496
|
+
},
|
|
1497
|
+
error
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1284
1500
|
}
|
|
1285
1501
|
async persistWorkflowSnapshot(params) {
|
|
1286
|
-
const { namespace = "workflows", workflowName, runId, resourceId, snapshot } = params;
|
|
1502
|
+
const { namespace = "workflows", workflowName, runId, resourceId, snapshot, createdAt, updatedAt } = params;
|
|
1287
1503
|
try {
|
|
1288
|
-
await this.
|
|
1504
|
+
await this.#db.insert({
|
|
1289
1505
|
tableName: TABLE_WORKFLOW_SNAPSHOT,
|
|
1290
1506
|
record: {
|
|
1291
1507
|
namespace,
|
|
@@ -1293,14 +1509,14 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1293
1509
|
run_id: runId,
|
|
1294
1510
|
resourceId,
|
|
1295
1511
|
snapshot,
|
|
1296
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1297
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1512
|
+
createdAt: createdAt ?? /* @__PURE__ */ new Date(),
|
|
1513
|
+
updatedAt: updatedAt ?? /* @__PURE__ */ new Date()
|
|
1298
1514
|
}
|
|
1299
1515
|
});
|
|
1300
1516
|
} catch (error) {
|
|
1301
1517
|
throw new MastraError(
|
|
1302
1518
|
{
|
|
1303
|
-
id: "
|
|
1519
|
+
id: createStorageErrorId("UPSTASH", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1304
1520
|
domain: ErrorDomain.STORAGE,
|
|
1305
1521
|
category: ErrorCategory.THIRD_PARTY,
|
|
1306
1522
|
details: {
|
|
@@ -1327,7 +1543,7 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1327
1543
|
} catch (error) {
|
|
1328
1544
|
throw new MastraError(
|
|
1329
1545
|
{
|
|
1330
|
-
id: "
|
|
1546
|
+
id: createStorageErrorId("UPSTASH", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1331
1547
|
domain: ErrorDomain.STORAGE,
|
|
1332
1548
|
category: ErrorCategory.THIRD_PARTY,
|
|
1333
1549
|
details: {
|
|
@@ -1346,7 +1562,7 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1346
1562
|
}) {
|
|
1347
1563
|
try {
|
|
1348
1564
|
const key = getKey(TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows", workflow_name: workflowName, run_id: runId }) + "*";
|
|
1349
|
-
const keys = await this.
|
|
1565
|
+
const keys = await this.#db.scanKeys(key);
|
|
1350
1566
|
const workflows = await Promise.all(
|
|
1351
1567
|
keys.map(async (key2) => {
|
|
1352
1568
|
const data2 = await this.client.get(key2);
|
|
@@ -1355,11 +1571,11 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1355
1571
|
);
|
|
1356
1572
|
const data = workflows.find((w) => w?.run_id === runId && w?.workflow_name === workflowName);
|
|
1357
1573
|
if (!data) return null;
|
|
1358
|
-
return parseWorkflowRun(data);
|
|
1574
|
+
return this.parseWorkflowRun(data);
|
|
1359
1575
|
} catch (error) {
|
|
1360
1576
|
throw new MastraError(
|
|
1361
1577
|
{
|
|
1362
|
-
id: "
|
|
1578
|
+
id: createStorageErrorId("UPSTASH", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1363
1579
|
domain: ErrorDomain.STORAGE,
|
|
1364
1580
|
category: ErrorCategory.THIRD_PARTY,
|
|
1365
1581
|
details: {
|
|
@@ -1372,6 +1588,26 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1372
1588
|
);
|
|
1373
1589
|
}
|
|
1374
1590
|
}
|
|
1591
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
1592
|
+
const key = getKey(TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows", workflow_name: workflowName, run_id: runId });
|
|
1593
|
+
try {
|
|
1594
|
+
await this.client.del(key);
|
|
1595
|
+
} catch (error) {
|
|
1596
|
+
throw new MastraError(
|
|
1597
|
+
{
|
|
1598
|
+
id: createStorageErrorId("UPSTASH", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1599
|
+
domain: ErrorDomain.STORAGE,
|
|
1600
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1601
|
+
details: {
|
|
1602
|
+
namespace: "workflows",
|
|
1603
|
+
runId,
|
|
1604
|
+
workflowName
|
|
1605
|
+
}
|
|
1606
|
+
},
|
|
1607
|
+
error
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1375
1611
|
async listWorkflowRuns({
|
|
1376
1612
|
workflowName,
|
|
1377
1613
|
fromDate,
|
|
@@ -1380,12 +1616,12 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1380
1616
|
page,
|
|
1381
1617
|
resourceId,
|
|
1382
1618
|
status
|
|
1383
|
-
}) {
|
|
1619
|
+
} = {}) {
|
|
1384
1620
|
try {
|
|
1385
1621
|
if (page !== void 0 && page < 0) {
|
|
1386
1622
|
throw new MastraError(
|
|
1387
1623
|
{
|
|
1388
|
-
id: "
|
|
1624
|
+
id: createStorageErrorId("UPSTASH", "LIST_WORKFLOW_RUNS", "INVALID_PAGE"),
|
|
1389
1625
|
domain: ErrorDomain.STORAGE,
|
|
1390
1626
|
category: ErrorCategory.USER,
|
|
1391
1627
|
details: { page }
|
|
@@ -1411,7 +1647,7 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1411
1647
|
resourceId
|
|
1412
1648
|
});
|
|
1413
1649
|
}
|
|
1414
|
-
const keys = await this.
|
|
1650
|
+
const keys = await this.#db.scanKeys(pattern);
|
|
1415
1651
|
if (keys.length === 0) {
|
|
1416
1652
|
return { runs: [], total: 0 };
|
|
1417
1653
|
}
|
|
@@ -1420,7 +1656,7 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1420
1656
|
const results = await pipeline.exec();
|
|
1421
1657
|
let runs = results.map((result) => result).filter(
|
|
1422
1658
|
(record) => record !== null && record !== void 0 && typeof record === "object" && "workflow_name" in record
|
|
1423
|
-
).filter((record) => !workflowName || record.workflow_name === workflowName).map((w) => parseWorkflowRun(w)).filter((w) => {
|
|
1659
|
+
).filter((record) => !workflowName || record.workflow_name === workflowName).map((w) => this.parseWorkflowRun(w)).filter((w) => {
|
|
1424
1660
|
if (fromDate && w.createdAt < fromDate) return false;
|
|
1425
1661
|
if (toDate && w.createdAt > toDate) return false;
|
|
1426
1662
|
if (status) {
|
|
@@ -1429,7 +1665,7 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1429
1665
|
try {
|
|
1430
1666
|
snapshot = JSON.parse(snapshot);
|
|
1431
1667
|
} catch (e) {
|
|
1432
|
-
|
|
1668
|
+
this.logger.warn(`Failed to parse snapshot for workflow ${w.workflowName}: ${e}`);
|
|
1433
1669
|
return false;
|
|
1434
1670
|
}
|
|
1435
1671
|
}
|
|
@@ -1445,9 +1681,10 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1445
1681
|
}
|
|
1446
1682
|
return { runs, total };
|
|
1447
1683
|
} catch (error) {
|
|
1684
|
+
if (error instanceof MastraError) throw error;
|
|
1448
1685
|
throw new MastraError(
|
|
1449
1686
|
{
|
|
1450
|
-
id: "
|
|
1687
|
+
id: createStorageErrorId("UPSTASH", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
1451
1688
|
domain: ErrorDomain.STORAGE,
|
|
1452
1689
|
category: ErrorCategory.THIRD_PARTY,
|
|
1453
1690
|
details: {
|
|
@@ -1463,179 +1700,39 @@ var WorkflowsUpstash = class extends WorkflowsStorage {
|
|
|
1463
1700
|
};
|
|
1464
1701
|
|
|
1465
1702
|
// src/storage/index.ts
|
|
1703
|
+
var isClientConfig = (config) => {
|
|
1704
|
+
return "client" in config;
|
|
1705
|
+
};
|
|
1466
1706
|
var UpstashStore = class extends MastraStorage {
|
|
1467
1707
|
redis;
|
|
1468
1708
|
stores;
|
|
1469
1709
|
constructor(config) {
|
|
1470
|
-
super({ id: config.id, name: "Upstash" });
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1710
|
+
super({ id: config.id, name: "Upstash", disableInit: config.disableInit });
|
|
1711
|
+
if (isClientConfig(config)) {
|
|
1712
|
+
this.redis = config.client;
|
|
1713
|
+
} else {
|
|
1714
|
+
if (!config.url || typeof config.url !== "string" || config.url.trim() === "") {
|
|
1715
|
+
throw new Error("UpstashStore: url is required and cannot be empty.");
|
|
1716
|
+
}
|
|
1717
|
+
if (!config.token || typeof config.token !== "string" || config.token.trim() === "") {
|
|
1718
|
+
throw new Error("UpstashStore: token is required and cannot be empty.");
|
|
1719
|
+
}
|
|
1720
|
+
this.redis = new Redis({
|
|
1721
|
+
url: config.url,
|
|
1722
|
+
token: config.token
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
const scores = new ScoresUpstash({ client: this.redis });
|
|
1726
|
+
const workflows = new WorkflowsUpstash({ client: this.redis });
|
|
1727
|
+
const memory = new StoreMemoryUpstash({ client: this.redis });
|
|
1479
1728
|
this.stores = {
|
|
1480
|
-
operations,
|
|
1481
1729
|
scores,
|
|
1482
1730
|
workflows,
|
|
1483
1731
|
memory
|
|
1484
1732
|
};
|
|
1485
1733
|
}
|
|
1486
|
-
get supports() {
|
|
1487
|
-
return {
|
|
1488
|
-
selectByIncludeResourceScope: true,
|
|
1489
|
-
resourceWorkingMemory: true,
|
|
1490
|
-
hasColumn: false,
|
|
1491
|
-
createTable: false,
|
|
1492
|
-
deleteMessages: true,
|
|
1493
|
-
listScoresBySpan: true
|
|
1494
|
-
};
|
|
1495
|
-
}
|
|
1496
|
-
async createTable({
|
|
1497
|
-
tableName,
|
|
1498
|
-
schema
|
|
1499
|
-
}) {
|
|
1500
|
-
return this.stores.operations.createTable({ tableName, schema });
|
|
1501
|
-
}
|
|
1502
|
-
/**
|
|
1503
|
-
* No-op: This backend is schemaless and does not require schema changes.
|
|
1504
|
-
* @param tableName Name of the table
|
|
1505
|
-
* @param schema Schema of the table
|
|
1506
|
-
* @param ifNotExists Array of column names to add if they don't exist
|
|
1507
|
-
*/
|
|
1508
|
-
async alterTable(args) {
|
|
1509
|
-
return this.stores.operations.alterTable(args);
|
|
1510
|
-
}
|
|
1511
|
-
async clearTable({ tableName }) {
|
|
1512
|
-
return this.stores.operations.clearTable({ tableName });
|
|
1513
|
-
}
|
|
1514
|
-
async dropTable({ tableName }) {
|
|
1515
|
-
return this.stores.operations.dropTable({ tableName });
|
|
1516
|
-
}
|
|
1517
|
-
async insert({ tableName, record }) {
|
|
1518
|
-
return this.stores.operations.insert({ tableName, record });
|
|
1519
|
-
}
|
|
1520
|
-
async batchInsert(input) {
|
|
1521
|
-
return this.stores.operations.batchInsert(input);
|
|
1522
|
-
}
|
|
1523
|
-
async load({ tableName, keys }) {
|
|
1524
|
-
return this.stores.operations.load({ tableName, keys });
|
|
1525
|
-
}
|
|
1526
|
-
async getThreadById({ threadId }) {
|
|
1527
|
-
return this.stores.memory.getThreadById({ threadId });
|
|
1528
|
-
}
|
|
1529
|
-
async saveThread({ thread }) {
|
|
1530
|
-
return this.stores.memory.saveThread({ thread });
|
|
1531
|
-
}
|
|
1532
|
-
async updateThread({
|
|
1533
|
-
id,
|
|
1534
|
-
title,
|
|
1535
|
-
metadata
|
|
1536
|
-
}) {
|
|
1537
|
-
return this.stores.memory.updateThread({ id, title, metadata });
|
|
1538
|
-
}
|
|
1539
|
-
async deleteThread({ threadId }) {
|
|
1540
|
-
return this.stores.memory.deleteThread({ threadId });
|
|
1541
|
-
}
|
|
1542
|
-
async saveMessages(args) {
|
|
1543
|
-
return this.stores.memory.saveMessages(args);
|
|
1544
|
-
}
|
|
1545
|
-
async listMessagesById({ messageIds }) {
|
|
1546
|
-
return this.stores.memory.listMessagesById({ messageIds });
|
|
1547
|
-
}
|
|
1548
|
-
async updateWorkflowResults({
|
|
1549
|
-
workflowName,
|
|
1550
|
-
runId,
|
|
1551
|
-
stepId,
|
|
1552
|
-
result,
|
|
1553
|
-
requestContext
|
|
1554
|
-
}) {
|
|
1555
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
1556
|
-
}
|
|
1557
|
-
async updateWorkflowState({
|
|
1558
|
-
workflowName,
|
|
1559
|
-
runId,
|
|
1560
|
-
opts
|
|
1561
|
-
}) {
|
|
1562
|
-
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
1563
|
-
}
|
|
1564
|
-
async persistWorkflowSnapshot(params) {
|
|
1565
|
-
return this.stores.workflows.persistWorkflowSnapshot(params);
|
|
1566
|
-
}
|
|
1567
|
-
async loadWorkflowSnapshot(params) {
|
|
1568
|
-
return this.stores.workflows.loadWorkflowSnapshot(params);
|
|
1569
|
-
}
|
|
1570
|
-
async listWorkflowRuns(args = {}) {
|
|
1571
|
-
return this.stores.workflows.listWorkflowRuns(args);
|
|
1572
|
-
}
|
|
1573
|
-
async getWorkflowRunById({
|
|
1574
|
-
runId,
|
|
1575
|
-
workflowName
|
|
1576
|
-
}) {
|
|
1577
|
-
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
1578
|
-
}
|
|
1579
1734
|
async close() {
|
|
1580
1735
|
}
|
|
1581
|
-
async updateMessages(args) {
|
|
1582
|
-
return this.stores.memory.updateMessages(args);
|
|
1583
|
-
}
|
|
1584
|
-
async deleteMessages(messageIds) {
|
|
1585
|
-
return this.stores.memory.deleteMessages(messageIds);
|
|
1586
|
-
}
|
|
1587
|
-
async getResourceById({ resourceId }) {
|
|
1588
|
-
return this.stores.memory.getResourceById({ resourceId });
|
|
1589
|
-
}
|
|
1590
|
-
async saveResource({ resource }) {
|
|
1591
|
-
return this.stores.memory.saveResource({ resource });
|
|
1592
|
-
}
|
|
1593
|
-
async updateResource({
|
|
1594
|
-
resourceId,
|
|
1595
|
-
workingMemory,
|
|
1596
|
-
metadata
|
|
1597
|
-
}) {
|
|
1598
|
-
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
1599
|
-
}
|
|
1600
|
-
async getScoreById({ id: _id }) {
|
|
1601
|
-
return this.stores.scores.getScoreById({ id: _id });
|
|
1602
|
-
}
|
|
1603
|
-
async saveScore(score) {
|
|
1604
|
-
return this.stores.scores.saveScore(score);
|
|
1605
|
-
}
|
|
1606
|
-
async listScoresByRunId({
|
|
1607
|
-
runId,
|
|
1608
|
-
pagination
|
|
1609
|
-
}) {
|
|
1610
|
-
return this.stores.scores.listScoresByRunId({ runId, pagination });
|
|
1611
|
-
}
|
|
1612
|
-
async listScoresByEntityId({
|
|
1613
|
-
entityId,
|
|
1614
|
-
entityType,
|
|
1615
|
-
pagination
|
|
1616
|
-
}) {
|
|
1617
|
-
return this.stores.scores.listScoresByEntityId({
|
|
1618
|
-
entityId,
|
|
1619
|
-
entityType,
|
|
1620
|
-
pagination
|
|
1621
|
-
});
|
|
1622
|
-
}
|
|
1623
|
-
async listScoresByScorerId({
|
|
1624
|
-
scorerId,
|
|
1625
|
-
pagination,
|
|
1626
|
-
entityId,
|
|
1627
|
-
entityType,
|
|
1628
|
-
source
|
|
1629
|
-
}) {
|
|
1630
|
-
return this.stores.scores.listScoresByScorerId({ scorerId, pagination, entityId, entityType, source });
|
|
1631
|
-
}
|
|
1632
|
-
async listScoresBySpan({
|
|
1633
|
-
traceId,
|
|
1634
|
-
spanId,
|
|
1635
|
-
pagination
|
|
1636
|
-
}) {
|
|
1637
|
-
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
|
|
1638
|
-
}
|
|
1639
1736
|
};
|
|
1640
1737
|
var UpstashFilterTranslator = class extends BaseFilterTranslator {
|
|
1641
1738
|
getSupportedOperators() {
|
|
@@ -1873,7 +1970,7 @@ var UpstashVector = class extends MastraVector {
|
|
|
1873
1970
|
} catch (error) {
|
|
1874
1971
|
throw new MastraError(
|
|
1875
1972
|
{
|
|
1876
|
-
id: "
|
|
1973
|
+
id: createVectorErrorId("UPSTASH", "UPSERT", "FAILED"),
|
|
1877
1974
|
domain: ErrorDomain.STORAGE,
|
|
1878
1975
|
category: ErrorCategory.THIRD_PARTY,
|
|
1879
1976
|
details: { namespace, vectorCount: vectors.length }
|
|
@@ -1936,7 +2033,7 @@ var UpstashVector = class extends MastraVector {
|
|
|
1936
2033
|
} catch (error) {
|
|
1937
2034
|
throw new MastraError(
|
|
1938
2035
|
{
|
|
1939
|
-
id: "
|
|
2036
|
+
id: createVectorErrorId("UPSTASH", "QUERY", "FAILED"),
|
|
1940
2037
|
domain: ErrorDomain.STORAGE,
|
|
1941
2038
|
category: ErrorCategory.THIRD_PARTY,
|
|
1942
2039
|
details: { namespace, topK }
|
|
@@ -1956,7 +2053,7 @@ var UpstashVector = class extends MastraVector {
|
|
|
1956
2053
|
} catch (error) {
|
|
1957
2054
|
throw new MastraError(
|
|
1958
2055
|
{
|
|
1959
|
-
id: "
|
|
2056
|
+
id: createVectorErrorId("UPSTASH", "LIST_INDEXES", "FAILED"),
|
|
1960
2057
|
domain: ErrorDomain.STORAGE,
|
|
1961
2058
|
category: ErrorCategory.THIRD_PARTY
|
|
1962
2059
|
},
|
|
@@ -1981,7 +2078,7 @@ var UpstashVector = class extends MastraVector {
|
|
|
1981
2078
|
} catch (error) {
|
|
1982
2079
|
throw new MastraError(
|
|
1983
2080
|
{
|
|
1984
|
-
id: "
|
|
2081
|
+
id: createVectorErrorId("UPSTASH", "DESCRIBE_INDEX", "FAILED"),
|
|
1985
2082
|
domain: ErrorDomain.STORAGE,
|
|
1986
2083
|
category: ErrorCategory.THIRD_PARTY,
|
|
1987
2084
|
details: { namespace }
|
|
@@ -1999,9 +2096,14 @@ var UpstashVector = class extends MastraVector {
|
|
|
1999
2096
|
try {
|
|
2000
2097
|
await this.client.deleteNamespace(namespace);
|
|
2001
2098
|
} catch (error) {
|
|
2099
|
+
const errorMessage = error?.message || "";
|
|
2100
|
+
if (errorMessage.includes("does not exist") || errorMessage.includes("not found")) {
|
|
2101
|
+
this.logger.info(`Namespace ${namespace} does not exist, treating as already deleted`);
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2002
2104
|
throw new MastraError(
|
|
2003
2105
|
{
|
|
2004
|
-
id: "
|
|
2106
|
+
id: createVectorErrorId("UPSTASH", "DELETE_INDEX", "FAILED"),
|
|
2005
2107
|
domain: ErrorDomain.STORAGE,
|
|
2006
2108
|
category: ErrorCategory.THIRD_PARTY,
|
|
2007
2109
|
details: { namespace }
|
|
@@ -2011,47 +2113,124 @@ var UpstashVector = class extends MastraVector {
|
|
|
2011
2113
|
}
|
|
2012
2114
|
}
|
|
2013
2115
|
/**
|
|
2014
|
-
* Updates a vector by its ID
|
|
2015
|
-
* @param
|
|
2016
|
-
* @param
|
|
2017
|
-
* @param
|
|
2018
|
-
* @param
|
|
2019
|
-
* @param update
|
|
2116
|
+
* Updates a vector by its ID or multiple vectors matching a filter.
|
|
2117
|
+
* @param params - Parameters containing the id or filter for targeting the vector(s) to update
|
|
2118
|
+
* @param params.indexName - The name of the namespace containing the vector.
|
|
2119
|
+
* @param params.id - The ID of the vector to update (mutually exclusive with filter).
|
|
2120
|
+
* @param params.filter - Filter to match multiple vectors to update (mutually exclusive with id).
|
|
2121
|
+
* @param params.update - An object containing the vector and/or metadata to update.
|
|
2020
2122
|
* @returns A promise that resolves when the update is complete.
|
|
2021
2123
|
* @throws Will throw an error if no updates are provided or if the update operation fails.
|
|
2022
2124
|
*/
|
|
2023
|
-
async updateVector(
|
|
2024
|
-
|
|
2125
|
+
async updateVector(params) {
|
|
2126
|
+
const { indexName: namespace, update } = params;
|
|
2127
|
+
const upstashUpdate = update;
|
|
2128
|
+
const sparseVector = upstashUpdate.sparseVector;
|
|
2129
|
+
if ("id" in params && params.id && "filter" in params && params.filter) {
|
|
2130
|
+
throw new MastraError({
|
|
2131
|
+
id: createVectorErrorId("UPSTASH", "UPDATE_VECTOR", "MUTUALLY_EXCLUSIVE"),
|
|
2132
|
+
text: "Cannot specify both id and filter - they are mutually exclusive",
|
|
2133
|
+
domain: ErrorDomain.STORAGE,
|
|
2134
|
+
category: ErrorCategory.USER,
|
|
2135
|
+
details: { namespace }
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
if (!("id" in params && params.id) && !("filter" in params && params.filter)) {
|
|
2139
|
+
throw new MastraError({
|
|
2140
|
+
id: createVectorErrorId("UPSTASH", "UPDATE_VECTOR", "NO_TARGET"),
|
|
2141
|
+
text: "Either id or filter must be provided",
|
|
2142
|
+
domain: ErrorDomain.STORAGE,
|
|
2143
|
+
category: ErrorCategory.USER,
|
|
2144
|
+
details: { namespace }
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
if (!update.vector && !update.metadata && !sparseVector) {
|
|
2025
2148
|
throw new MastraError({
|
|
2026
|
-
id: "
|
|
2149
|
+
id: createVectorErrorId("UPSTASH", "UPDATE_VECTOR", "NO_PAYLOAD"),
|
|
2150
|
+
text: "No update data provided",
|
|
2027
2151
|
domain: ErrorDomain.STORAGE,
|
|
2028
|
-
category: ErrorCategory.
|
|
2029
|
-
details: { namespace
|
|
2030
|
-
text: "No update data provided"
|
|
2152
|
+
category: ErrorCategory.USER,
|
|
2153
|
+
details: { namespace }
|
|
2031
2154
|
});
|
|
2032
2155
|
}
|
|
2033
|
-
if (
|
|
2156
|
+
if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
|
|
2034
2157
|
throw new MastraError({
|
|
2035
|
-
id: "
|
|
2158
|
+
id: createVectorErrorId("UPSTASH", "UPDATE_VECTOR", "EMPTY_FILTER"),
|
|
2159
|
+
text: "Filter cannot be an empty filter object",
|
|
2036
2160
|
domain: ErrorDomain.STORAGE,
|
|
2037
|
-
category: ErrorCategory.
|
|
2038
|
-
details: { namespace
|
|
2039
|
-
text: "Both vector and metadata must be provided for an update"
|
|
2161
|
+
category: ErrorCategory.USER,
|
|
2162
|
+
details: { namespace }
|
|
2040
2163
|
});
|
|
2041
2164
|
}
|
|
2042
2165
|
try {
|
|
2043
|
-
const
|
|
2044
|
-
if (
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2166
|
+
const ns = this.client.namespace(namespace);
|
|
2167
|
+
if ("id" in params && params.id) {
|
|
2168
|
+
const points = { id: params.id };
|
|
2169
|
+
if (!update.vector || !update.metadata) {
|
|
2170
|
+
try {
|
|
2171
|
+
const existing = await ns.fetch([params.id], {
|
|
2172
|
+
includeVectors: true,
|
|
2173
|
+
includeMetadata: true
|
|
2174
|
+
});
|
|
2175
|
+
if (existing && existing.length > 0 && existing[0]) {
|
|
2176
|
+
if (!update.vector && existing[0]?.vector) {
|
|
2177
|
+
points.vector = existing[0].vector;
|
|
2178
|
+
}
|
|
2179
|
+
if (!update.metadata && existing[0]?.metadata) {
|
|
2180
|
+
points.metadata = existing[0].metadata;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
} catch (fetchError) {
|
|
2184
|
+
this.logger.warn(`Failed to fetch existing vector ${params.id} for partial update: ${fetchError}`);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
if (update.vector) points.vector = update.vector;
|
|
2188
|
+
if (update.metadata) points.metadata = update.metadata;
|
|
2189
|
+
if (sparseVector) points.sparseVector = sparseVector;
|
|
2190
|
+
await ns.upsert(points);
|
|
2191
|
+
} else if ("filter" in params && params.filter) {
|
|
2192
|
+
const filterString = this.transformFilter(params.filter);
|
|
2193
|
+
if (filterString) {
|
|
2194
|
+
const stats = await this.describeIndex({ indexName: namespace });
|
|
2195
|
+
const dummyVector = new Array(stats.dimension).fill(1 / Math.sqrt(stats.dimension));
|
|
2196
|
+
const needsVectors = !update.vector;
|
|
2197
|
+
const results = await ns.query({
|
|
2198
|
+
vector: dummyVector,
|
|
2199
|
+
topK: 1e3,
|
|
2200
|
+
// Upstash's max query limit
|
|
2201
|
+
filter: filterString,
|
|
2202
|
+
includeVectors: needsVectors,
|
|
2203
|
+
includeMetadata: needsVectors
|
|
2204
|
+
});
|
|
2205
|
+
for (const result of results) {
|
|
2206
|
+
const points = { id: `${result.id}` };
|
|
2207
|
+
if (update.vector) {
|
|
2208
|
+
points.vector = update.vector;
|
|
2209
|
+
} else if (result.vector) {
|
|
2210
|
+
points.vector = result.vector;
|
|
2211
|
+
}
|
|
2212
|
+
if (update.metadata) {
|
|
2213
|
+
points.metadata = update.metadata;
|
|
2214
|
+
} else if (result.metadata) {
|
|
2215
|
+
points.metadata = result.metadata;
|
|
2216
|
+
}
|
|
2217
|
+
if (sparseVector) points.sparseVector = sparseVector;
|
|
2218
|
+
await ns.upsert(points);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2048
2222
|
} catch (error) {
|
|
2223
|
+
if (error instanceof MastraError) throw error;
|
|
2049
2224
|
throw new MastraError(
|
|
2050
2225
|
{
|
|
2051
|
-
id: "
|
|
2226
|
+
id: createVectorErrorId("UPSTASH", "UPDATE_VECTOR", "FAILED"),
|
|
2052
2227
|
domain: ErrorDomain.STORAGE,
|
|
2053
2228
|
category: ErrorCategory.THIRD_PARTY,
|
|
2054
|
-
details: {
|
|
2229
|
+
details: {
|
|
2230
|
+
namespace,
|
|
2231
|
+
..."id" in params && params.id && { id: params.id },
|
|
2232
|
+
..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) }
|
|
2233
|
+
}
|
|
2055
2234
|
},
|
|
2056
2235
|
error
|
|
2057
2236
|
);
|
|
@@ -2066,22 +2245,109 @@ var UpstashVector = class extends MastraVector {
|
|
|
2066
2245
|
*/
|
|
2067
2246
|
async deleteVector({ indexName: namespace, id }) {
|
|
2068
2247
|
try {
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
});
|
|
2248
|
+
const ns = this.client.namespace(namespace);
|
|
2249
|
+
await ns.delete(id);
|
|
2072
2250
|
} catch (error) {
|
|
2073
2251
|
const mastraError = new MastraError(
|
|
2074
2252
|
{
|
|
2075
|
-
id: "
|
|
2253
|
+
id: createVectorErrorId("UPSTASH", "DELETE_VECTOR", "FAILED"),
|
|
2076
2254
|
domain: ErrorDomain.STORAGE,
|
|
2077
2255
|
category: ErrorCategory.THIRD_PARTY,
|
|
2078
|
-
details: {
|
|
2256
|
+
details: {
|
|
2257
|
+
namespace,
|
|
2258
|
+
...id && { id }
|
|
2259
|
+
}
|
|
2079
2260
|
},
|
|
2080
2261
|
error
|
|
2081
2262
|
);
|
|
2082
2263
|
this.logger?.error(mastraError.toString());
|
|
2083
2264
|
}
|
|
2084
2265
|
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Deletes multiple vectors by IDs or filter.
|
|
2268
|
+
* @param indexName - The name of the namespace containing the vectors.
|
|
2269
|
+
* @param ids - Array of vector IDs to delete (mutually exclusive with filter).
|
|
2270
|
+
* @param filter - Filter to match vectors to delete (mutually exclusive with ids).
|
|
2271
|
+
* @returns A promise that resolves when the deletion is complete.
|
|
2272
|
+
* @throws Will throw an error if both ids and filter are provided, or if neither is provided.
|
|
2273
|
+
*/
|
|
2274
|
+
async deleteVectors({ indexName: namespace, filter, ids }) {
|
|
2275
|
+
if (ids && filter) {
|
|
2276
|
+
throw new MastraError({
|
|
2277
|
+
id: createVectorErrorId("UPSTASH", "DELETE_VECTORS", "MUTUALLY_EXCLUSIVE"),
|
|
2278
|
+
text: "Cannot specify both ids and filter - they are mutually exclusive",
|
|
2279
|
+
domain: ErrorDomain.STORAGE,
|
|
2280
|
+
category: ErrorCategory.USER,
|
|
2281
|
+
details: { namespace }
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
if (!ids && !filter) {
|
|
2285
|
+
throw new MastraError({
|
|
2286
|
+
id: createVectorErrorId("UPSTASH", "DELETE_VECTORS", "NO_TARGET"),
|
|
2287
|
+
text: "Either filter or ids must be provided",
|
|
2288
|
+
domain: ErrorDomain.STORAGE,
|
|
2289
|
+
category: ErrorCategory.USER,
|
|
2290
|
+
details: { namespace }
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
if (ids && ids.length === 0) {
|
|
2294
|
+
throw new MastraError({
|
|
2295
|
+
id: createVectorErrorId("UPSTASH", "DELETE_VECTORS", "EMPTY_IDS"),
|
|
2296
|
+
text: "Cannot delete with empty ids array",
|
|
2297
|
+
domain: ErrorDomain.STORAGE,
|
|
2298
|
+
category: ErrorCategory.USER,
|
|
2299
|
+
details: { namespace }
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
if (filter && Object.keys(filter).length === 0) {
|
|
2303
|
+
throw new MastraError({
|
|
2304
|
+
id: createVectorErrorId("UPSTASH", "DELETE_VECTORS", "EMPTY_FILTER"),
|
|
2305
|
+
text: "Cannot delete with empty filter object",
|
|
2306
|
+
domain: ErrorDomain.STORAGE,
|
|
2307
|
+
category: ErrorCategory.USER,
|
|
2308
|
+
details: { namespace }
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2311
|
+
try {
|
|
2312
|
+
const ns = this.client.namespace(namespace);
|
|
2313
|
+
if (ids) {
|
|
2314
|
+
await ns.delete(ids);
|
|
2315
|
+
} else if (filter) {
|
|
2316
|
+
const filterString = this.transformFilter(filter);
|
|
2317
|
+
if (filterString) {
|
|
2318
|
+
const stats = await this.describeIndex({ indexName: namespace });
|
|
2319
|
+
const dummyVector = new Array(stats.dimension).fill(1 / Math.sqrt(stats.dimension));
|
|
2320
|
+
const results = await ns.query({
|
|
2321
|
+
vector: dummyVector,
|
|
2322
|
+
topK: 1e3,
|
|
2323
|
+
// Upstash's max query limit
|
|
2324
|
+
filter: filterString,
|
|
2325
|
+
includeVectors: false,
|
|
2326
|
+
includeMetadata: false
|
|
2327
|
+
});
|
|
2328
|
+
const idsToDelete = results.map((r) => `${r.id}`);
|
|
2329
|
+
if (idsToDelete.length > 0) {
|
|
2330
|
+
await ns.delete(idsToDelete);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
} catch (error) {
|
|
2335
|
+
if (error instanceof MastraError) throw error;
|
|
2336
|
+
throw new MastraError(
|
|
2337
|
+
{
|
|
2338
|
+
id: createVectorErrorId("UPSTASH", "DELETE_VECTORS", "FAILED"),
|
|
2339
|
+
domain: ErrorDomain.STORAGE,
|
|
2340
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2341
|
+
details: {
|
|
2342
|
+
namespace,
|
|
2343
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
2344
|
+
...ids && { idsCount: ids.length }
|
|
2345
|
+
}
|
|
2346
|
+
},
|
|
2347
|
+
error
|
|
2348
|
+
);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2085
2351
|
};
|
|
2086
2352
|
|
|
2087
2353
|
// src/vector/prompt.ts
|
|
@@ -2159,6 +2425,6 @@ Example Complex Query:
|
|
|
2159
2425
|
]
|
|
2160
2426
|
}`;
|
|
2161
2427
|
|
|
2162
|
-
export { UPSTASH_PROMPT, UpstashStore, UpstashVector };
|
|
2428
|
+
export { ScoresUpstash, StoreMemoryUpstash, UPSTASH_PROMPT, UpstashStore, UpstashVector, WorkflowsUpstash };
|
|
2163
2429
|
//# sourceMappingURL=index.js.map
|
|
2164
2430
|
//# sourceMappingURL=index.js.map
|