@mastra/cloudflare 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-transpile-packages-20250724123433

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,391 +1,581 @@
1
1
  'use strict';
2
2
 
3
- var agent = require('@mastra/core/agent');
3
+ var error = require('@mastra/core/error');
4
4
  var storage = require('@mastra/core/storage');
5
5
  var Cloudflare = require('cloudflare');
6
+ var agent = require('@mastra/core/agent');
6
7
 
7
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
9
 
9
10
  var Cloudflare__default = /*#__PURE__*/_interopDefault(Cloudflare);
10
11
 
11
12
  // src/storage/index.ts
12
-
13
- // src/storage/types.ts
14
- function isWorkersConfig(config) {
15
- return "bindings" in config;
16
- }
17
-
18
- // src/storage/index.ts
19
- var CloudflareStore = class extends storage.MastraStorage {
20
- client;
21
- accountId;
22
- namespacePrefix;
23
- bindings;
24
- validateWorkersConfig(config) {
25
- if (!isWorkersConfig(config)) {
26
- throw new Error("Invalid Workers API configuration");
27
- }
28
- if (!config.bindings) {
29
- throw new Error("KV bindings are required when using Workers Binding API");
30
- }
31
- const requiredTables = [storage.TABLE_THREADS, storage.TABLE_MESSAGES, storage.TABLE_WORKFLOW_SNAPSHOT, storage.TABLE_EVALS, storage.TABLE_TRACES];
32
- for (const table of requiredTables) {
33
- if (!(table in config.bindings)) {
34
- throw new Error(`Missing KV binding for table: ${table}`);
35
- }
36
- }
13
+ var LegacyEvalsStorageCloudflare = class extends storage.LegacyEvalsStorage {
14
+ operations;
15
+ constructor({ operations }) {
16
+ super();
17
+ this.operations = operations;
37
18
  }
38
- validateRestConfig(config) {
39
- if (isWorkersConfig(config)) {
40
- throw new Error("Invalid REST API configuration");
41
- }
42
- if (!config.accountId?.trim()) {
43
- throw new Error("accountId is required for REST API");
44
- }
45
- if (!config.apiToken?.trim()) {
46
- throw new Error("apiToken is required for REST API");
19
+ async getEvalsByAgentName(agentName, type) {
20
+ try {
21
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
22
+ const keyObjs = await this.operations.listKV(storage.TABLE_EVALS, { prefix: `${prefix}${storage.TABLE_EVALS}` });
23
+ const evals = [];
24
+ for (const { name: key } of keyObjs) {
25
+ const data = await this.operations.getKV(storage.TABLE_EVALS, key);
26
+ if (!data) continue;
27
+ if (data.agent_name !== agentName) continue;
28
+ if (type) {
29
+ const isTest = data.test_info !== null && data.test_info !== void 0;
30
+ const evalType = isTest ? "test" : "live";
31
+ if (evalType !== type) continue;
32
+ }
33
+ const mappedData = {
34
+ ...data,
35
+ runId: data.run_id,
36
+ testInfo: data.test_info
37
+ };
38
+ evals.push(mappedData);
39
+ }
40
+ evals.sort((a, b) => {
41
+ const aTime = new Date(a.createdAt || 0).getTime();
42
+ const bTime = new Date(b.createdAt || 0).getTime();
43
+ return bTime - aTime;
44
+ });
45
+ return evals;
46
+ } catch (error$1) {
47
+ throw new error.MastraError(
48
+ {
49
+ id: "CLOUDFLARE_STORAGE_GET_EVALS_BY_AGENT_NAME_FAILED",
50
+ domain: error.ErrorDomain.STORAGE,
51
+ category: error.ErrorCategory.THIRD_PARTY,
52
+ text: "Failed to get evals by agent name"
53
+ },
54
+ error$1
55
+ );
47
56
  }
48
57
  }
49
- constructor(config) {
50
- super({ name: "Cloudflare" });
58
+ async getEvals(options) {
51
59
  try {
52
- if (isWorkersConfig(config)) {
53
- this.validateWorkersConfig(config);
54
- this.bindings = config.bindings;
55
- this.namespacePrefix = config.keyPrefix?.trim() || "";
56
- this.logger.info("Using Cloudflare KV Workers Binding API");
57
- } else {
58
- this.validateRestConfig(config);
59
- this.accountId = config.accountId.trim();
60
- this.namespacePrefix = config.namespacePrefix?.trim() || "";
61
- this.client = new Cloudflare__default.default({
62
- apiToken: config.apiToken.trim()
63
- });
64
- this.logger.info("Using Cloudflare KV REST API");
60
+ const { agentName, type, page = 0, perPage = 100, dateRange } = options;
61
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
62
+ const keyObjs = await this.operations.listKV(storage.TABLE_EVALS, { prefix: `${prefix}${storage.TABLE_EVALS}` });
63
+ const evals = [];
64
+ for (const { name: key } of keyObjs) {
65
+ const data = await this.operations.getKV(storage.TABLE_EVALS, key);
66
+ if (!data) continue;
67
+ if (agentName && data.agent_name !== agentName) continue;
68
+ if (type) {
69
+ const isTest = data.test_info !== null && data.test_info !== void 0;
70
+ const evalType = isTest ? "test" : "live";
71
+ if (evalType !== type) continue;
72
+ }
73
+ if (dateRange?.start || dateRange?.end) {
74
+ const evalDate = new Date(data.createdAt || data.created_at || 0);
75
+ if (dateRange.start && evalDate < dateRange.start) continue;
76
+ if (dateRange.end && evalDate > dateRange.end) continue;
77
+ }
78
+ const mappedData = {
79
+ ...data,
80
+ runId: data.run_id,
81
+ testInfo: data.test_info
82
+ };
83
+ evals.push(mappedData);
65
84
  }
66
- } catch (error) {
67
- const message = error instanceof Error ? error.message : String(error);
68
- this.logger.error("Failed to initialize CloudflareStore:", { message });
69
- throw error;
85
+ evals.sort((a, b) => {
86
+ const aTime = new Date(a.createdAt || 0).getTime();
87
+ const bTime = new Date(b.createdAt || 0).getTime();
88
+ return bTime - aTime;
89
+ });
90
+ const start = page * perPage;
91
+ const end = start + perPage;
92
+ const paginatedEvals = evals.slice(start, end);
93
+ return {
94
+ page,
95
+ perPage,
96
+ total: evals.length,
97
+ hasMore: start + perPage < evals.length,
98
+ evals: paginatedEvals
99
+ };
100
+ } catch (error$1) {
101
+ throw new error.MastraError(
102
+ {
103
+ id: "CLOUDFLARE_STORAGE_GET_EVALS_FAILED",
104
+ domain: error.ErrorDomain.STORAGE,
105
+ category: error.ErrorCategory.THIRD_PARTY,
106
+ text: "Failed to get evals"
107
+ },
108
+ error$1
109
+ );
70
110
  }
71
111
  }
72
- getBinding(tableName) {
73
- if (!this.bindings) {
74
- throw new Error(`Cannot use Workers API binding for ${tableName}: Store initialized with REST API configuration`);
75
- }
76
- const binding = this.bindings[tableName];
77
- if (!binding) throw new Error(`No binding found for namespace ${tableName}`);
78
- return binding;
112
+ };
113
+ var MemoryStorageCloudflare = class extends storage.MemoryStorage {
114
+ operations;
115
+ constructor({ operations }) {
116
+ super();
117
+ this.operations = operations;
79
118
  }
80
- async listNamespaces() {
81
- if (this.bindings) {
119
+ ensureMetadata(metadata) {
120
+ if (!metadata) return void 0;
121
+ return typeof metadata === "string" ? JSON.parse(metadata) : metadata;
122
+ }
123
+ async getThreadById({ threadId }) {
124
+ const thread = await this.operations.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
125
+ if (!thread) return null;
126
+ try {
82
127
  return {
83
- result: Object.keys(this.bindings).map((name) => ({
84
- id: name,
85
- title: name,
86
- supports_url_encoding: true
87
- }))
128
+ ...thread,
129
+ createdAt: storage.ensureDate(thread.createdAt),
130
+ updatedAt: storage.ensureDate(thread.updatedAt),
131
+ metadata: this.ensureMetadata(thread.metadata)
88
132
  };
133
+ } catch (error$1) {
134
+ const mastraError = new error.MastraError(
135
+ {
136
+ id: "CLOUDFLARE_STORAGE_GET_THREAD_BY_ID_FAILED",
137
+ domain: error.ErrorDomain.STORAGE,
138
+ category: error.ErrorCategory.THIRD_PARTY,
139
+ details: {
140
+ threadId
141
+ }
142
+ },
143
+ error$1
144
+ );
145
+ this.logger?.trackException(mastraError);
146
+ this.logger?.error(mastraError.toString());
147
+ return null;
89
148
  }
90
- let allNamespaces = [];
91
- let currentPage = 1;
92
- const perPage = 50;
93
- let morePagesExist = true;
94
- while (morePagesExist) {
95
- const response = await this.client.kv.namespaces.list({
96
- account_id: this.accountId,
97
- page: currentPage,
98
- per_page: perPage
99
- });
100
- if (response.result) {
101
- allNamespaces = allNamespaces.concat(response.result);
102
- }
103
- morePagesExist = response.result ? response.result.length === perPage : false;
104
- if (morePagesExist) {
105
- currentPage++;
106
- }
107
- }
108
- return { result: allNamespaces };
109
149
  }
110
- async getNamespaceValue(tableName, key) {
150
+ async getThreadsByResourceId({ resourceId }) {
111
151
  try {
112
- if (this.bindings) {
113
- const binding = this.getBinding(tableName);
114
- const result = await binding.getWithMetadata(key, "text");
115
- if (!result) return null;
116
- return JSON.stringify(result);
117
- } else {
118
- const namespaceId = await this.getNamespaceId(tableName);
119
- const response = await this.client.kv.namespaces.values.get(namespaceId, key, {
120
- account_id: this.accountId
121
- });
122
- return await response.text();
123
- }
124
- } catch (error) {
125
- if (error.message && error.message.includes("key not found")) {
126
- return null;
127
- }
128
- const message = error instanceof Error ? error.message : String(error);
129
- this.logger.error(`Failed to get value for ${tableName} ${key}:`, { message });
130
- throw error;
152
+ const keyList = await this.operations.listKV(storage.TABLE_THREADS);
153
+ const threads = await Promise.all(
154
+ keyList.map(async (keyObj) => {
155
+ try {
156
+ const data = await this.operations.getKV(storage.TABLE_THREADS, keyObj.name);
157
+ if (!data) return null;
158
+ const thread = typeof data === "string" ? JSON.parse(data) : data;
159
+ if (!thread || !thread.resourceId || thread.resourceId !== resourceId) return null;
160
+ return {
161
+ ...thread,
162
+ createdAt: storage.ensureDate(thread.createdAt),
163
+ updatedAt: storage.ensureDate(thread.updatedAt),
164
+ metadata: this.ensureMetadata(thread.metadata)
165
+ };
166
+ } catch (error$1) {
167
+ const mastraError = new error.MastraError(
168
+ {
169
+ id: "CLOUDFLARE_STORAGE_GET_THREADS_BY_RESOURCE_ID_FAILED",
170
+ domain: error.ErrorDomain.STORAGE,
171
+ category: error.ErrorCategory.THIRD_PARTY,
172
+ details: {
173
+ resourceId
174
+ }
175
+ },
176
+ error$1
177
+ );
178
+ this.logger?.trackException(mastraError);
179
+ this.logger?.error(mastraError.toString());
180
+ return null;
181
+ }
182
+ })
183
+ );
184
+ return threads.filter((thread) => thread !== null);
185
+ } catch (error$1) {
186
+ const mastraError = new error.MastraError(
187
+ {
188
+ id: "CLOUDFLARE_STORAGE_GET_THREADS_BY_RESOURCE_ID_FAILED",
189
+ domain: error.ErrorDomain.STORAGE,
190
+ category: error.ErrorCategory.THIRD_PARTY,
191
+ details: {
192
+ resourceId
193
+ }
194
+ },
195
+ error$1
196
+ );
197
+ this.logger?.trackException(mastraError);
198
+ this.logger?.error(mastraError.toString());
199
+ return [];
131
200
  }
132
201
  }
133
- async putNamespaceValue({
134
- tableName,
135
- key,
136
- value,
137
- metadata
138
- }) {
202
+ async getThreadsByResourceIdPaginated(args) {
139
203
  try {
140
- const serializedValue = this.safeSerialize(value);
141
- const serializedMetadata = metadata ? this.safeSerialize(metadata) : "";
142
- if (this.bindings) {
143
- const binding = this.getBinding(tableName);
144
- await binding.put(key, serializedValue, { metadata: serializedMetadata });
145
- } else {
146
- const namespaceId = await this.getNamespaceId(tableName);
147
- await this.client.kv.namespaces.values.update(namespaceId, key, {
148
- account_id: this.accountId,
149
- value: serializedValue,
150
- metadata: serializedMetadata
151
- });
204
+ const { resourceId, page = 0, perPage = 100 } = args;
205
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
206
+ const keyObjs = await this.operations.listKV(storage.TABLE_THREADS, { prefix: `${prefix}${storage.TABLE_THREADS}` });
207
+ const threads = [];
208
+ for (const { name: key } of keyObjs) {
209
+ const data = await this.operations.getKV(storage.TABLE_THREADS, key);
210
+ if (!data) continue;
211
+ if (data.resourceId !== resourceId) continue;
212
+ threads.push(data);
152
213
  }
153
- } catch (error) {
154
- const message = error instanceof Error ? error.message : String(error);
155
- this.logger.error(`Failed to put value for ${tableName} ${key}:`, { message });
156
- throw error;
157
- }
158
- }
159
- async deleteNamespaceValue(tableName, key) {
160
- if (this.bindings) {
161
- const binding = this.getBinding(tableName);
162
- await binding.delete(key);
163
- } else {
164
- const namespaceId = await this.getNamespaceId(tableName);
165
- await this.client.kv.namespaces.values.delete(namespaceId, key, {
166
- account_id: this.accountId
214
+ threads.sort((a, b) => {
215
+ const aTime = new Date(a.createdAt || 0).getTime();
216
+ const bTime = new Date(b.createdAt || 0).getTime();
217
+ return bTime - aTime;
167
218
  });
219
+ const start = page * perPage;
220
+ const end = start + perPage;
221
+ const paginatedThreads = threads.slice(start, end);
222
+ return {
223
+ page,
224
+ perPage,
225
+ total: threads.length,
226
+ hasMore: start + perPage < threads.length,
227
+ threads: paginatedThreads
228
+ };
229
+ } catch (error$1) {
230
+ throw new error.MastraError(
231
+ {
232
+ id: "CLOUDFLARE_STORAGE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
233
+ domain: error.ErrorDomain.STORAGE,
234
+ category: error.ErrorCategory.THIRD_PARTY,
235
+ text: "Failed to get threads by resource ID with pagination"
236
+ },
237
+ error$1
238
+ );
168
239
  }
169
240
  }
170
- async listNamespaceKeys(tableName, options) {
241
+ async saveThread({ thread }) {
171
242
  try {
172
- if (this.bindings) {
173
- const binding = this.getBinding(tableName);
174
- const response = await binding.list({
175
- limit: options?.limit || 1e3,
176
- prefix: options?.prefix
177
- });
178
- return response.keys;
179
- } else {
180
- const namespaceId = await this.getNamespaceId(tableName);
181
- const response = await this.client.kv.namespaces.keys.list(namespaceId, {
182
- account_id: this.accountId,
183
- limit: options?.limit || 1e3,
184
- prefix: options?.prefix
185
- });
186
- return response.result;
187
- }
188
- } catch (error) {
189
- this.logger.error(`Failed to list keys for ${tableName}:`, error);
190
- throw new Error(`Failed to list keys: ${error.message}`);
243
+ await this.operations.insert({ tableName: storage.TABLE_THREADS, record: thread });
244
+ return thread;
245
+ } catch (error$1) {
246
+ throw new error.MastraError(
247
+ {
248
+ id: "CLOUDFLARE_STORAGE_SAVE_THREAD_FAILED",
249
+ domain: error.ErrorDomain.STORAGE,
250
+ category: error.ErrorCategory.THIRD_PARTY,
251
+ details: {
252
+ threadId: thread.id
253
+ }
254
+ },
255
+ error$1
256
+ );
191
257
  }
192
258
  }
193
- async createNamespaceById(title) {
194
- if (this.bindings) {
195
- return {
196
- id: title,
197
- // Use title as ID since that's what we need
259
+ async updateThread({
260
+ id,
261
+ title,
262
+ metadata
263
+ }) {
264
+ try {
265
+ const thread = await this.getThreadById({ threadId: id });
266
+ if (!thread) {
267
+ throw new Error(`Thread ${id} not found`);
268
+ }
269
+ const updatedThread = {
270
+ ...thread,
198
271
  title,
199
- supports_url_encoding: true
272
+ metadata: this.ensureMetadata({
273
+ ...thread.metadata ?? {},
274
+ ...metadata
275
+ }),
276
+ updatedAt: /* @__PURE__ */ new Date()
200
277
  };
278
+ await this.operations.insert({ tableName: storage.TABLE_THREADS, record: updatedThread });
279
+ return updatedThread;
280
+ } catch (error$1) {
281
+ throw new error.MastraError(
282
+ {
283
+ id: "CLOUDFLARE_STORAGE_UPDATE_THREAD_FAILED",
284
+ domain: error.ErrorDomain.STORAGE,
285
+ category: error.ErrorCategory.THIRD_PARTY,
286
+ details: {
287
+ threadId: id,
288
+ title
289
+ }
290
+ },
291
+ error$1
292
+ );
201
293
  }
202
- return await this.client.kv.namespaces.create({
203
- account_id: this.accountId,
204
- title
205
- });
206
294
  }
207
- async getNamespaceIdByName(namespaceName) {
295
+ getMessageKey(threadId, messageId) {
208
296
  try {
209
- const response = await this.listNamespaces();
210
- const namespace = response.result.find((ns) => ns.title === namespaceName);
211
- return namespace ? namespace.id : null;
297
+ return this.operations.getKey(storage.TABLE_MESSAGES, { threadId, id: messageId });
212
298
  } catch (error) {
213
- this.logger.error(`Failed to get namespace ID for ${namespaceName}:`, error);
214
- return null;
299
+ const message = error instanceof Error ? error.message : String(error);
300
+ this.logger.error(`Error getting message key for thread ${threadId} and message ${messageId}:`, { message });
301
+ throw error;
215
302
  }
216
303
  }
217
- async createNamespace(namespaceName) {
304
+ getThreadMessagesKey(threadId) {
218
305
  try {
219
- const response = await this.createNamespaceById(namespaceName);
220
- return response.id;
306
+ return this.operations.getKey(storage.TABLE_MESSAGES, { threadId, id: "messages" });
221
307
  } catch (error) {
222
- if (error.message && error.message.includes("already exists")) {
223
- const namespaces = await this.listNamespaces();
224
- const namespace = namespaces.result.find((ns) => ns.title === namespaceName);
225
- if (namespace) return namespace.id;
226
- }
227
- this.logger.error("Error creating namespace:", error);
228
- throw new Error(`Failed to create namespace ${namespaceName}: ${error.message}`);
308
+ const message = error instanceof Error ? error.message : String(error);
309
+ this.logger.error(`Error getting thread messages key for thread ${threadId}:`, { message });
310
+ throw error;
229
311
  }
230
312
  }
231
- async getOrCreateNamespaceId(namespaceName) {
232
- let namespaceId = await this.getNamespaceIdByName(namespaceName);
233
- if (!namespaceId) {
234
- namespaceId = await this.createNamespace(namespaceName);
313
+ async deleteThread({ threadId }) {
314
+ try {
315
+ const thread = await this.getThreadById({ threadId });
316
+ if (!thread) {
317
+ throw new Error(`Thread ${threadId} not found`);
318
+ }
319
+ const messageKeys = await this.operations.listKV(storage.TABLE_MESSAGES);
320
+ const threadMessageKeys = messageKeys.filter((key) => key.name.includes(`${storage.TABLE_MESSAGES}:${threadId}:`));
321
+ await Promise.all([
322
+ // Delete message order
323
+ this.operations.deleteKV(storage.TABLE_MESSAGES, this.getThreadMessagesKey(threadId)),
324
+ // Delete all messages
325
+ ...threadMessageKeys.map((key) => this.operations.deleteKV(storage.TABLE_MESSAGES, key.name)),
326
+ // Delete thread
327
+ this.operations.deleteKV(storage.TABLE_THREADS, this.operations.getKey(storage.TABLE_THREADS, { id: threadId }))
328
+ ]);
329
+ } catch (error$1) {
330
+ throw new error.MastraError(
331
+ {
332
+ id: "CLOUDFLARE_STORAGE_DELETE_THREAD_FAILED",
333
+ domain: error.ErrorDomain.STORAGE,
334
+ category: error.ErrorCategory.THIRD_PARTY,
335
+ details: {
336
+ threadId
337
+ }
338
+ },
339
+ error$1
340
+ );
235
341
  }
236
- return namespaceId;
237
342
  }
238
- async getNamespaceId(tableName) {
239
- const prefix = this.namespacePrefix ? `${this.namespacePrefix}_` : "";
343
+ async findMessageInAnyThread(messageId) {
240
344
  try {
241
- const legacyNamespaceId = await this.checkLegacyNamespace(tableName, prefix);
242
- if (legacyNamespaceId) {
243
- return legacyNamespaceId;
345
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
346
+ const threadKeys = await this.operations.listKV(storage.TABLE_THREADS, { prefix: `${prefix}${storage.TABLE_THREADS}` });
347
+ for (const { name: threadKey } of threadKeys) {
348
+ const threadId = threadKey.split(":").pop();
349
+ if (!threadId || threadId === "messages") continue;
350
+ const messageKey = this.getMessageKey(threadId, messageId);
351
+ const message = await this.operations.getKV(storage.TABLE_MESSAGES, messageKey);
352
+ if (message) {
353
+ return { ...message, threadId };
354
+ }
244
355
  }
245
- return await this.getOrCreateNamespaceId(`${prefix}${tableName}`);
356
+ return null;
246
357
  } catch (error) {
247
- this.logger.error("Error fetching namespace ID:", error);
248
- throw new Error(`Failed to fetch namespace ID for table ${tableName}: ${error.message}`);
358
+ this.logger?.error(`Error finding message ${messageId} in any thread:`, error);
359
+ return null;
249
360
  }
250
361
  }
251
- LEGACY_NAMESPACE_MAP = {
252
- [storage.TABLE_MESSAGES]: storage.TABLE_THREADS,
253
- [storage.TABLE_WORKFLOW_SNAPSHOT]: "mastra_workflows",
254
- [storage.TABLE_TRACES]: storage.TABLE_EVALS
255
- };
256
362
  /**
257
- * There were a few legacy mappings for tables such as
258
- * - messages -> threads
259
- * - workflow_snapshot -> mastra_workflows
260
- * - traces -> evals
261
- * This has been updated to use dedicated namespaces for each table.
262
- * In the case of data for a table existing in the legacy namespace, warn the user to migrate to the new namespace.
263
- *
264
- * @param tableName The table name to check for legacy data
265
- * @param prefix The namespace prefix
266
- * @returns The legacy namespace ID if data exists; otherwise, null
363
+ * Queue for serializing sorted order updates.
364
+ * Updates the sorted order for a given key. This operation is eventually consistent.
267
365
  */
268
- async checkLegacyNamespace(tableName, prefix) {
269
- const legacyNamespaceBase = this.LEGACY_NAMESPACE_MAP[tableName];
270
- if (legacyNamespaceBase) {
271
- const legacyNamespace = `${prefix}${legacyNamespaceBase}`;
272
- const keyPrefix = this.namespacePrefix ? `${this.namespacePrefix}:` : "";
273
- const prefixKey = `${keyPrefix}${tableName}:`;
274
- const legacyId = await this.getNamespaceIdByName(legacyNamespace);
275
- if (legacyId) {
276
- const response = await this.client.kv.namespaces.keys.list(legacyId, {
277
- account_id: this.accountId,
278
- prefix: prefixKey
366
+ updateQueue = /* @__PURE__ */ new Map();
367
+ async updateSorting(threadMessages) {
368
+ return threadMessages.map((msg) => ({
369
+ message: msg,
370
+ // Use _index if available, otherwise timestamp, matching Upstash
371
+ score: msg._index !== void 0 ? msg._index : msg.createdAt.getTime()
372
+ })).sort((a, b) => a.score - b.score).map((item) => ({
373
+ id: item.message.id,
374
+ score: item.score
375
+ }));
376
+ }
377
+ /**
378
+ * Updates the sorted order for a given key. This operation is eventually consistent.
379
+ * Note: Operations on the same orderKey are serialized using a queue to prevent
380
+ * concurrent updates from conflicting with each other.
381
+ */
382
+ async updateSortedMessages(orderKey, newEntries) {
383
+ const currentPromise = this.updateQueue.get(orderKey) || Promise.resolve();
384
+ const nextPromise = currentPromise.then(async () => {
385
+ try {
386
+ const currentOrder = await this.getSortedMessages(orderKey);
387
+ const orderMap = new Map(currentOrder.map((entry) => [entry.id, entry]));
388
+ for (const entry of newEntries) {
389
+ orderMap.set(entry.id, entry);
390
+ }
391
+ const updatedOrder = Array.from(orderMap.values()).sort((a, b) => a.score - b.score);
392
+ await this.operations.putKV({
393
+ tableName: storage.TABLE_MESSAGES,
394
+ key: orderKey,
395
+ value: JSON.stringify(updatedOrder)
279
396
  });
280
- const keys = response.result;
281
- const hasTableData = keys.length > 0;
282
- if (hasTableData) {
283
- this.logger.warn(
284
- `Using legacy namespace "${legacyNamespace}" for ${tableName}. Consider migrating to a dedicated namespace "${prefix}${tableName}".`
285
- );
286
- return legacyId;
397
+ } catch (error) {
398
+ const message = error instanceof Error ? error.message : String(error);
399
+ this.logger.error(`Error updating sorted order for key ${orderKey}:`, { message });
400
+ throw error;
401
+ } finally {
402
+ if (this.updateQueue.get(orderKey) === nextPromise) {
403
+ this.updateQueue.delete(orderKey);
287
404
  }
288
405
  }
406
+ });
407
+ this.updateQueue.set(orderKey, nextPromise);
408
+ return nextPromise;
409
+ }
410
+ async getSortedMessages(orderKey) {
411
+ const raw = await this.operations.getKV(storage.TABLE_MESSAGES, orderKey);
412
+ if (!raw) return [];
413
+ try {
414
+ const arr = JSON.parse(typeof raw === "string" ? raw : JSON.stringify(raw));
415
+ return Array.isArray(arr) ? arr : [];
416
+ } catch (e) {
417
+ this.logger.error(`Error parsing order data for key ${orderKey}:`, { e });
418
+ return [];
289
419
  }
290
- return null;
291
420
  }
292
- /**
293
- * Helper to safely serialize data for KV storage
294
- */
295
- safeSerialize(data) {
296
- return typeof data === "string" ? data : JSON.stringify(data);
421
+ async migrateMessage(messageId, fromThreadId, toThreadId) {
422
+ try {
423
+ const oldMessageKey = this.getMessageKey(fromThreadId, messageId);
424
+ const message = await this.operations.getKV(storage.TABLE_MESSAGES, oldMessageKey);
425
+ if (!message) return;
426
+ const updatedMessage = {
427
+ ...message,
428
+ threadId: toThreadId
429
+ };
430
+ const newMessageKey = this.getMessageKey(toThreadId, messageId);
431
+ await this.operations.putKV({ tableName: storage.TABLE_MESSAGES, key: newMessageKey, value: updatedMessage });
432
+ const oldOrderKey = this.getThreadMessagesKey(fromThreadId);
433
+ const oldEntries = await this.getSortedMessages(oldOrderKey);
434
+ const filteredEntries = oldEntries.filter((entry) => entry.id !== messageId);
435
+ await this.updateSortedMessages(oldOrderKey, filteredEntries);
436
+ const newOrderKey = this.getThreadMessagesKey(toThreadId);
437
+ const newEntries = await this.getSortedMessages(newOrderKey);
438
+ const newEntry = { id: messageId, score: Date.now() };
439
+ newEntries.push(newEntry);
440
+ await this.updateSortedMessages(newOrderKey, newEntries);
441
+ await this.operations.deleteKV(storage.TABLE_MESSAGES, oldMessageKey);
442
+ } catch (error) {
443
+ this.logger?.error(`Error migrating message ${messageId} from ${fromThreadId} to ${toThreadId}:`, error);
444
+ throw error;
445
+ }
297
446
  }
298
- /**
299
- * Helper to safely parse data from KV storage
300
- */
301
- safeParse(text) {
302
- if (!text) return null;
447
+ async saveMessages(args) {
448
+ const { messages, format = "v1" } = args;
449
+ if (!Array.isArray(messages) || messages.length === 0) return [];
303
450
  try {
304
- const data = JSON.parse(text);
305
- if (data && typeof data === "object" && "value" in data) {
306
- if (typeof data.value === "string") {
451
+ const validatedMessages = messages.map((message, index) => {
452
+ const errors = [];
453
+ if (!message.id) errors.push("id is required");
454
+ if (!message.threadId) errors.push("threadId is required");
455
+ if (!message.content) errors.push("content is required");
456
+ if (!message.role) errors.push("role is required");
457
+ if (!message.createdAt) errors.push("createdAt is required");
458
+ if (message.resourceId === null || message.resourceId === void 0) errors.push("resourceId is required");
459
+ if (errors.length > 0) {
460
+ throw new Error(`Invalid message at index ${index}: ${errors.join(", ")}`);
461
+ }
462
+ return {
463
+ ...message,
464
+ createdAt: storage.ensureDate(message.createdAt),
465
+ type: message.type || "v2",
466
+ _index: index
467
+ };
468
+ }).filter((m) => !!m);
469
+ const messageMigrationTasks = [];
470
+ for (const message of validatedMessages) {
471
+ const existingMessage = await this.findMessageInAnyThread(message.id);
472
+ console.log(`Checking message ${message.id}: existing=${existingMessage?.threadId}, new=${message.threadId}`);
473
+ if (existingMessage && existingMessage.threadId && existingMessage.threadId !== message.threadId) {
474
+ console.log(`Migrating message ${message.id} from ${existingMessage.threadId} to ${message.threadId}`);
475
+ messageMigrationTasks.push(this.migrateMessage(message.id, existingMessage.threadId, message.threadId));
476
+ }
477
+ }
478
+ await Promise.all(messageMigrationTasks);
479
+ const messagesByThread = validatedMessages.reduce((acc, message) => {
480
+ if (message.threadId && !acc.has(message.threadId)) {
481
+ acc.set(message.threadId, []);
482
+ }
483
+ if (message.threadId) {
484
+ acc.get(message.threadId).push(message);
485
+ }
486
+ return acc;
487
+ }, /* @__PURE__ */ new Map());
488
+ await Promise.all(
489
+ Array.from(messagesByThread.entries()).map(async ([threadId, threadMessages]) => {
307
490
  try {
308
- return JSON.parse(data.value);
309
- } catch {
310
- return data.value;
491
+ const thread = await this.getThreadById({ threadId });
492
+ if (!thread) {
493
+ throw new Error(`Thread ${threadId} not found`);
494
+ }
495
+ await Promise.all(
496
+ threadMessages.map(async (message) => {
497
+ const key = this.getMessageKey(threadId, message.id);
498
+ const { _index, ...cleanMessage } = message;
499
+ const serializedMessage = {
500
+ ...cleanMessage,
501
+ createdAt: storage.serializeDate(cleanMessage.createdAt)
502
+ };
503
+ console.log(`Saving message ${message.id} with content:`, {
504
+ content: serializedMessage.content,
505
+ contentType: typeof serializedMessage.content,
506
+ isArray: Array.isArray(serializedMessage.content)
507
+ });
508
+ await this.operations.putKV({ tableName: storage.TABLE_MESSAGES, key, value: serializedMessage });
509
+ })
510
+ );
511
+ const orderKey = this.getThreadMessagesKey(threadId);
512
+ const entries = await this.updateSorting(threadMessages);
513
+ await this.updateSortedMessages(orderKey, entries);
514
+ const updatedThread = {
515
+ ...thread,
516
+ updatedAt: /* @__PURE__ */ new Date()
517
+ };
518
+ await this.operations.putKV({
519
+ tableName: storage.TABLE_THREADS,
520
+ key: this.operations.getKey(storage.TABLE_THREADS, { id: threadId }),
521
+ value: updatedThread
522
+ });
523
+ } catch (error$1) {
524
+ throw new error.MastraError(
525
+ {
526
+ id: "CLOUDFLARE_STORAGE_SAVE_MESSAGES_FAILED",
527
+ domain: error.ErrorDomain.STORAGE,
528
+ category: error.ErrorCategory.THIRD_PARTY,
529
+ details: {
530
+ threadId
531
+ }
532
+ },
533
+ error$1
534
+ );
311
535
  }
312
- }
313
- return null;
314
- }
315
- return data;
316
- } catch (error) {
317
- const message = error instanceof Error ? error.message : String(error);
318
- this.logger.error("Failed to parse text:", { message, text });
319
- return null;
320
- }
321
- }
322
- async putKV({
323
- tableName,
324
- key,
325
- value,
326
- metadata
327
- }) {
328
- try {
329
- await this.putNamespaceValue({ tableName, key, value, metadata });
330
- } catch (error) {
331
- this.logger.error(`Failed to put KV value for ${tableName}:${key}:`, error);
332
- throw new Error(`Failed to put KV value: ${error.message}`);
333
- }
334
- }
335
- async getKV(tableName, key) {
336
- try {
337
- const text = await this.getNamespaceValue(tableName, key);
338
- return this.safeParse(text);
339
- } catch (error) {
340
- this.logger.error(`Failed to get KV value for ${tableName}:${key}:`, error);
341
- throw new Error(`Failed to get KV value: ${error.message}`);
536
+ })
537
+ );
538
+ const prepared = validatedMessages.map(
539
+ ({ _index, ...message }) => ({ ...message, type: message.type !== "v2" ? message.type : void 0 })
540
+ );
541
+ const list = new agent.MessageList().add(prepared, "memory");
542
+ if (format === `v2`) return list.get.all.v2();
543
+ return list.get.all.v1();
544
+ } catch (error$1) {
545
+ throw new error.MastraError(
546
+ {
547
+ id: "CLOUDFLARE_STORAGE_SAVE_MESSAGES_FAILED",
548
+ domain: error.ErrorDomain.STORAGE,
549
+ category: error.ErrorCategory.THIRD_PARTY
550
+ },
551
+ error$1
552
+ );
342
553
  }
343
554
  }
344
- async deleteKV(tableName, key) {
345
- try {
346
- await this.deleteNamespaceValue(tableName, key);
347
- } catch (error) {
348
- this.logger.error(`Failed to delete KV value for ${tableName}:${key}:`, error);
349
- throw new Error(`Failed to delete KV value: ${error.message}`);
350
- }
555
+ async getRank(orderKey, id) {
556
+ const order = await this.getSortedMessages(orderKey);
557
+ const index = order.findIndex((item) => item.id === id);
558
+ return index >= 0 ? index : null;
351
559
  }
352
- async listKV(tableName, options) {
353
- try {
354
- return await this.listNamespaceKeys(tableName, options);
355
- } catch (error) {
356
- this.logger.error(`Failed to list KV for ${tableName}:`, error);
357
- throw new Error(`Failed to list KV: ${error.message}`);
358
- }
560
+ async getRange(orderKey, start, end) {
561
+ const order = await this.getSortedMessages(orderKey);
562
+ const actualStart = start < 0 ? Math.max(0, order.length + start) : start;
563
+ const actualEnd = end < 0 ? order.length + end : Math.min(end, order.length - 1);
564
+ const sliced = order.slice(actualStart, actualEnd + 1);
565
+ return sliced.map((item) => item.id);
359
566
  }
360
- /*---------------------------------------------------------------------------
361
- Sorted set simulation helpers for message ordering.
362
- We store an array of objects { id, score } as JSON under a dedicated key.
363
- ---------------------------------------------------------------------------*/
364
- async getSortedMessages(orderKey) {
365
- const raw = await this.getKV(storage.TABLE_MESSAGES, orderKey);
366
- if (!raw) return [];
367
- try {
368
- const arr = JSON.parse(typeof raw === "string" ? raw : JSON.stringify(raw));
369
- return Array.isArray(arr) ? arr : [];
370
- } catch (e) {
371
- this.logger.error(`Error parsing order data for key ${orderKey}:`, { e });
372
- return [];
373
- }
567
+ async getLastN(orderKey, n) {
568
+ return this.getRange(orderKey, -n, -1);
374
569
  }
375
- async updateSorting(threadMessages) {
376
- return threadMessages.map((msg) => ({
377
- message: msg,
378
- // Use _index if available, otherwise timestamp, matching Upstash
379
- score: msg._index !== void 0 ? msg._index : msg.createdAt.getTime()
380
- })).sort((a, b) => a.score - b.score).map((item) => ({
381
- id: item.message.id,
382
- score: item.score
383
- }));
570
+ async getFullOrder(orderKey) {
571
+ return this.getRange(orderKey, 0, -1);
384
572
  }
385
573
  async getIncludedMessagesWithContext(threadId, include, messageIds) {
386
- const threadMessagesKey = this.getThreadMessagesKey(threadId);
387
574
  await Promise.all(
388
575
  include.map(async (item) => {
576
+ const targetThreadId = item.threadId || threadId;
577
+ if (!targetThreadId) return;
578
+ const threadMessagesKey = this.getThreadMessagesKey(targetThreadId);
389
579
  messageIds.add(item.id);
390
580
  if (!item.withPreviousMessages && !item.withNextMessages) return;
391
581
  const rank = await this.getRank(threadMessagesKey, item.id);
@@ -415,14 +605,40 @@ var CloudflareStore = class extends storage.MastraStorage {
415
605
  console.log(`No message order found for thread ${threadId}, skipping latest messages`);
416
606
  }
417
607
  }
418
- async fetchAndParseMessages(threadId, messageIds) {
608
+ async fetchAndParseMessagesFromMultipleThreads(messageIds, include, targetThreadId) {
609
+ const messageIdToThreadId = /* @__PURE__ */ new Map();
610
+ if (include) {
611
+ for (const item of include) {
612
+ if (item.threadId) {
613
+ messageIdToThreadId.set(item.id, item.threadId);
614
+ }
615
+ }
616
+ }
419
617
  const messages = await Promise.all(
420
618
  messageIds.map(async (id) => {
421
619
  try {
620
+ let threadId = messageIdToThreadId.get(id);
621
+ if (!threadId) {
622
+ if (targetThreadId) {
623
+ threadId = targetThreadId;
624
+ } else {
625
+ const foundMessage = await this.findMessageInAnyThread(id);
626
+ if (foundMessage) {
627
+ threadId = foundMessage.threadId;
628
+ }
629
+ }
630
+ }
631
+ if (!threadId) return null;
422
632
  const key = this.getMessageKey(threadId, id);
423
- const data = await this.getKV(storage.TABLE_MESSAGES, key);
633
+ const data = await this.operations.getKV(storage.TABLE_MESSAGES, key);
424
634
  if (!data) return null;
425
- return typeof data === "string" ? JSON.parse(data) : data;
635
+ const parsed = typeof data === "string" ? JSON.parse(data) : data;
636
+ console.log(`Retrieved message ${id} from thread ${threadId} with content:`, {
637
+ content: parsed.content,
638
+ contentType: typeof parsed.content,
639
+ isArray: Array.isArray(parsed.content)
640
+ });
641
+ return parsed;
426
642
  } catch (error) {
427
643
  const message = error instanceof Error ? error.message : String(error);
428
644
  this.logger.error(`Error retrieving message ${id}:`, { message });
@@ -432,61 +648,389 @@ var CloudflareStore = class extends storage.MastraStorage {
432
648
  );
433
649
  return messages.filter((msg) => msg !== null);
434
650
  }
435
- /**
436
- * Queue for serializing sorted order updates.
437
- * Updates the sorted order for a given key. This operation is eventually consistent.
438
- */
439
- updateQueue = /* @__PURE__ */ new Map();
440
- /**
441
- * Updates the sorted order for a given key. This operation is eventually consistent.
442
- * Note: Operations on the same orderKey are serialized using a queue to prevent
443
- * concurrent updates from conflicting with each other.
444
- */
445
- async updateSortedMessages(orderKey, newEntries) {
446
- const currentPromise = this.updateQueue.get(orderKey) || Promise.resolve();
447
- const nextPromise = currentPromise.then(async () => {
651
+ async getMessages({
652
+ threadId,
653
+ resourceId,
654
+ selectBy,
655
+ format
656
+ }) {
657
+ console.log(`getMessages called with format: ${format}, threadId: ${threadId}`);
658
+ if (!threadId) throw new Error("threadId is required");
659
+ const actualFormat = format || "v1";
660
+ console.log(`Using format: ${actualFormat}`);
661
+ if (!threadId) throw new Error("threadId is required");
662
+ const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
663
+ const messageIds = /* @__PURE__ */ new Set();
664
+ if (limit === 0 && !selectBy?.include?.length) return [];
665
+ try {
666
+ await Promise.all([
667
+ selectBy?.include?.length ? this.getIncludedMessagesWithContext(threadId, selectBy.include, messageIds) : Promise.resolve(),
668
+ limit > 0 ? this.getRecentMessages(threadId, limit, messageIds) : Promise.resolve()
669
+ ]);
670
+ const targetThreadId = selectBy?.include?.length ? void 0 : threadId;
671
+ const messages = await this.fetchAndParseMessagesFromMultipleThreads(
672
+ Array.from(messageIds),
673
+ selectBy?.include,
674
+ targetThreadId
675
+ );
676
+ if (!messages.length) return [];
448
677
  try {
449
- const currentOrder = await this.getSortedMessages(orderKey);
450
- const orderMap = new Map(currentOrder.map((entry) => [entry.id, entry]));
451
- for (const entry of newEntries) {
452
- orderMap.set(entry.id, entry);
453
- }
454
- const updatedOrder = Array.from(orderMap.values()).sort((a, b) => a.score - b.score);
455
- await this.putKV({
456
- tableName: storage.TABLE_MESSAGES,
457
- key: orderKey,
458
- value: JSON.stringify(updatedOrder)
678
+ const threadMessagesKey = this.getThreadMessagesKey(threadId);
679
+ const messageOrder = await this.getFullOrder(threadMessagesKey);
680
+ const orderMap = new Map(messageOrder.map((id, index) => [id, index]));
681
+ messages.sort((a, b) => {
682
+ const indexA = orderMap.get(a.id);
683
+ const indexB = orderMap.get(b.id);
684
+ if (indexA !== void 0 && indexB !== void 0) return orderMap.get(a.id) - orderMap.get(b.id);
685
+ return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
459
686
  });
460
- } catch (error) {
461
- const message = error instanceof Error ? error.message : String(error);
462
- this.logger.error(`Error updating sorted order for key ${orderKey}:`, { message });
463
- throw error;
464
- } finally {
465
- if (this.updateQueue.get(orderKey) === nextPromise) {
466
- this.updateQueue.delete(orderKey);
687
+ } catch (error$1) {
688
+ const mastraError = new error.MastraError(
689
+ {
690
+ id: "CLOUDFLARE_STORAGE_SORT_MESSAGES_FAILED",
691
+ domain: error.ErrorDomain.STORAGE,
692
+ category: error.ErrorCategory.THIRD_PARTY,
693
+ text: `Error sorting messages for thread ${threadId} falling back to creation time`,
694
+ details: {
695
+ threadId
696
+ }
697
+ },
698
+ error$1
699
+ );
700
+ this.logger?.trackException(mastraError);
701
+ this.logger?.error(mastraError.toString());
702
+ messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
703
+ }
704
+ const prepared = messages.map(({ _index, ...message }) => ({
705
+ ...message,
706
+ type: message.type === `v2` ? void 0 : message.type,
707
+ createdAt: storage.ensureDate(message.createdAt)
708
+ }));
709
+ if (actualFormat === `v1`) {
710
+ console.log(`Processing ${prepared.length} messages for v1 format - returning directly without MessageList`);
711
+ return prepared.map((msg) => ({
712
+ ...msg,
713
+ createdAt: new Date(msg.createdAt)
714
+ }));
715
+ }
716
+ const list = new agent.MessageList({ threadId, resourceId }).add(prepared, "memory");
717
+ return list.get.all.v2();
718
+ } catch (error$1) {
719
+ const mastraError = new error.MastraError(
720
+ {
721
+ id: "CLOUDFLARE_STORAGE_GET_MESSAGES_FAILED",
722
+ domain: error.ErrorDomain.STORAGE,
723
+ category: error.ErrorCategory.THIRD_PARTY,
724
+ text: `Error retrieving messages for thread ${threadId}`,
725
+ details: {
726
+ threadId
727
+ }
728
+ },
729
+ error$1
730
+ );
731
+ this.logger?.trackException(mastraError);
732
+ this.logger?.error(mastraError.toString());
733
+ return [];
734
+ }
735
+ }
736
+ async getMessagesPaginated(args) {
737
+ try {
738
+ const { threadId, selectBy, format = "v1" } = args;
739
+ const { page = 0, perPage = 100 } = selectBy?.pagination || {};
740
+ const messages = format === "v2" ? await this.getMessages({ threadId, selectBy, format: "v2" }) : await this.getMessages({ threadId, selectBy, format: "v1" });
741
+ let filteredMessages = messages;
742
+ if (selectBy?.pagination?.dateRange) {
743
+ const { start: dateStart, end: dateEnd } = selectBy.pagination.dateRange;
744
+ filteredMessages = messages.filter((message) => {
745
+ const messageDate = new Date(message.createdAt);
746
+ if (dateStart && messageDate < dateStart) return false;
747
+ if (dateEnd && messageDate > dateEnd) return false;
748
+ return true;
749
+ });
750
+ }
751
+ const start = page * perPage;
752
+ const end = start + perPage;
753
+ const paginatedMessages = filteredMessages.slice(start, end);
754
+ return {
755
+ page,
756
+ perPage,
757
+ total: filteredMessages.length,
758
+ hasMore: start + perPage < filteredMessages.length,
759
+ messages: paginatedMessages
760
+ };
761
+ } catch (error$1) {
762
+ throw new error.MastraError(
763
+ {
764
+ id: "CLOUDFLARE_STORAGE_GET_MESSAGES_PAGINATED_FAILED",
765
+ domain: error.ErrorDomain.STORAGE,
766
+ category: error.ErrorCategory.THIRD_PARTY,
767
+ text: "Failed to get messages with pagination"
768
+ },
769
+ error$1
770
+ );
771
+ }
772
+ }
773
+ async updateMessages(args) {
774
+ try {
775
+ const { messages } = args;
776
+ const updatedMessages = [];
777
+ for (const messageUpdate of messages) {
778
+ const { id, content, ...otherFields } = messageUpdate;
779
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
780
+ const keyObjs = await this.operations.listKV(storage.TABLE_MESSAGES, { prefix: `${prefix}${storage.TABLE_MESSAGES}` });
781
+ let existingMessage = null;
782
+ let messageKey = "";
783
+ for (const { name: key } of keyObjs) {
784
+ const data = await this.operations.getKV(storage.TABLE_MESSAGES, key);
785
+ if (data && data.id === id) {
786
+ existingMessage = data;
787
+ messageKey = key;
788
+ break;
789
+ }
790
+ }
791
+ if (!existingMessage) {
792
+ continue;
793
+ }
794
+ const updatedMessage = {
795
+ ...existingMessage,
796
+ ...otherFields,
797
+ id
798
+ };
799
+ if (content) {
800
+ if (content.metadata !== void 0) {
801
+ updatedMessage.content = {
802
+ ...updatedMessage.content,
803
+ metadata: {
804
+ ...updatedMessage.content?.metadata,
805
+ ...content.metadata
806
+ }
807
+ };
808
+ }
809
+ if (content.content !== void 0) {
810
+ updatedMessage.content = {
811
+ ...updatedMessage.content,
812
+ content: content.content
813
+ };
814
+ }
815
+ }
816
+ if ("threadId" in messageUpdate && messageUpdate.threadId && messageUpdate.threadId !== existingMessage.threadId) {
817
+ await this.operations.deleteKV(storage.TABLE_MESSAGES, messageKey);
818
+ updatedMessage.threadId = messageUpdate.threadId;
819
+ const newMessageKey = this.getMessageKey(messageUpdate.threadId, id);
820
+ await this.operations.putKV({
821
+ tableName: storage.TABLE_MESSAGES,
822
+ key: newMessageKey,
823
+ value: updatedMessage
824
+ });
825
+ if (existingMessage.threadId) {
826
+ const sourceOrderKey = this.getThreadMessagesKey(existingMessage.threadId);
827
+ const sourceEntries = await this.getSortedMessages(sourceOrderKey);
828
+ const filteredEntries = sourceEntries.filter((entry) => entry.id !== id);
829
+ await this.updateSortedMessages(sourceOrderKey, filteredEntries);
830
+ }
831
+ const destOrderKey = this.getThreadMessagesKey(messageUpdate.threadId);
832
+ const destEntries = await this.getSortedMessages(destOrderKey);
833
+ const newEntry = { id, score: Date.now() };
834
+ destEntries.push(newEntry);
835
+ await this.updateSortedMessages(destOrderKey, destEntries);
836
+ } else {
837
+ await this.operations.putKV({
838
+ tableName: storage.TABLE_MESSAGES,
839
+ key: messageKey,
840
+ value: updatedMessage
841
+ });
842
+ }
843
+ const threadsToUpdate = /* @__PURE__ */ new Set();
844
+ if (updatedMessage.threadId) {
845
+ threadsToUpdate.add(updatedMessage.threadId);
846
+ }
847
+ if ("threadId" in messageUpdate && messageUpdate.threadId && messageUpdate.threadId !== existingMessage.threadId) {
848
+ if (existingMessage.threadId) {
849
+ threadsToUpdate.add(existingMessage.threadId);
850
+ }
851
+ threadsToUpdate.add(messageUpdate.threadId);
852
+ }
853
+ for (const threadId of threadsToUpdate) {
854
+ const thread = await this.getThreadById({ threadId });
855
+ if (thread) {
856
+ const updatedThread = {
857
+ ...thread,
858
+ updatedAt: /* @__PURE__ */ new Date()
859
+ };
860
+ await this.operations.putKV({
861
+ tableName: storage.TABLE_THREADS,
862
+ key: this.operations.getKey(storage.TABLE_THREADS, { id: threadId }),
863
+ value: updatedThread
864
+ });
865
+ }
467
866
  }
867
+ updatedMessages.push(updatedMessage);
468
868
  }
469
- });
470
- this.updateQueue.set(orderKey, nextPromise);
471
- return nextPromise;
869
+ return updatedMessages;
870
+ } catch (error$1) {
871
+ throw new error.MastraError(
872
+ {
873
+ id: "CLOUDFLARE_STORAGE_UPDATE_MESSAGES_FAILED",
874
+ domain: error.ErrorDomain.STORAGE,
875
+ category: error.ErrorCategory.THIRD_PARTY,
876
+ text: "Failed to update messages"
877
+ },
878
+ error$1
879
+ );
880
+ }
472
881
  }
473
- async getRank(orderKey, id) {
474
- const order = await this.getSortedMessages(orderKey);
475
- const index = order.findIndex((item) => item.id === id);
476
- return index >= 0 ? index : null;
882
+ async getResourceById({ resourceId }) {
883
+ try {
884
+ const data = await this.operations.getKV(storage.TABLE_RESOURCES, resourceId);
885
+ if (!data) return null;
886
+ const resource = typeof data === "string" ? JSON.parse(data) : data;
887
+ return {
888
+ ...resource,
889
+ createdAt: storage.ensureDate(resource.createdAt),
890
+ updatedAt: storage.ensureDate(resource.updatedAt),
891
+ metadata: this.ensureMetadata(resource.metadata)
892
+ };
893
+ } catch (error$1) {
894
+ const mastraError = new error.MastraError(
895
+ {
896
+ id: "CLOUDFLARE_STORAGE_GET_RESOURCE_BY_ID_FAILED",
897
+ domain: error.ErrorDomain.STORAGE,
898
+ category: error.ErrorCategory.THIRD_PARTY,
899
+ details: {
900
+ resourceId
901
+ }
902
+ },
903
+ error$1
904
+ );
905
+ this.logger?.trackException(mastraError);
906
+ this.logger?.error(mastraError.toString());
907
+ return null;
908
+ }
477
909
  }
478
- async getRange(orderKey, start, end) {
479
- const order = await this.getSortedMessages(orderKey);
480
- const actualStart = start < 0 ? Math.max(0, order.length + start) : start;
481
- const actualEnd = end < 0 ? order.length + end : Math.min(end, order.length - 1);
482
- const sliced = order.slice(actualStart, actualEnd + 1);
483
- return sliced.map((item) => item.id);
910
+ async saveResource({ resource }) {
911
+ try {
912
+ const resourceToSave = {
913
+ ...resource,
914
+ metadata: resource.metadata ? JSON.stringify(resource.metadata) : null
915
+ };
916
+ await this.operations.putKV({
917
+ tableName: storage.TABLE_RESOURCES,
918
+ key: resource.id,
919
+ value: resourceToSave
920
+ });
921
+ return resource;
922
+ } catch (error$1) {
923
+ throw new error.MastraError(
924
+ {
925
+ id: "CLOUDFLARE_STORAGE_SAVE_RESOURCE_FAILED",
926
+ domain: error.ErrorDomain.STORAGE,
927
+ category: error.ErrorCategory.THIRD_PARTY,
928
+ details: {
929
+ resourceId: resource.id
930
+ }
931
+ },
932
+ error$1
933
+ );
934
+ }
484
935
  }
485
- async getLastN(orderKey, n) {
486
- return this.getRange(orderKey, -n, -1);
936
+ async updateResource({
937
+ resourceId,
938
+ workingMemory,
939
+ metadata
940
+ }) {
941
+ const existingResource = await this.getResourceById({ resourceId });
942
+ if (!existingResource) {
943
+ const newResource = {
944
+ id: resourceId,
945
+ workingMemory,
946
+ metadata: metadata || {},
947
+ createdAt: /* @__PURE__ */ new Date(),
948
+ updatedAt: /* @__PURE__ */ new Date()
949
+ };
950
+ return this.saveResource({ resource: newResource });
951
+ }
952
+ const updatedAt = /* @__PURE__ */ new Date();
953
+ const updatedResource = {
954
+ ...existingResource,
955
+ workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
956
+ metadata: {
957
+ ...existingResource.metadata,
958
+ ...metadata
959
+ },
960
+ updatedAt
961
+ };
962
+ return this.saveResource({ resource: updatedResource });
487
963
  }
488
- async getFullOrder(orderKey) {
489
- return this.getRange(orderKey, 0, -1);
964
+ };
965
+ var StoreOperationsCloudflare = class extends storage.StoreOperations {
966
+ bindings;
967
+ client;
968
+ accountId;
969
+ namespacePrefix;
970
+ constructor({
971
+ namespacePrefix,
972
+ bindings,
973
+ client,
974
+ accountId
975
+ }) {
976
+ super();
977
+ this.bindings = bindings;
978
+ this.namespacePrefix = namespacePrefix;
979
+ this.client = client;
980
+ this.accountId = accountId;
981
+ }
982
+ async hasColumn() {
983
+ return true;
984
+ }
985
+ async alterTable(_args) {
986
+ }
987
+ async clearTable({ tableName }) {
988
+ try {
989
+ const keys = await this.listKV(tableName);
990
+ if (keys.length > 0) {
991
+ await Promise.all(keys.map((keyObj) => this.deleteKV(tableName, keyObj.name)));
992
+ }
993
+ } catch (error$1) {
994
+ throw new error.MastraError(
995
+ {
996
+ id: "CLOUDFLARE_STORAGE_CLEAR_TABLE_FAILED",
997
+ domain: error.ErrorDomain.STORAGE,
998
+ category: error.ErrorCategory.THIRD_PARTY,
999
+ details: {
1000
+ tableName
1001
+ }
1002
+ },
1003
+ error$1
1004
+ );
1005
+ }
1006
+ }
1007
+ async dropTable({ tableName }) {
1008
+ try {
1009
+ const keys = await this.listKV(tableName);
1010
+ if (keys.length > 0) {
1011
+ await Promise.all(keys.map((keyObj) => this.deleteKV(tableName, keyObj.name)));
1012
+ }
1013
+ } catch (error$1) {
1014
+ throw new error.MastraError(
1015
+ {
1016
+ id: "CLOUDFLARE_STORAGE_DROP_TABLE_FAILED",
1017
+ domain: error.ErrorDomain.STORAGE,
1018
+ category: error.ErrorCategory.THIRD_PARTY,
1019
+ details: {
1020
+ tableName
1021
+ }
1022
+ },
1023
+ error$1
1024
+ );
1025
+ }
1026
+ }
1027
+ getBinding(tableName) {
1028
+ if (!this.bindings) {
1029
+ throw new Error(`Cannot use Workers API binding for ${tableName}: Store initialized with REST API configuration`);
1030
+ }
1031
+ const binding = this.bindings[tableName];
1032
+ if (!binding) throw new Error(`No binding found for namespace ${tableName}`);
1033
+ return binding;
490
1034
  }
491
1035
  getKey(tableName, record) {
492
1036
  const prefix = this.namespacePrefix ? `${this.namespacePrefix}:` : "";
@@ -498,10 +1042,10 @@ var CloudflareStore = class extends storage.MastraStorage {
498
1042
  if (!record.threadId || !record.id) throw new Error("Thread ID and Message ID are required");
499
1043
  return `${prefix}${tableName}:${record.threadId}:${record.id}`;
500
1044
  case storage.TABLE_WORKFLOW_SNAPSHOT:
501
- if (!record.namespace || !record.workflow_name || !record.run_id) {
502
- throw new Error("Namespace, workflow name, and run ID are required");
1045
+ if (!record.workflow_name || !record.run_id) {
1046
+ throw new Error("Workflow name, and run ID are required");
503
1047
  }
504
- let key = `${prefix}${tableName}:${record.namespace}:${record.workflow_name}:${record.run_id}`;
1048
+ let key = `${prefix}${tableName}:${record.workflow_name}:${record.run_id}`;
505
1049
  if (record.resourceId) {
506
1050
  key = `${key}:${record.resourceId}`;
507
1051
  }
@@ -509,6 +1053,13 @@ var CloudflareStore = class extends storage.MastraStorage {
509
1053
  case storage.TABLE_TRACES:
510
1054
  if (!record.id) throw new Error("Trace ID is required");
511
1055
  return `${prefix}${tableName}:${record.id}`;
1056
+ case storage.TABLE_EVALS:
1057
+ const evalId = record.id || record.run_id;
1058
+ if (!evalId) throw new Error("Eval ID or run_id is required");
1059
+ return `${prefix}${tableName}:${evalId}`;
1060
+ case storage.TABLE_SCORERS:
1061
+ if (!record.id) throw new Error("Score ID is required");
1062
+ return `${prefix}${tableName}:${record.id}`;
512
1063
  default:
513
1064
  throw new Error(`Unsupported table: ${tableName}`);
514
1065
  }
@@ -517,6 +1068,146 @@ var CloudflareStore = class extends storage.MastraStorage {
517
1068
  const prefix = this.namespacePrefix ? `${this.namespacePrefix}:` : "";
518
1069
  return `${prefix}schema:${tableName}`;
519
1070
  }
1071
+ /**
1072
+ * Helper to safely parse data from KV storage
1073
+ */
1074
+ safeParse(text) {
1075
+ if (!text) return null;
1076
+ try {
1077
+ const data = JSON.parse(text);
1078
+ if (data && typeof data === "object" && "value" in data) {
1079
+ if (typeof data.value === "string") {
1080
+ try {
1081
+ return JSON.parse(data.value);
1082
+ } catch {
1083
+ return data.value;
1084
+ }
1085
+ }
1086
+ return null;
1087
+ }
1088
+ return data;
1089
+ } catch (error) {
1090
+ const message = error instanceof Error ? error.message : String(error);
1091
+ this.logger.error("Failed to parse text:", { message, text });
1092
+ return null;
1093
+ }
1094
+ }
1095
+ async createNamespaceById(title) {
1096
+ if (this.bindings) {
1097
+ return {
1098
+ id: title,
1099
+ // Use title as ID since that's what we need
1100
+ title,
1101
+ supports_url_encoding: true
1102
+ };
1103
+ }
1104
+ return await this.client.kv.namespaces.create({
1105
+ account_id: this.accountId,
1106
+ title
1107
+ });
1108
+ }
1109
+ async createNamespace(namespaceName) {
1110
+ try {
1111
+ const response = await this.createNamespaceById(namespaceName);
1112
+ return response.id;
1113
+ } catch (error) {
1114
+ if (error.message && error.message.includes("already exists")) {
1115
+ const namespaces = await this.listNamespaces();
1116
+ const namespace = namespaces.result.find((ns) => ns.title === namespaceName);
1117
+ if (namespace) return namespace.id;
1118
+ }
1119
+ this.logger.error("Error creating namespace:", error);
1120
+ throw new Error(`Failed to create namespace ${namespaceName}: ${error.message}`);
1121
+ }
1122
+ }
1123
+ async listNamespaces() {
1124
+ if (this.bindings) {
1125
+ return {
1126
+ result: Object.keys(this.bindings).map((name) => ({
1127
+ id: name,
1128
+ title: name,
1129
+ supports_url_encoding: true
1130
+ }))
1131
+ };
1132
+ }
1133
+ let allNamespaces = [];
1134
+ let currentPage = 1;
1135
+ const perPage = 50;
1136
+ let morePagesExist = true;
1137
+ while (morePagesExist) {
1138
+ const response = await this.client.kv.namespaces.list({
1139
+ account_id: this.accountId,
1140
+ page: currentPage,
1141
+ per_page: perPage
1142
+ });
1143
+ if (response.result) {
1144
+ allNamespaces = allNamespaces.concat(response.result);
1145
+ }
1146
+ morePagesExist = response.result ? response.result.length === perPage : false;
1147
+ if (morePagesExist) {
1148
+ currentPage++;
1149
+ }
1150
+ }
1151
+ return { result: allNamespaces };
1152
+ }
1153
+ async getNamespaceIdByName(namespaceName) {
1154
+ try {
1155
+ const response = await this.listNamespaces();
1156
+ const namespace = response.result.find((ns) => ns.title === namespaceName);
1157
+ return namespace ? namespace.id : null;
1158
+ } catch (error) {
1159
+ this.logger.error(`Failed to get namespace ID for ${namespaceName}:`, error);
1160
+ return null;
1161
+ }
1162
+ }
1163
+ async getOrCreateNamespaceId(namespaceName) {
1164
+ let namespaceId = await this.getNamespaceIdByName(namespaceName);
1165
+ if (!namespaceId) {
1166
+ namespaceId = await this.createNamespace(namespaceName);
1167
+ }
1168
+ return namespaceId;
1169
+ }
1170
+ async getNamespaceId(tableName) {
1171
+ const prefix = this.namespacePrefix ? `${this.namespacePrefix}_` : "";
1172
+ try {
1173
+ return await this.getOrCreateNamespaceId(`${prefix}${tableName}`);
1174
+ } catch (error) {
1175
+ this.logger.error("Error fetching namespace ID:", error);
1176
+ throw new Error(`Failed to fetch namespace ID for table ${tableName}: ${error.message}`);
1177
+ }
1178
+ }
1179
+ async getNamespaceValue(tableName, key) {
1180
+ try {
1181
+ if (this.bindings) {
1182
+ const binding = this.getBinding(tableName);
1183
+ const result = await binding.getWithMetadata(key, "text");
1184
+ if (!result) return null;
1185
+ return JSON.stringify(result);
1186
+ } else {
1187
+ const namespaceId = await this.getNamespaceId(tableName);
1188
+ const response = await this.client.kv.namespaces.values.get(namespaceId, key, {
1189
+ account_id: this.accountId
1190
+ });
1191
+ return await response.text();
1192
+ }
1193
+ } catch (error) {
1194
+ if (error.message && error.message.includes("key not found")) {
1195
+ return null;
1196
+ }
1197
+ const message = error instanceof Error ? error.message : String(error);
1198
+ this.logger.error(`Failed to get value for ${tableName} ${key}:`, { message });
1199
+ throw error;
1200
+ }
1201
+ }
1202
+ async getKV(tableName, key) {
1203
+ try {
1204
+ const text = await this.getNamespaceValue(tableName, key);
1205
+ return this.safeParse(text);
1206
+ } catch (error) {
1207
+ this.logger.error(`Failed to get KV value for ${tableName}:${key}:`, error);
1208
+ throw new Error(`Failed to get KV value: ${error.message}`);
1209
+ }
1210
+ }
520
1211
  async getTableSchema(tableName) {
521
1212
  try {
522
1213
  const schemaKey = this.getSchemaKey(tableName);
@@ -596,7 +1287,7 @@ var CloudflareStore = class extends storage.MastraStorage {
596
1287
  }
597
1288
  break;
598
1289
  case storage.TABLE_WORKFLOW_SNAPSHOT:
599
- if (!("namespace" in recordTyped) || !("workflow_name" in recordTyped) || !("run_id" in recordTyped)) {
1290
+ if (!("workflow_name" in recordTyped) || !("run_id" in recordTyped)) {
600
1291
  throw new Error("Workflow record missing required fields");
601
1292
  }
602
1293
  break;
@@ -605,6 +1296,16 @@ var CloudflareStore = class extends storage.MastraStorage {
605
1296
  throw new Error("Trace record missing required fields");
606
1297
  }
607
1298
  break;
1299
+ case storage.TABLE_EVALS:
1300
+ if (!("agent_name" in recordTyped) || !("run_id" in recordTyped)) {
1301
+ throw new Error("Eval record missing required fields");
1302
+ }
1303
+ break;
1304
+ case storage.TABLE_SCORERS:
1305
+ if (!("id" in recordTyped) || !("scorerId" in recordTyped)) {
1306
+ throw new Error("Score record missing required fields");
1307
+ }
1308
+ break;
608
1309
  default:
609
1310
  throw new Error(`Unknown table type: ${tableName}`);
610
1311
  }
@@ -614,19 +1315,139 @@ var CloudflareStore = class extends storage.MastraStorage {
614
1315
  throw error;
615
1316
  }
616
1317
  }
617
- ensureDate(date) {
618
- if (!date) return void 0;
619
- return date instanceof Date ? date : new Date(date);
620
- }
621
- serializeDate(date) {
622
- if (!date) return void 0;
623
- const dateObj = this.ensureDate(date);
624
- return dateObj?.toISOString();
1318
+ async insert({ tableName, record }) {
1319
+ try {
1320
+ const key = this.getKey(tableName, record);
1321
+ const processedRecord = {
1322
+ ...record,
1323
+ createdAt: record.createdAt ? storage.serializeDate(record.createdAt) : void 0,
1324
+ updatedAt: record.updatedAt ? storage.serializeDate(record.updatedAt) : void 0,
1325
+ metadata: record.metadata ? JSON.stringify(record.metadata) : ""
1326
+ };
1327
+ await this.validateRecord(processedRecord, tableName);
1328
+ await this.putKV({ tableName, key, value: processedRecord });
1329
+ } catch (error$1) {
1330
+ throw new error.MastraError(
1331
+ {
1332
+ id: "CLOUDFLARE_STORAGE_INSERT_FAILED",
1333
+ domain: error.ErrorDomain.STORAGE,
1334
+ category: error.ErrorCategory.THIRD_PARTY,
1335
+ details: {
1336
+ tableName
1337
+ }
1338
+ },
1339
+ error$1
1340
+ );
1341
+ }
625
1342
  }
626
1343
  ensureMetadata(metadata) {
627
1344
  if (!metadata) return {};
628
1345
  return typeof metadata === "string" ? JSON.parse(metadata) : metadata;
629
1346
  }
1347
+ async load({ tableName, keys }) {
1348
+ try {
1349
+ const key = this.getKey(tableName, keys);
1350
+ const data = await this.getKV(tableName, key);
1351
+ if (!data) return null;
1352
+ const processed = {
1353
+ ...data,
1354
+ createdAt: storage.ensureDate(data.createdAt),
1355
+ updatedAt: storage.ensureDate(data.updatedAt),
1356
+ metadata: this.ensureMetadata(data.metadata)
1357
+ };
1358
+ return processed;
1359
+ } catch (error$1) {
1360
+ const mastraError = new error.MastraError(
1361
+ {
1362
+ id: "CLOUDFLARE_STORAGE_LOAD_FAILED",
1363
+ domain: error.ErrorDomain.STORAGE,
1364
+ category: error.ErrorCategory.THIRD_PARTY,
1365
+ details: {
1366
+ tableName
1367
+ }
1368
+ },
1369
+ error$1
1370
+ );
1371
+ this.logger?.trackException(mastraError);
1372
+ this.logger?.error(mastraError.toString());
1373
+ return null;
1374
+ }
1375
+ }
1376
+ async batchInsert(input) {
1377
+ if (!input.records || input.records.length === 0) return;
1378
+ try {
1379
+ await Promise.all(
1380
+ input.records.map(async (record) => {
1381
+ const key = this.getKey(input.tableName, record);
1382
+ const processedRecord = {
1383
+ ...record,
1384
+ createdAt: record.createdAt ? storage.serializeDate(record.createdAt) : void 0,
1385
+ updatedAt: record.updatedAt ? storage.serializeDate(record.updatedAt) : void 0,
1386
+ metadata: record.metadata ? JSON.stringify(record.metadata) : void 0
1387
+ };
1388
+ await this.putKV({ tableName: input.tableName, key, value: processedRecord });
1389
+ })
1390
+ );
1391
+ } catch (error$1) {
1392
+ throw new error.MastraError(
1393
+ {
1394
+ id: "CLOUDFLARE_STORAGE_BATCH_INSERT_FAILED",
1395
+ domain: error.ErrorDomain.STORAGE,
1396
+ category: error.ErrorCategory.THIRD_PARTY,
1397
+ text: `Error in batch insert for table ${input.tableName}`,
1398
+ details: {
1399
+ tableName: input.tableName
1400
+ }
1401
+ },
1402
+ error$1
1403
+ );
1404
+ }
1405
+ }
1406
+ /**
1407
+ * Helper to safely serialize data for KV storage
1408
+ */
1409
+ safeSerialize(data) {
1410
+ return typeof data === "string" ? data : JSON.stringify(data);
1411
+ }
1412
+ async putNamespaceValue({
1413
+ tableName,
1414
+ key,
1415
+ value,
1416
+ metadata
1417
+ }) {
1418
+ try {
1419
+ const serializedValue = this.safeSerialize(value);
1420
+ const serializedMetadata = metadata ? this.safeSerialize(metadata) : "";
1421
+ if (this.bindings) {
1422
+ const binding = this.getBinding(tableName);
1423
+ await binding.put(key, serializedValue, { metadata: serializedMetadata });
1424
+ } else {
1425
+ const namespaceId = await this.getNamespaceId(tableName);
1426
+ await this.client.kv.namespaces.values.update(namespaceId, key, {
1427
+ account_id: this.accountId,
1428
+ value: serializedValue,
1429
+ metadata: serializedMetadata
1430
+ });
1431
+ }
1432
+ } catch (error) {
1433
+ const message = error instanceof Error ? error.message : String(error);
1434
+ this.logger.error(`Failed to put value for ${tableName} ${key}:`, { message });
1435
+ throw error;
1436
+ }
1437
+ }
1438
+ async putKV({
1439
+ tableName,
1440
+ key,
1441
+ value,
1442
+ metadata
1443
+ }) {
1444
+ try {
1445
+ await this.putNamespaceValue({ tableName, key, value, metadata });
1446
+ } catch (error) {
1447
+ this.logger.error(`Failed to put KV value for ${tableName}:${key}:`, error);
1448
+ throw new Error(`Failed to put KV value: ${error.message}`);
1449
+ }
1450
+ }
630
1451
  async createTable({
631
1452
  tableName,
632
1453
  schema
@@ -639,489 +1460,491 @@ var CloudflareStore = class extends storage.MastraStorage {
639
1460
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
640
1461
  };
641
1462
  await this.putKV({ tableName, key: schemaKey, value: schema, metadata });
642
- } catch (error) {
643
- this.logger.error(`Failed to store schema for ${tableName}:`, error);
644
- throw new Error(`Failed to store schema: ${error.message}`);
1463
+ } catch (error$1) {
1464
+ throw new error.MastraError(
1465
+ {
1466
+ id: "CLOUDFLARE_STORAGE_CREATE_TABLE_FAILED",
1467
+ domain: error.ErrorDomain.STORAGE,
1468
+ category: error.ErrorCategory.THIRD_PARTY,
1469
+ details: {
1470
+ tableName
1471
+ }
1472
+ },
1473
+ error$1
1474
+ );
1475
+ }
1476
+ }
1477
+ async listNamespaceKeys(tableName, options) {
1478
+ try {
1479
+ if (this.bindings) {
1480
+ const binding = this.getBinding(tableName);
1481
+ const response = await binding.list({
1482
+ limit: options?.limit || 1e3,
1483
+ prefix: options?.prefix
1484
+ });
1485
+ return response.keys;
1486
+ } else {
1487
+ const namespaceId = await this.getNamespaceId(tableName);
1488
+ const response = await this.client.kv.namespaces.keys.list(namespaceId, {
1489
+ account_id: this.accountId,
1490
+ limit: options?.limit || 1e3,
1491
+ prefix: options?.prefix
1492
+ });
1493
+ return response.result;
1494
+ }
1495
+ } catch (error$1) {
1496
+ throw new error.MastraError(
1497
+ {
1498
+ id: "CLOUDFLARE_STORAGE_LIST_NAMESPACE_KEYS_FAILED",
1499
+ domain: error.ErrorDomain.STORAGE,
1500
+ category: error.ErrorCategory.THIRD_PARTY,
1501
+ details: {
1502
+ tableName
1503
+ }
1504
+ },
1505
+ error$1
1506
+ );
645
1507
  }
646
1508
  }
647
- async clearTable({ tableName }) {
648
- const keys = await this.listKV(tableName);
649
- if (keys.length > 0) {
650
- await Promise.all(keys.map((keyObj) => this.deleteKV(tableName, keyObj.name)));
1509
+ async deleteNamespaceValue(tableName, key) {
1510
+ if (this.bindings) {
1511
+ const binding = this.getBinding(tableName);
1512
+ await binding.delete(key);
1513
+ } else {
1514
+ const namespaceId = await this.getNamespaceId(tableName);
1515
+ await this.client.kv.namespaces.values.delete(namespaceId, key, {
1516
+ account_id: this.accountId
1517
+ });
651
1518
  }
652
1519
  }
653
- async insert({
654
- tableName,
655
- record
656
- }) {
1520
+ async deleteKV(tableName, key) {
657
1521
  try {
658
- const key = this.getKey(tableName, record);
659
- const processedRecord = {
660
- ...record,
661
- createdAt: record.createdAt ? this.serializeDate(record.createdAt) : void 0,
662
- updatedAt: record.updatedAt ? this.serializeDate(record.updatedAt) : void 0,
663
- metadata: record.metadata ? JSON.stringify(record.metadata) : ""
664
- };
665
- await this.validateRecord(processedRecord, tableName);
666
- await this.putKV({ tableName, key, value: processedRecord });
1522
+ await this.deleteNamespaceValue(tableName, key);
667
1523
  } catch (error) {
668
- const message = error instanceof Error ? error.message : String(error);
669
- this.logger.error(`Failed to insert record for ${tableName}:`, { message });
670
- throw error;
1524
+ this.logger.error(`Failed to delete KV value for ${tableName}:${key}:`, error);
1525
+ throw new Error(`Failed to delete KV value: ${error.message}`);
671
1526
  }
672
1527
  }
673
- async load({ tableName, keys }) {
1528
+ async listKV(tableName, options) {
674
1529
  try {
675
- const key = this.getKey(tableName, keys);
676
- const data = await this.getKV(tableName, key);
677
- if (!data) return null;
678
- const processed = {
679
- ...data,
680
- createdAt: this.ensureDate(data.createdAt),
681
- updatedAt: this.ensureDate(data.updatedAt),
682
- metadata: this.ensureMetadata(data.metadata)
683
- };
684
- return processed;
1530
+ return await this.listNamespaceKeys(tableName, options);
685
1531
  } catch (error) {
686
- this.logger.error(`Failed to load data for ${tableName}:`, {
687
- error: error instanceof Error ? error.message : String(error)
688
- });
689
- return null;
1532
+ this.logger.error(`Failed to list KV for ${tableName}:`, error);
1533
+ throw new Error(`Failed to list KV: ${error.message}`);
690
1534
  }
691
1535
  }
692
- async getThreadById({ threadId }) {
693
- const thread = await this.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
694
- if (!thread) return null;
1536
+ };
1537
+ function transformScoreRow(row) {
1538
+ let input = void 0;
1539
+ if (row.input) {
695
1540
  try {
696
- return {
697
- ...thread,
698
- createdAt: this.ensureDate(thread.createdAt),
699
- updatedAt: this.ensureDate(thread.updatedAt),
700
- metadata: this.ensureMetadata(thread.metadata)
701
- };
702
- } catch (error) {
703
- this.logger.error(`Error processing thread ${threadId}:`, {
704
- error: error instanceof Error ? error.message : String(error)
705
- });
706
- return null;
1541
+ input = JSON.parse(row.input);
1542
+ } catch {
1543
+ input = row.input;
707
1544
  }
708
1545
  }
709
- async getThreadsByResourceId({ resourceId }) {
1546
+ return {
1547
+ ...row,
1548
+ input
1549
+ };
1550
+ }
1551
+ var ScoresStorageCloudflare = class extends storage.ScoresStorage {
1552
+ operations;
1553
+ constructor({ operations }) {
1554
+ super();
1555
+ this.operations = operations;
1556
+ }
1557
+ async getScoreById({ id }) {
710
1558
  try {
711
- const keyList = await this.listKV(storage.TABLE_THREADS);
712
- const threads = await Promise.all(
713
- keyList.map(async (keyObj) => {
714
- try {
715
- const data = await this.getKV(storage.TABLE_THREADS, keyObj.name);
716
- if (!data) return null;
717
- const thread = typeof data === "string" ? JSON.parse(data) : data;
718
- if (!thread || !thread.resourceId || thread.resourceId !== resourceId) return null;
719
- return {
720
- ...thread,
721
- createdAt: this.ensureDate(thread.createdAt),
722
- updatedAt: this.ensureDate(thread.updatedAt),
723
- metadata: this.ensureMetadata(thread.metadata)
724
- };
725
- } catch (error) {
726
- const message = error instanceof Error ? error.message : String(error);
727
- this.logger.error(`Error processing thread from key ${keyObj.name}:`, { message });
728
- return null;
729
- }
730
- })
1559
+ const score = await this.operations.getKV(storage.TABLE_SCORERS, id);
1560
+ if (!score) {
1561
+ return null;
1562
+ }
1563
+ return transformScoreRow(score);
1564
+ } catch (error$1) {
1565
+ const mastraError = new error.MastraError(
1566
+ {
1567
+ id: "CLOUDFLARE_STORAGE_SCORES_GET_SCORE_BY_ID_FAILED",
1568
+ domain: error.ErrorDomain.STORAGE,
1569
+ category: error.ErrorCategory.THIRD_PARTY,
1570
+ text: `Failed to get score by id: ${id}`
1571
+ },
1572
+ error$1
731
1573
  );
732
- return threads.filter((thread) => thread !== null);
733
- } catch (error) {
734
- const message = error instanceof Error ? error.message : String(error);
735
- this.logger.error(`Error getting threads for resourceId ${resourceId}:`, { message });
736
- return [];
1574
+ this.logger.trackException(mastraError);
1575
+ this.logger.error(mastraError.toString());
1576
+ return null;
737
1577
  }
738
1578
  }
739
- async saveThread({ thread }) {
1579
+ async saveScore(score) {
740
1580
  try {
741
- await this.insert({ tableName: storage.TABLE_THREADS, record: thread });
742
- return thread;
743
- } catch (error) {
744
- const message = error instanceof Error ? error.message : String(error);
745
- this.logger.error("Error saving thread:", { message });
746
- throw error;
1581
+ const { input, ...rest } = score;
1582
+ const serializedRecord = {};
1583
+ for (const [key, value] of Object.entries(rest)) {
1584
+ if (value !== null && value !== void 0) {
1585
+ if (typeof value === "object") {
1586
+ serializedRecord[key] = JSON.stringify(value);
1587
+ } else {
1588
+ serializedRecord[key] = value;
1589
+ }
1590
+ } else {
1591
+ serializedRecord[key] = null;
1592
+ }
1593
+ }
1594
+ serializedRecord.input = JSON.stringify(input);
1595
+ serializedRecord.createdAt = (/* @__PURE__ */ new Date()).toISOString();
1596
+ serializedRecord.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1597
+ await this.operations.putKV({
1598
+ tableName: storage.TABLE_SCORERS,
1599
+ key: score.id,
1600
+ value: serializedRecord
1601
+ });
1602
+ const scoreFromDb = await this.getScoreById({ id: score.id });
1603
+ return { score: scoreFromDb };
1604
+ } catch (error$1) {
1605
+ const mastraError = new error.MastraError(
1606
+ {
1607
+ id: "CLOUDFLARE_STORAGE_SCORES_SAVE_SCORE_FAILED",
1608
+ domain: error.ErrorDomain.STORAGE,
1609
+ category: error.ErrorCategory.THIRD_PARTY,
1610
+ text: `Failed to save score: ${score.id}`
1611
+ },
1612
+ error$1
1613
+ );
1614
+ this.logger.trackException(mastraError);
1615
+ this.logger.error(mastraError.toString());
1616
+ throw mastraError;
747
1617
  }
748
1618
  }
749
- async updateThread({
750
- id,
751
- title,
752
- metadata
1619
+ async getScoresByScorerId({
1620
+ scorerId,
1621
+ pagination
753
1622
  }) {
754
1623
  try {
755
- const thread = await this.getThreadById({ threadId: id });
756
- if (!thread) {
757
- throw new Error(`Thread ${id} not found`);
1624
+ const keys = await this.operations.listKV(storage.TABLE_SCORERS);
1625
+ const scores = [];
1626
+ for (const { name: key } of keys) {
1627
+ const score = await this.operations.getKV(storage.TABLE_SCORERS, key);
1628
+ if (score && score.scorerId === scorerId) {
1629
+ scores.push(transformScoreRow(score));
1630
+ }
758
1631
  }
759
- const updatedThread = {
760
- ...thread,
761
- title,
762
- metadata: this.ensureMetadata({
763
- ...thread.metadata ?? {},
764
- ...metadata
765
- }),
766
- updatedAt: /* @__PURE__ */ new Date()
1632
+ scores.sort((a, b) => {
1633
+ const dateA = new Date(a.createdAt || 0).getTime();
1634
+ const dateB = new Date(b.createdAt || 0).getTime();
1635
+ return dateB - dateA;
1636
+ });
1637
+ const total = scores.length;
1638
+ const start = pagination.page * pagination.perPage;
1639
+ const end = start + pagination.perPage;
1640
+ const pagedScores = scores.slice(start, end);
1641
+ return {
1642
+ pagination: {
1643
+ total,
1644
+ page: pagination.page,
1645
+ perPage: pagination.perPage,
1646
+ hasMore: end < total
1647
+ },
1648
+ scores: pagedScores
767
1649
  };
768
- await this.insert({ tableName: storage.TABLE_THREADS, record: updatedThread });
769
- return updatedThread;
770
- } catch (error) {
771
- const message = error instanceof Error ? error.message : String(error);
772
- this.logger.error(`Error updating thread ${id}:`, { message });
773
- throw error;
1650
+ } catch (error$1) {
1651
+ const mastraError = new error.MastraError(
1652
+ {
1653
+ id: "CLOUDFLARE_STORAGE_SCORES_GET_SCORES_BY_SCORER_ID_FAILED",
1654
+ domain: error.ErrorDomain.STORAGE,
1655
+ category: error.ErrorCategory.THIRD_PARTY,
1656
+ text: `Failed to get scores by scorer id: ${scorerId}`
1657
+ },
1658
+ error$1
1659
+ );
1660
+ this.logger?.trackException(mastraError);
1661
+ this.logger?.error(mastraError.toString());
1662
+ return { pagination: { total: 0, page: 0, perPage: 100, hasMore: false }, scores: [] };
774
1663
  }
775
1664
  }
776
- async deleteThread({ threadId }) {
1665
+ async getScoresByRunId({
1666
+ runId,
1667
+ pagination
1668
+ }) {
777
1669
  try {
778
- const thread = await this.getThreadById({ threadId });
779
- if (!thread) {
780
- throw new Error(`Thread ${threadId} not found`);
1670
+ const keys = await this.operations.listKV(storage.TABLE_SCORERS);
1671
+ const scores = [];
1672
+ for (const { name: key } of keys) {
1673
+ const score = await this.operations.getKV(storage.TABLE_SCORERS, key);
1674
+ if (score && score.runId === runId) {
1675
+ scores.push(transformScoreRow(score));
1676
+ }
781
1677
  }
782
- const messageKeys = await this.listKV(storage.TABLE_MESSAGES);
783
- const threadMessageKeys = messageKeys.filter((key) => key.name.includes(`${storage.TABLE_MESSAGES}:${threadId}:`));
784
- await Promise.all([
785
- // Delete message order
786
- this.deleteKV(storage.TABLE_MESSAGES, this.getThreadMessagesKey(threadId)),
787
- // Delete all messages
788
- ...threadMessageKeys.map((key) => this.deleteKV(storage.TABLE_MESSAGES, key.name)),
789
- // Delete thread
790
- this.deleteKV(storage.TABLE_THREADS, this.getKey(storage.TABLE_THREADS, { id: threadId }))
791
- ]);
792
- } catch (error) {
793
- const message = error instanceof Error ? error.message : String(error);
794
- this.logger.error(`Error deleting thread ${threadId}:`, { message });
795
- throw error;
796
- }
797
- }
798
- getMessageKey(threadId, messageId) {
799
- try {
800
- return this.getKey(storage.TABLE_MESSAGES, { threadId, id: messageId });
801
- } catch (error) {
802
- const message = error instanceof Error ? error.message : String(error);
803
- this.logger.error(`Error getting message key for thread ${threadId} and message ${messageId}:`, { message });
804
- throw error;
1678
+ scores.sort((a, b) => {
1679
+ const dateA = new Date(a.createdAt || 0).getTime();
1680
+ const dateB = new Date(b.createdAt || 0).getTime();
1681
+ return dateB - dateA;
1682
+ });
1683
+ const total = scores.length;
1684
+ const start = pagination.page * pagination.perPage;
1685
+ const end = start + pagination.perPage;
1686
+ const pagedScores = scores.slice(start, end);
1687
+ return {
1688
+ pagination: {
1689
+ total,
1690
+ page: pagination.page,
1691
+ perPage: pagination.perPage,
1692
+ hasMore: end < total
1693
+ },
1694
+ scores: pagedScores
1695
+ };
1696
+ } catch (error$1) {
1697
+ const mastraError = new error.MastraError(
1698
+ {
1699
+ id: "CLOUDFLARE_STORAGE_SCORES_GET_SCORES_BY_RUN_ID_FAILED",
1700
+ domain: error.ErrorDomain.STORAGE,
1701
+ category: error.ErrorCategory.THIRD_PARTY,
1702
+ text: `Failed to get scores by run id: ${runId}`
1703
+ },
1704
+ error$1
1705
+ );
1706
+ this.logger.trackException(mastraError);
1707
+ this.logger.error(mastraError.toString());
1708
+ return { pagination: { total: 0, page: 0, perPage: 100, hasMore: false }, scores: [] };
805
1709
  }
806
1710
  }
807
- getThreadMessagesKey(threadId) {
1711
+ async getScoresByEntityId({
1712
+ entityId,
1713
+ entityType,
1714
+ pagination
1715
+ }) {
808
1716
  try {
809
- return this.getKey(storage.TABLE_MESSAGES, { threadId, id: "messages" });
810
- } catch (error) {
811
- const message = error instanceof Error ? error.message : String(error);
812
- this.logger.error(`Error getting thread messages key for thread ${threadId}:`, { message });
813
- throw error;
1717
+ const keys = await this.operations.listKV(storage.TABLE_SCORERS);
1718
+ const scores = [];
1719
+ for (const { name: key } of keys) {
1720
+ const score = await this.operations.getKV(storage.TABLE_SCORERS, key);
1721
+ if (score && score.entityId === entityId && score.entityType === entityType) {
1722
+ scores.push(transformScoreRow(score));
1723
+ }
1724
+ }
1725
+ scores.sort((a, b) => {
1726
+ const dateA = new Date(a.createdAt || 0).getTime();
1727
+ const dateB = new Date(b.createdAt || 0).getTime();
1728
+ return dateB - dateA;
1729
+ });
1730
+ const total = scores.length;
1731
+ const start = pagination.page * pagination.perPage;
1732
+ const end = start + pagination.perPage;
1733
+ const pagedScores = scores.slice(start, end);
1734
+ return {
1735
+ pagination: {
1736
+ total,
1737
+ page: pagination.page,
1738
+ perPage: pagination.perPage,
1739
+ hasMore: end < total
1740
+ },
1741
+ scores: pagedScores
1742
+ };
1743
+ } catch (error$1) {
1744
+ const mastraError = new error.MastraError(
1745
+ {
1746
+ id: "CLOUDFLARE_STORAGE_SCORES_GET_SCORES_BY_ENTITY_ID_FAILED",
1747
+ domain: error.ErrorDomain.STORAGE,
1748
+ category: error.ErrorCategory.THIRD_PARTY,
1749
+ text: `Failed to get scores by entity id: ${entityId}, type: ${entityType}`
1750
+ },
1751
+ error$1
1752
+ );
1753
+ this.logger.trackException(mastraError);
1754
+ this.logger.error(mastraError.toString());
1755
+ return { pagination: { total: 0, page: 0, perPage: 100, hasMore: false }, scores: [] };
814
1756
  }
815
1757
  }
816
- async saveMessages(args) {
817
- const { messages, format = "v1" } = args;
818
- if (!Array.isArray(messages) || messages.length === 0) return [];
1758
+ };
1759
+ var TracesStorageCloudflare = class extends storage.TracesStorage {
1760
+ operations;
1761
+ constructor({ operations }) {
1762
+ super();
1763
+ this.operations = operations;
1764
+ }
1765
+ async getTraces(args) {
1766
+ const paginatedArgs = {
1767
+ name: args.name,
1768
+ scope: args.scope,
1769
+ page: args.page,
1770
+ perPage: args.perPage,
1771
+ attributes: args.attributes,
1772
+ filters: args.filters,
1773
+ dateRange: args.fromDate || args.toDate ? {
1774
+ start: args.fromDate,
1775
+ end: args.toDate
1776
+ } : void 0
1777
+ };
819
1778
  try {
820
- const validatedMessages = messages.map((message, index) => {
821
- const errors = [];
822
- if (!message.id) errors.push("id is required");
823
- if (!message.threadId) errors.push("threadId is required");
824
- if (!message.content) errors.push("content is required");
825
- if (!message.role) errors.push("role is required");
826
- if (!message.createdAt) errors.push("createdAt is required");
827
- if (errors.length > 0) {
828
- throw new Error(`Invalid message at index ${index}: ${errors.join(", ")}`);
829
- }
830
- return {
831
- ...message,
832
- createdAt: this.ensureDate(message.createdAt),
833
- type: message.type || "v2",
834
- _index: index
835
- };
836
- });
837
- const messagesByThread = validatedMessages.reduce((acc, message) => {
838
- if (message.threadId && !acc.has(message.threadId)) {
839
- acc.set(message.threadId, []);
840
- }
841
- if (message.threadId) {
842
- acc.get(message.threadId).push(message);
843
- }
844
- return acc;
845
- }, /* @__PURE__ */ new Map());
846
- await Promise.all(
847
- Array.from(messagesByThread.entries()).map(async ([threadId, threadMessages]) => {
848
- try {
849
- const thread = await this.getThreadById({ threadId });
850
- if (!thread) {
851
- throw new Error(`Thread ${threadId} not found`);
852
- }
853
- await Promise.all(
854
- threadMessages.map(async (message) => {
855
- const key = this.getMessageKey(threadId, message.id);
856
- const { _index, ...cleanMessage } = message;
857
- const serializedMessage = {
858
- ...cleanMessage,
859
- createdAt: this.serializeDate(cleanMessage.createdAt)
860
- };
861
- await this.putKV({ tableName: storage.TABLE_MESSAGES, key, value: serializedMessage });
862
- })
863
- );
864
- const orderKey = this.getThreadMessagesKey(threadId);
865
- const entries = await this.updateSorting(threadMessages);
866
- await this.updateSortedMessages(orderKey, entries);
867
- } catch (error) {
868
- const errorMessage = error instanceof Error ? error.message : String(error);
869
- this.logger.error(`Error processing messages for thread ${threadId}: ${errorMessage}`);
870
- throw error;
1779
+ const result = await this.getTracesPaginated(paginatedArgs);
1780
+ return result.traces;
1781
+ } catch (error$1) {
1782
+ throw new error.MastraError(
1783
+ {
1784
+ id: "CLOUDFLARE_STORAGE_GET_TRACES_ERROR",
1785
+ domain: error.ErrorDomain.STORAGE,
1786
+ category: error.ErrorCategory.THIRD_PARTY,
1787
+ text: `Failed to retrieve traces: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1788
+ details: {
1789
+ name: args.name ?? "",
1790
+ scope: args.scope ?? ""
871
1791
  }
872
- })
1792
+ },
1793
+ error$1
873
1794
  );
874
- const prepared = validatedMessages.map(
875
- ({ _index, ...message }) => ({ ...message, type: message.type !== "v2" ? message.type : void 0 })
876
- );
877
- const list = new agent.MessageList().add(prepared, "memory");
878
- if (format === `v2`) return list.get.all.v2();
879
- return list.get.all.v1();
880
- } catch (error) {
881
- const errorMessage = error instanceof Error ? error.message : String(error);
882
- this.logger.error(`Error saving messages: ${errorMessage}`);
883
- throw error;
884
1795
  }
885
1796
  }
886
- async getMessages({
887
- threadId,
888
- resourceId,
889
- selectBy,
890
- format
891
- }) {
892
- if (!threadId) throw new Error("threadId is required");
893
- let limit = 40;
894
- if (typeof selectBy?.last === "number") {
895
- limit = Math.max(0, selectBy.last);
896
- } else if (selectBy?.last === false) {
897
- limit = 0;
898
- }
899
- const messageIds = /* @__PURE__ */ new Set();
900
- if (limit === 0 && !selectBy?.include?.length) return [];
1797
+ async getTracesPaginated(args) {
901
1798
  try {
902
- await Promise.all([
903
- selectBy?.include?.length ? this.getIncludedMessagesWithContext(threadId, selectBy.include, messageIds) : Promise.resolve(),
904
- limit > 0 && !selectBy?.include?.length ? this.getRecentMessages(threadId, limit, messageIds) : Promise.resolve()
905
- ]);
906
- const messages = await this.fetchAndParseMessages(threadId, Array.from(messageIds));
907
- if (!messages.length) return [];
908
- try {
909
- const threadMessagesKey = this.getThreadMessagesKey(threadId);
910
- const messageOrder = await this.getFullOrder(threadMessagesKey);
911
- const orderMap = new Map(messageOrder.map((id, index) => [id, index]));
912
- messages.sort((a, b) => {
913
- const indexA = orderMap.get(a.id);
914
- const indexB = orderMap.get(b.id);
915
- if (indexA !== void 0 && indexB !== void 0) return orderMap.get(a.id) - orderMap.get(b.id);
916
- return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
917
- });
918
- } catch (error) {
919
- const errorMessage = error instanceof Error ? error.message : String(error);
920
- this.logger.warn(`Error sorting messages, falling back to creation time: ${errorMessage}`);
921
- messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
922
- }
923
- const prepared = messages.map(({ _index, ...message }) => ({
924
- ...message,
925
- type: message.type === `v2` ? void 0 : message.type,
926
- createdAt: this.ensureDate(message.createdAt)
927
- }));
928
- const list = new agent.MessageList({ threadId, resourceId }).add(prepared, "memory");
929
- if (format === `v1`) return list.get.all.v1();
930
- return list.get.all.v2();
931
- } catch (error) {
932
- const errorMessage = error instanceof Error ? error.message : String(error);
933
- this.logger.error(`Error retrieving messages for thread ${threadId}: ${errorMessage}`);
934
- return [];
1799
+ const { name, scope, attributes, filters, page = 0, perPage = 100, dateRange } = args;
1800
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
1801
+ const keyObjs = await this.operations.listKV(storage.TABLE_TRACES, { prefix: `${prefix}${storage.TABLE_TRACES}` });
1802
+ const traces = [];
1803
+ for (const { name: key } of keyObjs) {
1804
+ try {
1805
+ const data = await this.operations.getKV(storage.TABLE_TRACES, key);
1806
+ if (!data) continue;
1807
+ if (name && data.name !== name) continue;
1808
+ if (scope && data.scope !== scope) continue;
1809
+ if (attributes) {
1810
+ const dataAttributes = data.attributes || {};
1811
+ let shouldSkip = false;
1812
+ for (const [key2, value] of Object.entries(attributes)) {
1813
+ if (dataAttributes[key2] !== value) {
1814
+ shouldSkip = true;
1815
+ break;
1816
+ }
1817
+ }
1818
+ if (shouldSkip) continue;
1819
+ }
1820
+ if (dateRange?.start || dateRange?.end) {
1821
+ const traceDate = new Date(data.createdAt || 0);
1822
+ if (dateRange.start && traceDate < dateRange.start) continue;
1823
+ if (dateRange.end && traceDate > dateRange.end) continue;
1824
+ }
1825
+ if (filters) {
1826
+ let shouldSkip = false;
1827
+ for (const [key2, value] of Object.entries(filters)) {
1828
+ if (data[key2] !== value) {
1829
+ shouldSkip = true;
1830
+ break;
1831
+ }
1832
+ }
1833
+ if (shouldSkip) continue;
1834
+ }
1835
+ traces.push(data);
1836
+ } catch (err) {
1837
+ this.logger.error("Failed to parse trace:", { key, error: err });
1838
+ }
1839
+ }
1840
+ traces.sort((a, b) => {
1841
+ const aTime = new Date(a.createdAt || 0).getTime();
1842
+ const bTime = new Date(b.createdAt || 0).getTime();
1843
+ return bTime - aTime;
1844
+ });
1845
+ const total = traces.length;
1846
+ const start = page * perPage;
1847
+ const end = start + perPage;
1848
+ const pagedTraces = traces.slice(start, end);
1849
+ return {
1850
+ traces: pagedTraces,
1851
+ total,
1852
+ page,
1853
+ perPage,
1854
+ hasMore: end < total
1855
+ };
1856
+ } catch (error$1) {
1857
+ const mastraError = new error.MastraError(
1858
+ {
1859
+ id: "CLOUDFLARE_STORAGE_GET_TRACES_PAGINATED_FAILED",
1860
+ domain: error.ErrorDomain.STORAGE,
1861
+ category: error.ErrorCategory.THIRD_PARTY,
1862
+ text: "Error getting traces with pagination"
1863
+ },
1864
+ error$1
1865
+ );
1866
+ this.logger.trackException?.(mastraError);
1867
+ this.logger.error(mastraError.toString());
1868
+ return { traces: [], total: 0, page: 0, perPage: 100, hasMore: false };
935
1869
  }
936
1870
  }
937
- validateWorkflowParams(params) {
938
- const { namespace, workflowName, runId } = params;
939
- if (!namespace || !workflowName || !runId) {
940
- throw new Error("Invalid workflow snapshot parameters");
941
- }
1871
+ async batchTraceInsert({ records }) {
1872
+ this.logger.debug("Batch inserting traces", { count: records.length });
1873
+ await this.operations.batchInsert({
1874
+ tableName: storage.TABLE_TRACES,
1875
+ records
1876
+ });
942
1877
  }
943
- validateWorkflowState(state) {
944
- if (!state?.runId || !state?.value || !state?.context?.input || !state?.activePaths) {
945
- throw new Error("Invalid workflow state structure");
946
- }
1878
+ };
1879
+ var WorkflowsStorageCloudflare = class extends storage.WorkflowsStorage {
1880
+ operations;
1881
+ constructor({ operations }) {
1882
+ super();
1883
+ this.operations = operations;
947
1884
  }
948
- normalizeSteps(steps) {
949
- const normalizedSteps = {};
950
- for (const [stepId, step] of Object.entries(steps)) {
951
- normalizedSteps[stepId] = {
952
- status: step.status,
953
- payload: step.payload || step.result,
954
- error: step.error
955
- };
1885
+ validateWorkflowParams(params) {
1886
+ const { workflowName, runId } = params;
1887
+ if (!workflowName || !runId) {
1888
+ throw new Error("Invalid workflow snapshot parameters");
956
1889
  }
957
- return normalizedSteps;
958
- }
959
- normalizeWorkflowState(data) {
960
- return {
961
- runId: data.runId,
962
- value: data.value,
963
- context: data.context,
964
- serializedStepGraph: data.serializedStepGraph,
965
- suspendedPaths: data.suspendedPaths || {},
966
- activePaths: data.activePaths || [],
967
- timestamp: data.timestamp || Date.now()
968
- };
969
1890
  }
970
1891
  async persistWorkflowSnapshot(params) {
971
1892
  try {
972
- this.validateWorkflowParams(params);
973
- const { namespace, workflowName, runId, snapshot } = params;
974
- const normalizedState = this.normalizeWorkflowState(snapshot);
975
- this.validateWorkflowState(normalizedState);
976
- await this.insert({
1893
+ const { workflowName, runId, snapshot } = params;
1894
+ await this.operations.putKV({
977
1895
  tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
978
- record: {
979
- namespace,
1896
+ key: this.operations.getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { workflow_name: workflowName, run_id: runId }),
1897
+ value: {
980
1898
  workflow_name: workflowName,
981
1899
  run_id: runId,
982
- snapshot: normalizedState,
1900
+ snapshot: typeof snapshot === "string" ? snapshot : JSON.stringify(snapshot),
983
1901
  createdAt: /* @__PURE__ */ new Date(),
984
1902
  updatedAt: /* @__PURE__ */ new Date()
985
1903
  }
986
1904
  });
987
- } catch (error) {
988
- const message = error instanceof Error ? error.message : String(error);
989
- this.logger.error("Error persisting workflow snapshot:", { message });
990
- throw error;
1905
+ } catch (error$1) {
1906
+ throw new error.MastraError(
1907
+ {
1908
+ id: "CLOUDFLARE_STORAGE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
1909
+ domain: error.ErrorDomain.STORAGE,
1910
+ category: error.ErrorCategory.THIRD_PARTY,
1911
+ text: `Error persisting workflow snapshot for workflow ${params.workflowName}, run ${params.runId}`,
1912
+ details: {
1913
+ workflowName: params.workflowName,
1914
+ runId: params.runId
1915
+ }
1916
+ },
1917
+ error$1
1918
+ );
991
1919
  }
992
1920
  }
993
1921
  async loadWorkflowSnapshot(params) {
994
1922
  try {
995
1923
  this.validateWorkflowParams(params);
996
- const { namespace, workflowName, runId } = params;
997
- const key = this.getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace, workflow_name: workflowName, run_id: runId });
998
- const data = await this.getKV(storage.TABLE_WORKFLOW_SNAPSHOT, key);
1924
+ const { workflowName, runId } = params;
1925
+ const key = this.operations.getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { workflow_name: workflowName, run_id: runId });
1926
+ const data = await this.operations.getKV(storage.TABLE_WORKFLOW_SNAPSHOT, key);
999
1927
  if (!data) return null;
1000
- const state = this.normalizeWorkflowState(data.snapshot || data);
1001
- this.validateWorkflowState(state);
1002
- return state;
1003
- } catch (error) {
1004
- this.logger.error("Error loading workflow snapshot:", {
1005
- error: error instanceof Error ? error.message : String(error)
1006
- });
1007
- return null;
1008
- }
1009
- }
1010
- async batchInsert(input) {
1011
- if (!input.records || input.records.length === 0) return;
1012
- try {
1013
- await Promise.all(
1014
- input.records.map(async (record) => {
1015
- const key = this.getKey(input.tableName, record);
1016
- const processedRecord = {
1017
- ...record,
1018
- createdAt: record.createdAt ? this.serializeDate(record.createdAt) : void 0,
1019
- updatedAt: record.updatedAt ? this.serializeDate(record.updatedAt) : void 0,
1020
- metadata: record.metadata ? JSON.stringify(record.metadata) : void 0
1021
- };
1022
- await this.putKV({ tableName: input.tableName, key, value: processedRecord });
1023
- })
1024
- );
1025
- } catch (error) {
1026
- const message = error instanceof Error ? error.message : String(error);
1027
- this.logger.error("Error in batch insert:", { message });
1028
- throw error;
1029
- }
1030
- }
1031
- async getTraces({
1032
- name,
1033
- scope,
1034
- page = 0,
1035
- perPage = 100,
1036
- attributes,
1037
- fromDate,
1038
- toDate
1039
- }) {
1040
- try {
1041
- let keys;
1042
- if (this.bindings) {
1043
- keys = (await this.listKV(storage.TABLE_TRACES))?.map((k) => k.name) || [];
1044
- } else {
1045
- const namespaceId = await this.getNamespaceId(storage.TABLE_TRACES);
1046
- const result = await this.client.kv.namespaces.keys.list(namespaceId, {
1047
- prefix: "",
1048
- limit: 1e3,
1049
- account_id: this.accountId
1050
- });
1051
- keys = result.result?.map((k) => k.name) || [];
1052
- }
1053
- const traceRecords = await Promise.all(
1054
- keys.map(async (key) => {
1055
- const record = await this.getKV(storage.TABLE_TRACES, key);
1056
- if (!record) return null;
1057
- return record;
1058
- })
1059
- );
1060
- let filteredTraces = traceRecords.filter(
1061
- (record) => record !== null && typeof record === "object"
1928
+ const snapshotData = typeof data.snapshot === "string" ? JSON.parse(data.snapshot) : data.snapshot;
1929
+ return snapshotData;
1930
+ } catch (error$1) {
1931
+ const mastraError = new error.MastraError(
1932
+ {
1933
+ id: "CLOUDFLARE_STORAGE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
1934
+ domain: error.ErrorDomain.STORAGE,
1935
+ category: error.ErrorCategory.THIRD_PARTY,
1936
+ text: `Error loading workflow snapshot for workflow ${params.workflowName}, run ${params.runId}`,
1937
+ details: {
1938
+ workflowName: params.workflowName,
1939
+ runId: params.runId
1940
+ }
1941
+ },
1942
+ error$1
1062
1943
  );
1063
- if (name) {
1064
- filteredTraces = filteredTraces.filter((record) => record.name?.toLowerCase().startsWith(name.toLowerCase()));
1065
- }
1066
- if (scope) {
1067
- filteredTraces = filteredTraces.filter((record) => record.scope === scope);
1068
- }
1069
- if (attributes) {
1070
- filteredTraces = filteredTraces.filter((record) => {
1071
- if (!record.attributes) return false;
1072
- const recordAttrs = this.parseJSON(record.attributes);
1073
- if (!recordAttrs) return false;
1074
- return Object.entries(attributes).every(([key, value]) => recordAttrs[key] === value);
1075
- });
1076
- }
1077
- if (fromDate) {
1078
- filteredTraces = filteredTraces.filter((record) => new Date(record.createdAt).getTime() >= fromDate.getTime());
1079
- }
1080
- if (toDate) {
1081
- filteredTraces = filteredTraces.filter((record) => new Date(record.createdAt).getTime() <= toDate.getTime());
1082
- }
1083
- filteredTraces.sort((a, b) => {
1084
- const dateA = new Date(a.createdAt).getTime();
1085
- const dateB = new Date(b.createdAt).getTime();
1086
- return dateB - dateA;
1087
- });
1088
- const start = page * perPage;
1089
- const end = start + perPage;
1090
- const paginatedTraces = filteredTraces.slice(start, end);
1091
- return paginatedTraces.map((record) => ({
1092
- id: record.id,
1093
- parentSpanId: record.parentSpanId,
1094
- traceId: record.traceId,
1095
- name: record.name,
1096
- scope: record.scope,
1097
- kind: record.kind,
1098
- status: this.parseJSON(record.status),
1099
- events: this.parseJSON(record.events) || [],
1100
- links: this.parseJSON(record.links) || [],
1101
- attributes: this.parseJSON(record?.attributes) || {},
1102
- startTime: record.startTime,
1103
- endTime: record.endTime,
1104
- other: this.parseJSON(record.other) || {},
1105
- createdAt: record.createdAt
1106
- }));
1107
- } catch (error) {
1108
- const message = error instanceof Error ? error.message : String(error);
1109
- this.logger.error("Failed to get traces:", { message });
1110
- return [];
1111
- }
1112
- }
1113
- parseJSON(value) {
1114
- if (typeof value === "string") {
1115
- try {
1116
- return JSON.parse(value);
1117
- } catch {
1118
- return value;
1119
- }
1944
+ this.logger.trackException?.(mastraError);
1945
+ this.logger.error(mastraError.toString());
1946
+ return null;
1120
1947
  }
1121
- return value;
1122
- }
1123
- getEvalsByAgentName(_agentName, _type) {
1124
- throw new Error("Method not implemented.");
1125
1948
  }
1126
1949
  parseWorkflowRun(row) {
1127
1950
  let parsedSnapshot = row.snapshot;
@@ -1136,28 +1959,24 @@ var CloudflareStore = class extends storage.MastraStorage {
1136
1959
  workflowName: row.workflow_name,
1137
1960
  runId: row.run_id,
1138
1961
  snapshot: parsedSnapshot,
1139
- createdAt: this.ensureDate(row.createdAt),
1140
- updatedAt: this.ensureDate(row.updatedAt),
1962
+ createdAt: storage.ensureDate(row.createdAt),
1963
+ updatedAt: storage.ensureDate(row.updatedAt),
1141
1964
  resourceId: row.resourceId
1142
1965
  };
1143
1966
  }
1144
1967
  buildWorkflowSnapshotPrefix({
1145
- namespace,
1146
1968
  workflowName,
1147
1969
  runId,
1148
1970
  resourceId
1149
1971
  }) {
1150
- const prefix = this.namespacePrefix ? `${this.namespacePrefix}:` : "";
1972
+ const prefix = this.operations.namespacePrefix ? `${this.operations.namespacePrefix}:` : "";
1151
1973
  let key = `${prefix}${storage.TABLE_WORKFLOW_SNAPSHOT}`;
1152
- if (namespace) key += `:${namespace}`;
1153
1974
  if (workflowName) key += `:${workflowName}`;
1154
1975
  if (runId) key += `:${runId}`;
1155
1976
  if (resourceId) key += `:${resourceId}`;
1156
- if (!resourceId && (runId || workflowName || namespace)) key += ":";
1157
1977
  return key;
1158
1978
  }
1159
1979
  async getWorkflowRuns({
1160
- namespace,
1161
1980
  workflowName,
1162
1981
  limit = 20,
1163
1982
  offset = 0,
@@ -1166,28 +1985,32 @@ var CloudflareStore = class extends storage.MastraStorage {
1166
1985
  toDate
1167
1986
  } = {}) {
1168
1987
  try {
1169
- const prefix = this.buildWorkflowSnapshotPrefix({ namespace, workflowName });
1170
- const keyObjs = await this.listKV(storage.TABLE_WORKFLOW_SNAPSHOT, { prefix });
1988
+ const prefix = this.buildWorkflowSnapshotPrefix({ workflowName });
1989
+ const keyObjs = await this.operations.listKV(storage.TABLE_WORKFLOW_SNAPSHOT, { prefix });
1171
1990
  const runs = [];
1172
1991
  for (const { name: key } of keyObjs) {
1173
1992
  const parts = key.split(":");
1174
1993
  const idx = parts.indexOf(storage.TABLE_WORKFLOW_SNAPSHOT);
1175
- if (idx === -1 || parts.length < idx + 4) continue;
1176
- const ns = parts[idx + 1];
1177
- const wfName = parts[idx + 2];
1178
- const keyResourceId = parts.length > idx + 4 ? parts[idx + 4] : void 0;
1179
- if (namespace && ns !== namespace || workflowName && wfName !== workflowName) continue;
1180
- if (resourceId && keyResourceId && keyResourceId !== resourceId) continue;
1181
- const data = await this.getKV(storage.TABLE_WORKFLOW_SNAPSHOT, key);
1994
+ if (idx === -1 || parts.length < idx + 3) continue;
1995
+ const wfName = parts[idx + 1];
1996
+ const keyResourceId = parts.length > idx + 3 ? parts[idx + 3] : void 0;
1997
+ if (workflowName && wfName !== workflowName) continue;
1998
+ if (resourceId && keyResourceId !== resourceId) continue;
1999
+ const data = await this.operations.getKV(storage.TABLE_WORKFLOW_SNAPSHOT, key);
1182
2000
  if (!data) continue;
1183
2001
  try {
1184
- if (resourceId && data.resourceId && data.resourceId !== resourceId) continue;
1185
- const createdAt = this.ensureDate(data.createdAt);
2002
+ if (resourceId && !keyResourceId) continue;
2003
+ const createdAt = storage.ensureDate(data.createdAt);
1186
2004
  if (fromDate && createdAt && createdAt < fromDate) continue;
1187
2005
  if (toDate && createdAt && createdAt > toDate) continue;
1188
- const state = this.normalizeWorkflowState(data.snapshot || data);
1189
- this.validateWorkflowState(state);
1190
- const run = this.parseWorkflowRun({ ...data, snapshot: state });
2006
+ const snapshotData = typeof data.snapshot === "string" ? JSON.parse(data.snapshot) : data.snapshot;
2007
+ const resourceIdToUse = keyResourceId || data.resourceId;
2008
+ const run = this.parseWorkflowRun({
2009
+ ...data,
2010
+ workflow_name: wfName,
2011
+ resourceId: resourceIdToUse,
2012
+ snapshot: snapshotData
2013
+ });
1191
2014
  runs.push(run);
1192
2015
  } catch (err) {
1193
2016
  this.logger.error("Failed to parse workflow snapshot:", { key, error: err });
@@ -1203,36 +2026,326 @@ var CloudflareStore = class extends storage.MastraStorage {
1203
2026
  runs: pagedRuns,
1204
2027
  total: runs.length
1205
2028
  };
1206
- } catch (error) {
1207
- const message = error instanceof Error ? error.message : String(error);
1208
- this.logger.error("Error in getWorkflowRuns:", { message });
2029
+ } catch (error$1) {
2030
+ const mastraError = new error.MastraError(
2031
+ {
2032
+ id: "CLOUDFLARE_STORAGE_GET_WORKFLOW_RUNS_FAILED",
2033
+ domain: error.ErrorDomain.STORAGE,
2034
+ category: error.ErrorCategory.THIRD_PARTY
2035
+ },
2036
+ error$1
2037
+ );
2038
+ this.logger.trackException?.(mastraError);
2039
+ this.logger.error(mastraError.toString());
1209
2040
  return { runs: [], total: 0 };
1210
2041
  }
1211
2042
  }
1212
2043
  async getWorkflowRunById({
1213
- namespace,
1214
2044
  runId,
1215
2045
  workflowName
1216
2046
  }) {
1217
2047
  try {
1218
- if (!runId || !workflowName || !namespace) {
1219
- throw new Error("runId, workflowName, and namespace are required");
2048
+ if (!runId || !workflowName) {
2049
+ throw new Error("runId, workflowName, are required");
1220
2050
  }
1221
- const prefix = this.buildWorkflowSnapshotPrefix({ namespace, workflowName, runId });
1222
- const keyObjs = await this.listKV(storage.TABLE_WORKFLOW_SNAPSHOT, { prefix });
2051
+ const prefix = this.buildWorkflowSnapshotPrefix({ workflowName, runId });
2052
+ const keyObjs = await this.operations.listKV(storage.TABLE_WORKFLOW_SNAPSHOT, { prefix });
1223
2053
  if (!keyObjs.length) return null;
1224
- const key = keyObjs[0]?.name;
1225
- const data = await this.getKV(storage.TABLE_WORKFLOW_SNAPSHOT, key);
2054
+ const exactKey = keyObjs.find((k) => {
2055
+ const parts = k.name.split(":");
2056
+ const idx = parts.indexOf(storage.TABLE_WORKFLOW_SNAPSHOT);
2057
+ if (idx === -1 || parts.length < idx + 3) return false;
2058
+ const wfName = parts[idx + 1];
2059
+ const rId = parts[idx + 2];
2060
+ return wfName === workflowName && rId === runId;
2061
+ });
2062
+ if (!exactKey) return null;
2063
+ const data = await this.operations.getKV(storage.TABLE_WORKFLOW_SNAPSHOT, exactKey.name);
1226
2064
  if (!data) return null;
1227
- const state = this.normalizeWorkflowState(data.snapshot || data);
1228
- this.validateWorkflowState(state);
1229
- return this.parseWorkflowRun({ ...data, snapshot: state });
1230
- } catch (error) {
1231
- const message = error instanceof Error ? error.message : String(error);
1232
- this.logger.error("Error in getWorkflowRunById:", { message });
2065
+ const snapshotData = typeof data.snapshot === "string" ? JSON.parse(data.snapshot) : data.snapshot;
2066
+ return this.parseWorkflowRun({ ...data, snapshot: snapshotData });
2067
+ } catch (error$1) {
2068
+ const mastraError = new error.MastraError(
2069
+ {
2070
+ id: "CLOUDFLARE_STORAGE_GET_WORKFLOW_RUN_BY_ID_FAILED",
2071
+ domain: error.ErrorDomain.STORAGE,
2072
+ category: error.ErrorCategory.THIRD_PARTY,
2073
+ details: {
2074
+ workflowName,
2075
+ runId
2076
+ }
2077
+ },
2078
+ error$1
2079
+ );
2080
+ this.logger.trackException?.(mastraError);
2081
+ this.logger.error(mastraError.toString());
1233
2082
  return null;
1234
2083
  }
1235
2084
  }
2085
+ };
2086
+
2087
+ // src/storage/types.ts
2088
+ function isWorkersConfig(config) {
2089
+ return "bindings" in config;
2090
+ }
2091
+
2092
+ // src/storage/index.ts
2093
+ var CloudflareStore = class extends storage.MastraStorage {
2094
+ stores;
2095
+ client;
2096
+ accountId;
2097
+ namespacePrefix;
2098
+ bindings;
2099
+ validateWorkersConfig(config) {
2100
+ if (!isWorkersConfig(config)) {
2101
+ throw new Error("Invalid Workers API configuration");
2102
+ }
2103
+ if (!config.bindings) {
2104
+ throw new Error("KV bindings are required when using Workers Binding API");
2105
+ }
2106
+ const requiredTables = [
2107
+ storage.TABLE_THREADS,
2108
+ storage.TABLE_MESSAGES,
2109
+ storage.TABLE_WORKFLOW_SNAPSHOT,
2110
+ storage.TABLE_EVALS,
2111
+ storage.TABLE_SCORERS,
2112
+ storage.TABLE_TRACES
2113
+ ];
2114
+ for (const table of requiredTables) {
2115
+ if (!(table in config.bindings)) {
2116
+ throw new Error(`Missing KV binding for table: ${table}`);
2117
+ }
2118
+ }
2119
+ }
2120
+ validateRestConfig(config) {
2121
+ if (isWorkersConfig(config)) {
2122
+ throw new Error("Invalid REST API configuration");
2123
+ }
2124
+ if (!config.accountId?.trim()) {
2125
+ throw new Error("accountId is required for REST API");
2126
+ }
2127
+ if (!config.apiToken?.trim()) {
2128
+ throw new Error("apiToken is required for REST API");
2129
+ }
2130
+ }
2131
+ constructor(config) {
2132
+ super({ name: "Cloudflare" });
2133
+ try {
2134
+ if (isWorkersConfig(config)) {
2135
+ this.validateWorkersConfig(config);
2136
+ this.bindings = config.bindings;
2137
+ this.namespacePrefix = config.keyPrefix?.trim() || "";
2138
+ this.logger.info("Using Cloudflare KV Workers Binding API");
2139
+ } else {
2140
+ this.validateRestConfig(config);
2141
+ this.accountId = config.accountId.trim();
2142
+ this.namespacePrefix = config.namespacePrefix?.trim() || "";
2143
+ this.client = new Cloudflare__default.default({
2144
+ apiToken: config.apiToken.trim()
2145
+ });
2146
+ this.logger.info("Using Cloudflare KV REST API");
2147
+ }
2148
+ const operations = new StoreOperationsCloudflare({
2149
+ accountId: this.accountId,
2150
+ client: this.client,
2151
+ namespacePrefix: this.namespacePrefix,
2152
+ bindings: this.bindings
2153
+ });
2154
+ const legacyEvals = new LegacyEvalsStorageCloudflare({
2155
+ operations
2156
+ });
2157
+ const workflows = new WorkflowsStorageCloudflare({
2158
+ operations
2159
+ });
2160
+ const traces = new TracesStorageCloudflare({
2161
+ operations
2162
+ });
2163
+ const memory = new MemoryStorageCloudflare({
2164
+ operations
2165
+ });
2166
+ const scores = new ScoresStorageCloudflare({
2167
+ operations
2168
+ });
2169
+ this.stores = {
2170
+ operations,
2171
+ legacyEvals,
2172
+ workflows,
2173
+ traces,
2174
+ memory,
2175
+ scores
2176
+ };
2177
+ } catch (error$1) {
2178
+ throw new error.MastraError(
2179
+ {
2180
+ id: "CLOUDFLARE_STORAGE_INIT_FAILED",
2181
+ domain: error.ErrorDomain.STORAGE,
2182
+ category: error.ErrorCategory.THIRD_PARTY
2183
+ },
2184
+ error$1
2185
+ );
2186
+ }
2187
+ }
2188
+ async createTable({
2189
+ tableName,
2190
+ schema
2191
+ }) {
2192
+ return this.stores.operations.createTable({ tableName, schema });
2193
+ }
2194
+ async alterTable(_args) {
2195
+ return this.stores.operations.alterTable(_args);
2196
+ }
2197
+ async clearTable({ tableName }) {
2198
+ return this.stores.operations.clearTable({ tableName });
2199
+ }
2200
+ async dropTable({ tableName }) {
2201
+ return this.stores.operations.dropTable({ tableName });
2202
+ }
2203
+ async insert({
2204
+ tableName,
2205
+ record
2206
+ }) {
2207
+ return this.stores.operations.insert({ tableName, record });
2208
+ }
2209
+ async load({ tableName, keys }) {
2210
+ return this.stores.operations.load({ tableName, keys });
2211
+ }
2212
+ async getThreadById({ threadId }) {
2213
+ return this.stores.memory.getThreadById({ threadId });
2214
+ }
2215
+ async getThreadsByResourceId({ resourceId }) {
2216
+ return this.stores.memory.getThreadsByResourceId({ resourceId });
2217
+ }
2218
+ async saveThread({ thread }) {
2219
+ return this.stores.memory.saveThread({ thread });
2220
+ }
2221
+ async updateThread({
2222
+ id,
2223
+ title,
2224
+ metadata
2225
+ }) {
2226
+ return this.stores.memory.updateThread({ id, title, metadata });
2227
+ }
2228
+ async deleteThread({ threadId }) {
2229
+ return this.stores.memory.deleteThread({ threadId });
2230
+ }
2231
+ async saveMessages(args) {
2232
+ return this.stores.memory.saveMessages(args);
2233
+ }
2234
+ async getMessages({
2235
+ threadId,
2236
+ resourceId,
2237
+ selectBy,
2238
+ format
2239
+ }) {
2240
+ return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
2241
+ }
2242
+ async persistWorkflowSnapshot(params) {
2243
+ return this.stores.workflows.persistWorkflowSnapshot(params);
2244
+ }
2245
+ async loadWorkflowSnapshot(params) {
2246
+ return this.stores.workflows.loadWorkflowSnapshot(params);
2247
+ }
2248
+ async batchInsert(input) {
2249
+ return this.stores.operations.batchInsert(input);
2250
+ }
2251
+ async getTraces({
2252
+ name,
2253
+ scope,
2254
+ page = 0,
2255
+ perPage = 100,
2256
+ attributes,
2257
+ fromDate,
2258
+ toDate
2259
+ }) {
2260
+ return this.stores.traces.getTraces({
2261
+ name,
2262
+ scope,
2263
+ page,
2264
+ perPage,
2265
+ attributes,
2266
+ fromDate,
2267
+ toDate
2268
+ });
2269
+ }
2270
+ async getEvalsByAgentName(agentName, type) {
2271
+ return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
2272
+ }
2273
+ async getEvals(options) {
2274
+ return this.stores.legacyEvals.getEvals(options);
2275
+ }
2276
+ async getWorkflowRuns({
2277
+ workflowName,
2278
+ limit = 20,
2279
+ offset = 0,
2280
+ resourceId,
2281
+ fromDate,
2282
+ toDate
2283
+ } = {}) {
2284
+ return this.stores.workflows.getWorkflowRuns({
2285
+ workflowName,
2286
+ limit,
2287
+ offset,
2288
+ resourceId,
2289
+ fromDate,
2290
+ toDate
2291
+ });
2292
+ }
2293
+ async getWorkflowRunById({
2294
+ runId,
2295
+ workflowName
2296
+ }) {
2297
+ return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
2298
+ }
2299
+ async getTracesPaginated(args) {
2300
+ return this.stores.traces.getTracesPaginated(args);
2301
+ }
2302
+ async getThreadsByResourceIdPaginated(args) {
2303
+ return this.stores.memory.getThreadsByResourceIdPaginated(args);
2304
+ }
2305
+ async getMessagesPaginated(args) {
2306
+ return this.stores.memory.getMessagesPaginated(args);
2307
+ }
2308
+ async updateMessages(args) {
2309
+ return this.stores.memory.updateMessages(args);
2310
+ }
2311
+ async getScoreById({ id }) {
2312
+ return this.stores.scores.getScoreById({ id });
2313
+ }
2314
+ async saveScore(score) {
2315
+ return this.stores.scores.saveScore(score);
2316
+ }
2317
+ async getScoresByRunId({
2318
+ runId,
2319
+ pagination
2320
+ }) {
2321
+ return this.stores.scores.getScoresByRunId({ runId, pagination });
2322
+ }
2323
+ async getScoresByEntityId({
2324
+ entityId,
2325
+ entityType,
2326
+ pagination
2327
+ }) {
2328
+ return this.stores.scores.getScoresByEntityId({ entityId, entityType, pagination });
2329
+ }
2330
+ async getScoresByScorerId({
2331
+ scorerId,
2332
+ pagination
2333
+ }) {
2334
+ return this.stores.scores.getScoresByScorerId({ scorerId, pagination });
2335
+ }
2336
+ async getResourceById({ resourceId }) {
2337
+ return this.stores.memory.getResourceById({ resourceId });
2338
+ }
2339
+ async saveResource({ resource }) {
2340
+ return this.stores.memory.saveResource({ resource });
2341
+ }
2342
+ async updateResource({
2343
+ resourceId,
2344
+ workingMemory,
2345
+ metadata
2346
+ }) {
2347
+ return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
2348
+ }
1236
2349
  async close() {
1237
2350
  }
1238
2351
  };