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