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