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