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