@mastra/cloudflare-d1 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-transpile-packages-20250724123433
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +11 -42
- package/README.md +15 -0
- package/dist/_tsup-dts-rollup.d.cts +414 -67
- package/dist/_tsup-dts-rollup.d.ts +414 -67
- package/dist/index.cjs +1799 -535
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1790 -526
- package/package.json +15 -14
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var error = require('@mastra/core/error');
|
|
4
4
|
var storage = require('@mastra/core/storage');
|
|
5
5
|
var Cloudflare = require('cloudflare');
|
|
6
6
|
var utils = require('@mastra/core/utils');
|
|
7
|
+
var agent = require('@mastra/core/agent');
|
|
7
8
|
|
|
8
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
10
|
|
|
@@ -240,358 +241,416 @@ function parseSelectIdentifier(column) {
|
|
|
240
241
|
return column;
|
|
241
242
|
}
|
|
242
243
|
|
|
243
|
-
// src/storage/
|
|
244
|
+
// src/storage/domains/utils.ts
|
|
244
245
|
function isArrayOfRecords(value) {
|
|
245
246
|
return value && Array.isArray(value) && value.length > 0;
|
|
246
247
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
*/
|
|
258
|
-
constructor(config) {
|
|
259
|
-
super({ name: "D1" });
|
|
260
|
-
if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
|
|
261
|
-
throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
|
|
262
|
-
}
|
|
263
|
-
this.tablePrefix = config.tablePrefix || "";
|
|
264
|
-
if ("binding" in config) {
|
|
265
|
-
if (!config.binding) {
|
|
266
|
-
throw new Error("D1 binding is required when using Workers Binding API");
|
|
267
|
-
}
|
|
268
|
-
this.binding = config.binding;
|
|
269
|
-
this.logger.info("Using D1 Workers Binding API");
|
|
270
|
-
} else {
|
|
271
|
-
if (!config.accountId || !config.databaseId || !config.apiToken) {
|
|
272
|
-
throw new Error("accountId, databaseId, and apiToken are required when using REST API");
|
|
273
|
-
}
|
|
274
|
-
this.accountId = config.accountId;
|
|
275
|
-
this.databaseId = config.databaseId;
|
|
276
|
-
this.client = new Cloudflare__default.default({
|
|
277
|
-
apiToken: config.apiToken
|
|
278
|
-
});
|
|
279
|
-
this.logger.info("Using D1 REST API");
|
|
248
|
+
function deserializeValue(value, type) {
|
|
249
|
+
if (value === null || value === void 0) return null;
|
|
250
|
+
if (type === "date" && typeof value === "string") {
|
|
251
|
+
return new Date(value);
|
|
252
|
+
}
|
|
253
|
+
if (type === "jsonb" && typeof value === "string") {
|
|
254
|
+
try {
|
|
255
|
+
return JSON.parse(value);
|
|
256
|
+
} catch {
|
|
257
|
+
return value;
|
|
280
258
|
}
|
|
281
259
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
260
|
+
if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
|
|
261
|
+
try {
|
|
262
|
+
return JSON.parse(value);
|
|
263
|
+
} catch {
|
|
264
|
+
return value;
|
|
265
|
+
}
|
|
285
266
|
}
|
|
286
|
-
|
|
287
|
-
|
|
267
|
+
return value;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/storage/domains/legacy-evals/index.ts
|
|
271
|
+
var LegacyEvalsStorageD1 = class extends storage.LegacyEvalsStorage {
|
|
272
|
+
operations;
|
|
273
|
+
constructor({ operations }) {
|
|
274
|
+
super();
|
|
275
|
+
this.operations = operations;
|
|
288
276
|
}
|
|
289
|
-
async
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
if (
|
|
295
|
-
|
|
277
|
+
async getEvals(options) {
|
|
278
|
+
const { agentName, type, page = 0, perPage = 40, dateRange } = options || {};
|
|
279
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_EVALS);
|
|
280
|
+
const conditions = [];
|
|
281
|
+
const queryParams = [];
|
|
282
|
+
if (agentName) {
|
|
283
|
+
conditions.push(`agent_name = ?`);
|
|
284
|
+
queryParams.push(agentName);
|
|
296
285
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (formattedParams.length > 0) {
|
|
302
|
-
if (first) {
|
|
303
|
-
result = await statement.bind(...formattedParams).first();
|
|
304
|
-
if (!result) return null;
|
|
305
|
-
return result;
|
|
306
|
-
} else {
|
|
307
|
-
result = await statement.bind(...formattedParams).all();
|
|
308
|
-
const results = result.results || [];
|
|
309
|
-
if (result.meta) {
|
|
310
|
-
this.logger.debug("Query metadata", { meta: result.meta });
|
|
311
|
-
}
|
|
312
|
-
return results;
|
|
313
|
-
}
|
|
314
|
-
} else {
|
|
315
|
-
if (first) {
|
|
316
|
-
result = await statement.first();
|
|
317
|
-
if (!result) return null;
|
|
318
|
-
return result;
|
|
319
|
-
} else {
|
|
320
|
-
result = await statement.all();
|
|
321
|
-
const results = result.results || [];
|
|
322
|
-
if (result.meta) {
|
|
323
|
-
this.logger.debug("Query metadata", { meta: result.meta });
|
|
324
|
-
}
|
|
325
|
-
return results;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
} catch (workerError) {
|
|
329
|
-
this.logger.error("Workers Binding API error", {
|
|
330
|
-
message: workerError instanceof Error ? workerError.message : String(workerError),
|
|
331
|
-
sql
|
|
332
|
-
});
|
|
333
|
-
throw new Error(`D1 Workers API error: ${workerError.message}`);
|
|
286
|
+
if (type === "test") {
|
|
287
|
+
conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
|
|
288
|
+
} else if (type === "live") {
|
|
289
|
+
conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
|
|
334
290
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
291
|
+
if (dateRange?.start) {
|
|
292
|
+
conditions.push(`created_at >= ?`);
|
|
293
|
+
queryParams.push(storage.serializeDate(dateRange.start));
|
|
294
|
+
}
|
|
295
|
+
if (dateRange?.end) {
|
|
296
|
+
conditions.push(`created_at <= ?`);
|
|
297
|
+
queryParams.push(storage.serializeDate(dateRange.end));
|
|
298
|
+
}
|
|
299
|
+
const countQueryBuilder = createSqlBuilder().count().from(fullTableName);
|
|
300
|
+
if (conditions.length > 0) {
|
|
301
|
+
countQueryBuilder.where(conditions.join(" AND "), ...queryParams);
|
|
343
302
|
}
|
|
303
|
+
const { sql: countSql, params: countParams } = countQueryBuilder.build();
|
|
344
304
|
try {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
305
|
+
const countResult = await this.operations.executeQuery({
|
|
306
|
+
sql: countSql,
|
|
307
|
+
params: countParams,
|
|
308
|
+
first: true
|
|
349
309
|
});
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
if (
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
310
|
+
const total = Number(countResult?.count || 0);
|
|
311
|
+
const currentOffset = page * perPage;
|
|
312
|
+
if (total === 0) {
|
|
313
|
+
return {
|
|
314
|
+
evals: [],
|
|
315
|
+
total: 0,
|
|
316
|
+
page,
|
|
317
|
+
perPage,
|
|
318
|
+
hasMore: false
|
|
319
|
+
};
|
|
356
320
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
321
|
+
const dataQueryBuilder = createSqlBuilder().select("*").from(fullTableName);
|
|
322
|
+
if (conditions.length > 0) {
|
|
323
|
+
dataQueryBuilder.where(conditions.join(" AND "), ...queryParams);
|
|
324
|
+
}
|
|
325
|
+
dataQueryBuilder.orderBy("created_at", "DESC").limit(perPage).offset(currentOffset);
|
|
326
|
+
const { sql: dataSql, params: dataParams } = dataQueryBuilder.build();
|
|
327
|
+
const rows = await this.operations.executeQuery({
|
|
328
|
+
sql: dataSql,
|
|
329
|
+
params: dataParams
|
|
330
|
+
});
|
|
331
|
+
const evals = (isArrayOfRecords(rows) ? rows : []).map((row) => {
|
|
332
|
+
const result = deserializeValue(row.result);
|
|
333
|
+
const testInfo = row.test_info ? deserializeValue(row.test_info) : void 0;
|
|
334
|
+
if (!result || typeof result !== "object" || !("score" in result)) {
|
|
335
|
+
throw new Error(`Invalid MetricResult format: ${JSON.stringify(result)}`);
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
input: row.input,
|
|
339
|
+
output: row.output,
|
|
340
|
+
result,
|
|
341
|
+
agentName: row.agent_name,
|
|
342
|
+
metricName: row.metric_name,
|
|
343
|
+
instructions: row.instructions,
|
|
344
|
+
testInfo,
|
|
345
|
+
globalRunId: row.global_run_id,
|
|
346
|
+
runId: row.run_id,
|
|
347
|
+
createdAt: row.created_at
|
|
348
|
+
};
|
|
362
349
|
});
|
|
363
|
-
|
|
350
|
+
const hasMore = currentOffset + evals.length < total;
|
|
351
|
+
return {
|
|
352
|
+
evals,
|
|
353
|
+
total,
|
|
354
|
+
page,
|
|
355
|
+
perPage,
|
|
356
|
+
hasMore
|
|
357
|
+
};
|
|
358
|
+
} catch (error$1) {
|
|
359
|
+
throw new error.MastraError(
|
|
360
|
+
{
|
|
361
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_EVALS_ERROR",
|
|
362
|
+
domain: error.ErrorDomain.STORAGE,
|
|
363
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
364
|
+
text: `Failed to retrieve evals for agent ${agentName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
365
|
+
details: { agentName: agentName ?? "", type: type ?? "" }
|
|
366
|
+
},
|
|
367
|
+
error$1
|
|
368
|
+
);
|
|
364
369
|
}
|
|
365
370
|
}
|
|
366
371
|
/**
|
|
367
|
-
*
|
|
368
|
-
* @param options Query options including SQL, parameters, and whether to return only the first result
|
|
369
|
-
* @returns Query results as an array or a single object if first=true
|
|
372
|
+
* @deprecated use getEvals instead
|
|
370
373
|
*/
|
|
371
|
-
async
|
|
372
|
-
const
|
|
374
|
+
async getEvalsByAgentName(agentName, type) {
|
|
375
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_EVALS);
|
|
373
376
|
try {
|
|
374
|
-
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
} else if (
|
|
378
|
-
|
|
379
|
-
} else {
|
|
380
|
-
throw new Error("No valid D1 configuration provided");
|
|
377
|
+
let query = createSqlBuilder().select("*").from(fullTableName).where("agent_name = ?", agentName);
|
|
378
|
+
if (type === "test") {
|
|
379
|
+
query = query.andWhere("test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL");
|
|
380
|
+
} else if (type === "live") {
|
|
381
|
+
query = query.andWhere("(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)");
|
|
381
382
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
serializeDate(date) {
|
|
416
|
-
if (!date) return void 0;
|
|
417
|
-
const dateObj = this.ensureDate(date);
|
|
418
|
-
return dateObj?.toISOString();
|
|
419
|
-
}
|
|
420
|
-
// Helper to serialize objects to JSON strings
|
|
421
|
-
serializeValue(value) {
|
|
422
|
-
if (value === null || value === void 0) return null;
|
|
423
|
-
if (value instanceof Date) {
|
|
424
|
-
return this.serializeDate(value);
|
|
425
|
-
}
|
|
426
|
-
if (typeof value === "object") {
|
|
427
|
-
return JSON.stringify(value);
|
|
383
|
+
query.orderBy("created_at", "DESC");
|
|
384
|
+
const { sql, params } = query.build();
|
|
385
|
+
const results = await this.operations.executeQuery({ sql, params });
|
|
386
|
+
return isArrayOfRecords(results) ? results.map((row) => {
|
|
387
|
+
const result = deserializeValue(row.result);
|
|
388
|
+
const testInfo = row.test_info ? deserializeValue(row.test_info) : void 0;
|
|
389
|
+
return {
|
|
390
|
+
input: row.input || "",
|
|
391
|
+
output: row.output || "",
|
|
392
|
+
result,
|
|
393
|
+
agentName: row.agent_name || "",
|
|
394
|
+
metricName: row.metric_name || "",
|
|
395
|
+
instructions: row.instructions || "",
|
|
396
|
+
runId: row.run_id || "",
|
|
397
|
+
globalRunId: row.global_run_id || "",
|
|
398
|
+
createdAt: row.created_at || "",
|
|
399
|
+
testInfo
|
|
400
|
+
};
|
|
401
|
+
}) : [];
|
|
402
|
+
} catch (error$1) {
|
|
403
|
+
const mastraError = new error.MastraError(
|
|
404
|
+
{
|
|
405
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_EVALS_ERROR",
|
|
406
|
+
domain: error.ErrorDomain.STORAGE,
|
|
407
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
408
|
+
text: `Failed to retrieve evals for agent ${agentName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
409
|
+
details: { agentName }
|
|
410
|
+
},
|
|
411
|
+
error$1
|
|
412
|
+
);
|
|
413
|
+
this.logger?.error(mastraError.toString());
|
|
414
|
+
this.logger?.trackException(mastraError);
|
|
415
|
+
return [];
|
|
428
416
|
}
|
|
429
|
-
return value;
|
|
430
417
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (type === "jsonb" && typeof value === "string") {
|
|
438
|
-
try {
|
|
439
|
-
return JSON.parse(value);
|
|
440
|
-
} catch {
|
|
441
|
-
return value;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
|
|
445
|
-
try {
|
|
446
|
-
return JSON.parse(value);
|
|
447
|
-
} catch {
|
|
448
|
-
return value;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
return value;
|
|
418
|
+
};
|
|
419
|
+
var MemoryStorageD1 = class extends storage.MemoryStorage {
|
|
420
|
+
operations;
|
|
421
|
+
constructor({ operations }) {
|
|
422
|
+
super();
|
|
423
|
+
this.operations = operations;
|
|
452
424
|
}
|
|
453
|
-
async
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const fullTableName = this.getTableName(tableName);
|
|
458
|
-
const columnDefinitions = Object.entries(schema).map(([colName, colDef]) => {
|
|
459
|
-
const type = this.getSqlType(colDef.type);
|
|
460
|
-
const nullable = colDef.nullable === false ? "NOT NULL" : "";
|
|
461
|
-
const primaryKey = colDef.primaryKey ? "PRIMARY KEY" : "";
|
|
462
|
-
return `${colName} ${type} ${nullable} ${primaryKey}`.trim();
|
|
425
|
+
async getResourceById({ resourceId }) {
|
|
426
|
+
const resource = await this.operations.load({
|
|
427
|
+
tableName: storage.TABLE_RESOURCES,
|
|
428
|
+
keys: { id: resourceId }
|
|
463
429
|
});
|
|
464
|
-
|
|
465
|
-
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
466
|
-
tableConstraints.push("UNIQUE (workflow_name, run_id)");
|
|
467
|
-
}
|
|
468
|
-
const query = createSqlBuilder().createTable(fullTableName, columnDefinitions, tableConstraints);
|
|
469
|
-
const { sql, params } = query.build();
|
|
470
|
-
try {
|
|
471
|
-
await this.executeQuery({ sql, params });
|
|
472
|
-
this.logger.debug(`Created table ${fullTableName}`);
|
|
473
|
-
} catch (error) {
|
|
474
|
-
this.logger.error(`Error creating table ${fullTableName}:`, {
|
|
475
|
-
message: error instanceof Error ? error.message : String(error)
|
|
476
|
-
});
|
|
477
|
-
throw new Error(`Failed to create table ${fullTableName}: ${error}`);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
async clearTable({ tableName }) {
|
|
481
|
-
const fullTableName = this.getTableName(tableName);
|
|
430
|
+
if (!resource) return null;
|
|
482
431
|
try {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
432
|
+
return {
|
|
433
|
+
...resource,
|
|
434
|
+
createdAt: storage.ensureDate(resource.createdAt),
|
|
435
|
+
updatedAt: storage.ensureDate(resource.updatedAt),
|
|
436
|
+
metadata: typeof resource.metadata === "string" ? JSON.parse(resource.metadata || "{}") : resource.metadata
|
|
437
|
+
};
|
|
438
|
+
} catch (error$1) {
|
|
439
|
+
const mastraError = new error.MastraError(
|
|
440
|
+
{
|
|
441
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_RESOURCE_BY_ID_ERROR",
|
|
442
|
+
domain: error.ErrorDomain.STORAGE,
|
|
443
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
444
|
+
text: `Error processing resource ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
445
|
+
details: { resourceId }
|
|
446
|
+
},
|
|
447
|
+
error$1
|
|
448
|
+
);
|
|
449
|
+
this.logger?.error(mastraError.toString());
|
|
450
|
+
this.logger?.trackException(mastraError);
|
|
451
|
+
return null;
|
|
498
452
|
}
|
|
499
|
-
return processedRecord;
|
|
500
453
|
}
|
|
501
|
-
async
|
|
502
|
-
const fullTableName = this.getTableName(
|
|
503
|
-
const
|
|
454
|
+
async saveResource({ resource }) {
|
|
455
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_RESOURCES);
|
|
456
|
+
const resourceToSave = {
|
|
457
|
+
id: resource.id,
|
|
458
|
+
workingMemory: resource.workingMemory,
|
|
459
|
+
metadata: resource.metadata ? JSON.stringify(resource.metadata) : null,
|
|
460
|
+
createdAt: resource.createdAt,
|
|
461
|
+
updatedAt: resource.updatedAt
|
|
462
|
+
};
|
|
463
|
+
const processedRecord = await this.operations.processRecord(resourceToSave);
|
|
504
464
|
const columns = Object.keys(processedRecord);
|
|
505
465
|
const values = Object.values(processedRecord);
|
|
506
|
-
const
|
|
466
|
+
const updateMap = {
|
|
467
|
+
workingMemory: "excluded.workingMemory",
|
|
468
|
+
metadata: "excluded.metadata",
|
|
469
|
+
createdAt: "excluded.createdAt",
|
|
470
|
+
updatedAt: "excluded.updatedAt"
|
|
471
|
+
};
|
|
472
|
+
const query = createSqlBuilder().insert(fullTableName, columns, values, ["id"], updateMap);
|
|
507
473
|
const { sql, params } = query.build();
|
|
508
474
|
try {
|
|
509
|
-
await this.executeQuery({ sql, params });
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
475
|
+
await this.operations.executeQuery({ sql, params });
|
|
476
|
+
return resource;
|
|
477
|
+
} catch (error$1) {
|
|
478
|
+
throw new error.MastraError(
|
|
479
|
+
{
|
|
480
|
+
id: "CLOUDFLARE_D1_STORAGE_SAVE_RESOURCE_ERROR",
|
|
481
|
+
domain: error.ErrorDomain.STORAGE,
|
|
482
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
483
|
+
text: `Failed to save resource to ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
484
|
+
details: { resourceId: resource.id }
|
|
485
|
+
},
|
|
486
|
+
error$1
|
|
487
|
+
);
|
|
514
488
|
}
|
|
515
489
|
}
|
|
516
|
-
async
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
490
|
+
async updateResource({
|
|
491
|
+
resourceId,
|
|
492
|
+
workingMemory,
|
|
493
|
+
metadata
|
|
494
|
+
}) {
|
|
495
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
496
|
+
if (!existingResource) {
|
|
497
|
+
const newResource = {
|
|
498
|
+
id: resourceId,
|
|
499
|
+
workingMemory,
|
|
500
|
+
metadata: metadata || {},
|
|
501
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
502
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
503
|
+
};
|
|
504
|
+
return this.saveResource({ resource: newResource });
|
|
527
505
|
}
|
|
528
|
-
|
|
506
|
+
const updatedAt = /* @__PURE__ */ new Date();
|
|
507
|
+
const updatedResource = {
|
|
508
|
+
...existingResource,
|
|
509
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
510
|
+
metadata: {
|
|
511
|
+
...existingResource.metadata,
|
|
512
|
+
...metadata
|
|
513
|
+
},
|
|
514
|
+
updatedAt
|
|
515
|
+
};
|
|
516
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_RESOURCES);
|
|
517
|
+
const columns = ["workingMemory", "metadata", "updatedAt"];
|
|
518
|
+
const values = [updatedResource.workingMemory, JSON.stringify(updatedResource.metadata), updatedAt.toISOString()];
|
|
519
|
+
const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", resourceId);
|
|
529
520
|
const { sql, params } = query.build();
|
|
530
521
|
try {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
522
|
+
await this.operations.executeQuery({ sql, params });
|
|
523
|
+
return updatedResource;
|
|
524
|
+
} catch (error$1) {
|
|
525
|
+
throw new error.MastraError(
|
|
526
|
+
{
|
|
527
|
+
id: "CLOUDFLARE_D1_STORAGE_UPDATE_RESOURCE_ERROR",
|
|
528
|
+
domain: error.ErrorDomain.STORAGE,
|
|
529
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
530
|
+
text: `Failed to update resource ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
531
|
+
details: { resourceId }
|
|
532
|
+
},
|
|
533
|
+
error$1
|
|
534
|
+
);
|
|
543
535
|
}
|
|
544
536
|
}
|
|
545
537
|
async getThreadById({ threadId }) {
|
|
546
|
-
const thread = await this.load({
|
|
538
|
+
const thread = await this.operations.load({
|
|
547
539
|
tableName: storage.TABLE_THREADS,
|
|
548
540
|
keys: { id: threadId }
|
|
549
541
|
});
|
|
550
542
|
if (!thread) return null;
|
|
543
|
+
console.log("thread", thread);
|
|
551
544
|
try {
|
|
552
545
|
return {
|
|
553
546
|
...thread,
|
|
554
|
-
createdAt:
|
|
555
|
-
updatedAt:
|
|
547
|
+
createdAt: storage.ensureDate(thread.createdAt),
|
|
548
|
+
updatedAt: storage.ensureDate(thread.updatedAt),
|
|
556
549
|
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata || "{}") : thread.metadata || {}
|
|
557
550
|
};
|
|
558
|
-
} catch (error) {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
551
|
+
} catch (error$1) {
|
|
552
|
+
const mastraError = new error.MastraError(
|
|
553
|
+
{
|
|
554
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_THREAD_BY_ID_ERROR",
|
|
555
|
+
domain: error.ErrorDomain.STORAGE,
|
|
556
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
557
|
+
text: `Error processing thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
558
|
+
details: { threadId }
|
|
559
|
+
},
|
|
560
|
+
error$1
|
|
561
|
+
);
|
|
562
|
+
this.logger?.error(mastraError.toString());
|
|
563
|
+
this.logger?.trackException(mastraError);
|
|
562
564
|
return null;
|
|
563
565
|
}
|
|
564
566
|
}
|
|
567
|
+
/**
|
|
568
|
+
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
569
|
+
*/
|
|
565
570
|
async getThreadsByResourceId({ resourceId }) {
|
|
566
|
-
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
571
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_THREADS);
|
|
567
572
|
try {
|
|
568
573
|
const query = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId);
|
|
569
574
|
const { sql, params } = query.build();
|
|
570
|
-
const results = await this.executeQuery({ sql, params });
|
|
575
|
+
const results = await this.operations.executeQuery({ sql, params });
|
|
571
576
|
return (isArrayOfRecords(results) ? results : []).map((thread) => ({
|
|
572
577
|
...thread,
|
|
573
|
-
createdAt:
|
|
574
|
-
updatedAt:
|
|
578
|
+
createdAt: storage.ensureDate(thread.createdAt),
|
|
579
|
+
updatedAt: storage.ensureDate(thread.updatedAt),
|
|
575
580
|
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata || "{}") : thread.metadata || {}
|
|
576
581
|
}));
|
|
577
|
-
} catch (error) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
582
|
+
} catch (error$1) {
|
|
583
|
+
const mastraError = new error.MastraError(
|
|
584
|
+
{
|
|
585
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_THREADS_BY_RESOURCE_ID_ERROR",
|
|
586
|
+
domain: error.ErrorDomain.STORAGE,
|
|
587
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
588
|
+
text: `Error getting threads by resourceId ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
589
|
+
details: { resourceId }
|
|
590
|
+
},
|
|
591
|
+
error$1
|
|
592
|
+
);
|
|
593
|
+
this.logger?.error(mastraError.toString());
|
|
594
|
+
this.logger?.trackException(mastraError);
|
|
581
595
|
return [];
|
|
582
596
|
}
|
|
583
597
|
}
|
|
598
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
599
|
+
const { resourceId, page, perPage } = args;
|
|
600
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_THREADS);
|
|
601
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
602
|
+
...row,
|
|
603
|
+
createdAt: storage.ensureDate(row.createdAt),
|
|
604
|
+
updatedAt: storage.ensureDate(row.updatedAt),
|
|
605
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
|
|
606
|
+
});
|
|
607
|
+
try {
|
|
608
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
|
|
609
|
+
const countResult = await this.operations.executeQuery(countQuery.build());
|
|
610
|
+
const total = Number(countResult?.[0]?.count ?? 0);
|
|
611
|
+
const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
|
|
612
|
+
const results = await this.operations.executeQuery(selectQuery.build());
|
|
613
|
+
const threads = results.map(mapRowToStorageThreadType);
|
|
614
|
+
return {
|
|
615
|
+
threads,
|
|
616
|
+
total,
|
|
617
|
+
page,
|
|
618
|
+
perPage,
|
|
619
|
+
hasMore: page * perPage + threads.length < total
|
|
620
|
+
};
|
|
621
|
+
} catch (error$1) {
|
|
622
|
+
const mastraError = new error.MastraError(
|
|
623
|
+
{
|
|
624
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_ERROR",
|
|
625
|
+
domain: error.ErrorDomain.STORAGE,
|
|
626
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
627
|
+
text: `Error getting threads by resourceId ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
628
|
+
details: { resourceId }
|
|
629
|
+
},
|
|
630
|
+
error$1
|
|
631
|
+
);
|
|
632
|
+
this.logger?.error(mastraError.toString());
|
|
633
|
+
this.logger?.trackException(mastraError);
|
|
634
|
+
return {
|
|
635
|
+
threads: [],
|
|
636
|
+
total: 0,
|
|
637
|
+
page,
|
|
638
|
+
perPage,
|
|
639
|
+
hasMore: false
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
}
|
|
584
643
|
async saveThread({ thread }) {
|
|
585
|
-
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
644
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_THREADS);
|
|
586
645
|
const threadToSave = {
|
|
587
646
|
id: thread.id,
|
|
588
647
|
resourceId: thread.resourceId,
|
|
589
648
|
title: thread.title,
|
|
590
649
|
metadata: thread.metadata ? JSON.stringify(thread.metadata) : null,
|
|
591
|
-
createdAt: thread.createdAt,
|
|
592
|
-
updatedAt: thread.updatedAt
|
|
650
|
+
createdAt: thread.createdAt.toISOString(),
|
|
651
|
+
updatedAt: thread.updatedAt.toISOString()
|
|
593
652
|
};
|
|
594
|
-
const processedRecord = await this.processRecord(threadToSave);
|
|
653
|
+
const processedRecord = await this.operations.processRecord(threadToSave);
|
|
595
654
|
const columns = Object.keys(processedRecord);
|
|
596
655
|
const values = Object.values(processedRecord);
|
|
597
656
|
const updateMap = {
|
|
@@ -604,12 +663,19 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
604
663
|
const query = createSqlBuilder().insert(fullTableName, columns, values, ["id"], updateMap);
|
|
605
664
|
const { sql, params } = query.build();
|
|
606
665
|
try {
|
|
607
|
-
await this.executeQuery({ sql, params });
|
|
666
|
+
await this.operations.executeQuery({ sql, params });
|
|
608
667
|
return thread;
|
|
609
|
-
} catch (error) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
668
|
+
} catch (error$1) {
|
|
669
|
+
throw new error.MastraError(
|
|
670
|
+
{
|
|
671
|
+
id: "CLOUDFLARE_D1_STORAGE_SAVE_THREAD_ERROR",
|
|
672
|
+
domain: error.ErrorDomain.STORAGE,
|
|
673
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
674
|
+
text: `Failed to save thread to ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
675
|
+
details: { threadId: thread.id }
|
|
676
|
+
},
|
|
677
|
+
error$1
|
|
678
|
+
);
|
|
613
679
|
}
|
|
614
680
|
}
|
|
615
681
|
async updateThread({
|
|
@@ -618,20 +684,21 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
618
684
|
metadata
|
|
619
685
|
}) {
|
|
620
686
|
const thread = await this.getThreadById({ threadId: id });
|
|
621
|
-
if (!thread) {
|
|
622
|
-
throw new Error(`Thread ${id} not found`);
|
|
623
|
-
}
|
|
624
|
-
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
625
|
-
const mergedMetadata = {
|
|
626
|
-
...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
627
|
-
...metadata
|
|
628
|
-
};
|
|
629
|
-
const columns = ["title", "metadata", "updatedAt"];
|
|
630
|
-
const values = [title, JSON.stringify(mergedMetadata), (/* @__PURE__ */ new Date()).toISOString()];
|
|
631
|
-
const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", id);
|
|
632
|
-
const { sql, params } = query.build();
|
|
633
687
|
try {
|
|
634
|
-
|
|
688
|
+
if (!thread) {
|
|
689
|
+
throw new Error(`Thread ${id} not found`);
|
|
690
|
+
}
|
|
691
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_THREADS);
|
|
692
|
+
const mergedMetadata = {
|
|
693
|
+
...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
694
|
+
...metadata
|
|
695
|
+
};
|
|
696
|
+
const updatedAt = /* @__PURE__ */ new Date();
|
|
697
|
+
const columns = ["title", "metadata", "updatedAt"];
|
|
698
|
+
const values = [title, JSON.stringify(mergedMetadata), updatedAt.toISOString()];
|
|
699
|
+
const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", id);
|
|
700
|
+
const { sql, params } = query.build();
|
|
701
|
+
await this.operations.executeQuery({ sql, params });
|
|
635
702
|
return {
|
|
636
703
|
...thread,
|
|
637
704
|
title,
|
|
@@ -639,29 +706,42 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
639
706
|
...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
640
707
|
...metadata
|
|
641
708
|
},
|
|
642
|
-
updatedAt
|
|
709
|
+
updatedAt
|
|
643
710
|
};
|
|
644
|
-
} catch (error) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
711
|
+
} catch (error$1) {
|
|
712
|
+
throw new error.MastraError(
|
|
713
|
+
{
|
|
714
|
+
id: "CLOUDFLARE_D1_STORAGE_UPDATE_THREAD_ERROR",
|
|
715
|
+
domain: error.ErrorDomain.STORAGE,
|
|
716
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
717
|
+
text: `Failed to update thread ${id}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
718
|
+
details: { threadId: id }
|
|
719
|
+
},
|
|
720
|
+
error$1
|
|
721
|
+
);
|
|
648
722
|
}
|
|
649
723
|
}
|
|
650
724
|
async deleteThread({ threadId }) {
|
|
651
|
-
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
725
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_THREADS);
|
|
652
726
|
try {
|
|
653
727
|
const deleteThreadQuery = createSqlBuilder().delete(fullTableName).where("id = ?", threadId);
|
|
654
728
|
const { sql: threadSql, params: threadParams } = deleteThreadQuery.build();
|
|
655
|
-
await this.executeQuery({ sql: threadSql, params: threadParams });
|
|
656
|
-
const messagesTableName = this.getTableName(storage.TABLE_MESSAGES);
|
|
729
|
+
await this.operations.executeQuery({ sql: threadSql, params: threadParams });
|
|
730
|
+
const messagesTableName = this.operations.getTableName(storage.TABLE_MESSAGES);
|
|
657
731
|
const deleteMessagesQuery = createSqlBuilder().delete(messagesTableName).where("thread_id = ?", threadId);
|
|
658
732
|
const { sql: messagesSql, params: messagesParams } = deleteMessagesQuery.build();
|
|
659
|
-
await this.executeQuery({ sql: messagesSql, params: messagesParams });
|
|
660
|
-
} catch (error) {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
733
|
+
await this.operations.executeQuery({ sql: messagesSql, params: messagesParams });
|
|
734
|
+
} catch (error$1) {
|
|
735
|
+
throw new error.MastraError(
|
|
736
|
+
{
|
|
737
|
+
id: "CLOUDFLARE_D1_STORAGE_DELETE_THREAD_ERROR",
|
|
738
|
+
domain: error.ErrorDomain.STORAGE,
|
|
739
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
740
|
+
text: `Failed to delete thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
741
|
+
details: { threadId }
|
|
742
|
+
},
|
|
743
|
+
error$1
|
|
744
|
+
);
|
|
665
745
|
}
|
|
666
746
|
}
|
|
667
747
|
async saveMessages(args) {
|
|
@@ -669,11 +749,21 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
669
749
|
if (messages.length === 0) return [];
|
|
670
750
|
try {
|
|
671
751
|
const now = /* @__PURE__ */ new Date();
|
|
752
|
+
const threadId = messages[0]?.threadId;
|
|
672
753
|
for (const [i, message] of messages.entries()) {
|
|
673
754
|
if (!message.id) throw new Error(`Message at index ${i} missing id`);
|
|
674
|
-
if (!message.threadId)
|
|
675
|
-
|
|
676
|
-
|
|
755
|
+
if (!message.threadId) {
|
|
756
|
+
throw new Error(`Message at index ${i} missing threadId`);
|
|
757
|
+
}
|
|
758
|
+
if (!message.content) {
|
|
759
|
+
throw new Error(`Message at index ${i} missing content`);
|
|
760
|
+
}
|
|
761
|
+
if (!message.role) {
|
|
762
|
+
throw new Error(`Message at index ${i} missing role`);
|
|
763
|
+
}
|
|
764
|
+
if (!message.resourceId) {
|
|
765
|
+
throw new Error(`Message at index ${i} missing resourceId`);
|
|
766
|
+
}
|
|
677
767
|
const thread = await this.getThreadById({ threadId: message.threadId });
|
|
678
768
|
if (!thread) {
|
|
679
769
|
throw new Error(`Thread ${message.threadId} not found`);
|
|
@@ -687,80 +777,119 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
687
777
|
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
688
778
|
createdAt: createdAt.toISOString(),
|
|
689
779
|
role: message.role,
|
|
690
|
-
type: message.type || "v2"
|
|
780
|
+
type: message.type || "v2",
|
|
781
|
+
resourceId: message.resourceId
|
|
691
782
|
};
|
|
692
783
|
});
|
|
693
|
-
await
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
784
|
+
await Promise.all([
|
|
785
|
+
this.operations.batchUpsert({
|
|
786
|
+
tableName: storage.TABLE_MESSAGES,
|
|
787
|
+
records: messagesToInsert
|
|
788
|
+
}),
|
|
789
|
+
// Update thread's updatedAt timestamp
|
|
790
|
+
this.operations.executeQuery({
|
|
791
|
+
sql: `UPDATE ${this.operations.getTableName(storage.TABLE_THREADS)} SET updatedAt = ? WHERE id = ?`,
|
|
792
|
+
params: [now.toISOString(), threadId]
|
|
793
|
+
})
|
|
794
|
+
]);
|
|
697
795
|
this.logger.debug(`Saved ${messages.length} messages`);
|
|
698
796
|
const list = new agent.MessageList().add(messages, "memory");
|
|
699
797
|
if (format === `v2`) return list.get.all.v2();
|
|
700
798
|
return list.get.all.v1();
|
|
701
|
-
} catch (error) {
|
|
702
|
-
|
|
703
|
-
|
|
799
|
+
} catch (error$1) {
|
|
800
|
+
throw new error.MastraError(
|
|
801
|
+
{
|
|
802
|
+
id: "CLOUDFLARE_D1_STORAGE_SAVE_MESSAGES_ERROR",
|
|
803
|
+
domain: error.ErrorDomain.STORAGE,
|
|
804
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
805
|
+
text: `Failed to save messages: ${error$1 instanceof Error ? error$1.message : String(error$1)}`
|
|
806
|
+
},
|
|
807
|
+
error$1
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
async _getIncludedMessages(threadId, selectBy) {
|
|
812
|
+
const include = selectBy?.include;
|
|
813
|
+
if (!include) return null;
|
|
814
|
+
const unionQueries = [];
|
|
815
|
+
const params = [];
|
|
816
|
+
let paramIdx = 1;
|
|
817
|
+
for (const inc of include) {
|
|
818
|
+
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
819
|
+
const searchId = inc.threadId || threadId;
|
|
820
|
+
unionQueries.push(`
|
|
821
|
+
SELECT * FROM (
|
|
822
|
+
WITH ordered_messages AS (
|
|
823
|
+
SELECT
|
|
824
|
+
*,
|
|
825
|
+
ROW_NUMBER() OVER (ORDER BY createdAt ASC) AS row_num
|
|
826
|
+
FROM ${this.operations.getTableName(storage.TABLE_MESSAGES)}
|
|
827
|
+
WHERE thread_id = ?
|
|
828
|
+
)
|
|
829
|
+
SELECT
|
|
830
|
+
m.id,
|
|
831
|
+
m.content,
|
|
832
|
+
m.role,
|
|
833
|
+
m.type,
|
|
834
|
+
m.createdAt,
|
|
835
|
+
m.thread_id AS threadId,
|
|
836
|
+
m.resourceId
|
|
837
|
+
FROM ordered_messages m
|
|
838
|
+
WHERE m.id = ?
|
|
839
|
+
OR EXISTS (
|
|
840
|
+
SELECT 1 FROM ordered_messages target
|
|
841
|
+
WHERE target.id = ?
|
|
842
|
+
AND (
|
|
843
|
+
(m.row_num <= target.row_num + ? AND m.row_num > target.row_num)
|
|
844
|
+
OR
|
|
845
|
+
(m.row_num >= target.row_num - ? AND m.row_num < target.row_num)
|
|
846
|
+
)
|
|
847
|
+
)
|
|
848
|
+
) AS query_${paramIdx}
|
|
849
|
+
`);
|
|
850
|
+
params.push(searchId, id, id, withNextMessages, withPreviousMessages);
|
|
851
|
+
paramIdx++;
|
|
852
|
+
}
|
|
853
|
+
const finalQuery = unionQueries.join(" UNION ALL ") + " ORDER BY createdAt ASC";
|
|
854
|
+
const messages = await this.operations.executeQuery({ sql: finalQuery, params });
|
|
855
|
+
if (!Array.isArray(messages)) {
|
|
856
|
+
return [];
|
|
704
857
|
}
|
|
858
|
+
const processedMessages = messages.map((message) => {
|
|
859
|
+
const processedMsg = {};
|
|
860
|
+
for (const [key, value] of Object.entries(message)) {
|
|
861
|
+
if (key === `type` && value === `v2`) continue;
|
|
862
|
+
processedMsg[key] = deserializeValue(value);
|
|
863
|
+
}
|
|
864
|
+
return processedMsg;
|
|
865
|
+
});
|
|
866
|
+
return processedMessages;
|
|
705
867
|
}
|
|
706
868
|
async getMessages({
|
|
707
869
|
threadId,
|
|
708
870
|
selectBy,
|
|
709
871
|
format
|
|
710
872
|
}) {
|
|
711
|
-
const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
|
|
712
|
-
const limit =
|
|
873
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_MESSAGES);
|
|
874
|
+
const limit = storage.resolveMessageLimit({
|
|
875
|
+
last: selectBy?.last,
|
|
876
|
+
defaultLimit: 40
|
|
877
|
+
});
|
|
713
878
|
const include = selectBy?.include || [];
|
|
714
879
|
const messages = [];
|
|
715
880
|
try {
|
|
716
881
|
if (include.length) {
|
|
717
|
-
const
|
|
718
|
-
const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
|
|
719
|
-
const includeIds = include.map((i) => i.id);
|
|
720
|
-
const sql2 = `
|
|
721
|
-
WITH ordered_messages AS (
|
|
722
|
-
SELECT
|
|
723
|
-
*,
|
|
724
|
-
ROW_NUMBER() OVER (ORDER BY createdAt DESC) AS row_num
|
|
725
|
-
FROM ${fullTableName}
|
|
726
|
-
WHERE thread_id = ?
|
|
727
|
-
)
|
|
728
|
-
SELECT
|
|
729
|
-
m.id,
|
|
730
|
-
m.content,
|
|
731
|
-
m.role,
|
|
732
|
-
m.type,
|
|
733
|
-
m.createdAt,
|
|
734
|
-
m.thread_id AS threadId
|
|
735
|
-
FROM ordered_messages m
|
|
736
|
-
WHERE m.id IN (${includeIds.map(() => "?").join(",")})
|
|
737
|
-
OR EXISTS (
|
|
738
|
-
SELECT 1 FROM ordered_messages target
|
|
739
|
-
WHERE target.id IN (${includeIds.map(() => "?").join(",")})
|
|
740
|
-
AND (
|
|
741
|
-
(m.row_num <= target.row_num + ? AND m.row_num > target.row_num)
|
|
742
|
-
OR
|
|
743
|
-
(m.row_num >= target.row_num - ? AND m.row_num < target.row_num)
|
|
744
|
-
)
|
|
745
|
-
)
|
|
746
|
-
ORDER BY m.createdAt DESC
|
|
747
|
-
`;
|
|
748
|
-
const params2 = [
|
|
749
|
-
threadId,
|
|
750
|
-
...includeIds,
|
|
751
|
-
// for m.id IN (...)
|
|
752
|
-
...includeIds,
|
|
753
|
-
// for target.id IN (...)
|
|
754
|
-
prevMax,
|
|
755
|
-
nextMax
|
|
756
|
-
];
|
|
757
|
-
const includeResult = await this.executeQuery({ sql: sql2, params: params2 });
|
|
882
|
+
const includeResult = await this._getIncludedMessages(threadId, selectBy);
|
|
758
883
|
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
759
884
|
}
|
|
760
885
|
const excludeIds = messages.map((m) => m.id);
|
|
761
|
-
|
|
886
|
+
const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
|
|
887
|
+
if (excludeIds.length > 0) {
|
|
888
|
+
query.andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds);
|
|
889
|
+
}
|
|
890
|
+
query.orderBy("createdAt", "DESC").limit(limit);
|
|
762
891
|
const { sql, params } = query.build();
|
|
763
|
-
const result = await this.executeQuery({ sql, params });
|
|
892
|
+
const result = await this.operations.executeQuery({ sql, params });
|
|
764
893
|
if (Array.isArray(result)) messages.push(...result);
|
|
765
894
|
messages.sort((a, b) => {
|
|
766
895
|
const aRecord = a;
|
|
@@ -773,7 +902,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
773
902
|
const processedMsg = {};
|
|
774
903
|
for (const [key, value] of Object.entries(message)) {
|
|
775
904
|
if (key === `type` && value === `v2`) continue;
|
|
776
|
-
processedMsg[key] =
|
|
905
|
+
processedMsg[key] = deserializeValue(value);
|
|
777
906
|
}
|
|
778
907
|
return processedMsg;
|
|
779
908
|
});
|
|
@@ -781,22 +910,973 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
781
910
|
const list = new agent.MessageList().add(processedMessages, "memory");
|
|
782
911
|
if (format === `v2`) return list.get.all.v2();
|
|
783
912
|
return list.get.all.v1();
|
|
784
|
-
} catch (error) {
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
913
|
+
} catch (error$1) {
|
|
914
|
+
const mastraError = new error.MastraError(
|
|
915
|
+
{
|
|
916
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_MESSAGES_ERROR",
|
|
917
|
+
domain: error.ErrorDomain.STORAGE,
|
|
918
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
919
|
+
text: `Failed to retrieve messages for thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
920
|
+
details: { threadId }
|
|
921
|
+
},
|
|
922
|
+
error$1
|
|
923
|
+
);
|
|
924
|
+
this.logger?.error(mastraError.toString());
|
|
925
|
+
this.logger?.trackException(mastraError);
|
|
926
|
+
throw mastraError;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
async getMessagesPaginated({
|
|
930
|
+
threadId,
|
|
931
|
+
selectBy,
|
|
932
|
+
format
|
|
933
|
+
}) {
|
|
934
|
+
const { dateRange, page = 0, perPage: perPageInput } = selectBy?.pagination || {};
|
|
935
|
+
const { start: fromDate, end: toDate } = dateRange || {};
|
|
936
|
+
const perPage = perPageInput !== void 0 ? perPageInput : storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
937
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_MESSAGES);
|
|
938
|
+
const messages = [];
|
|
939
|
+
try {
|
|
940
|
+
if (selectBy?.include?.length) {
|
|
941
|
+
const includeResult = await this._getIncludedMessages(threadId, selectBy);
|
|
942
|
+
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
943
|
+
}
|
|
944
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("thread_id = ?", threadId);
|
|
945
|
+
if (fromDate) {
|
|
946
|
+
countQuery.andWhere("createdAt >= ?", storage.serializeDate(fromDate));
|
|
947
|
+
}
|
|
948
|
+
if (toDate) {
|
|
949
|
+
countQuery.andWhere("createdAt <= ?", storage.serializeDate(toDate));
|
|
950
|
+
}
|
|
951
|
+
const countResult = await this.operations.executeQuery(countQuery.build());
|
|
952
|
+
const total = Number(countResult[0]?.count ?? 0);
|
|
953
|
+
if (total === 0 && messages.length === 0) {
|
|
954
|
+
return {
|
|
955
|
+
messages: [],
|
|
956
|
+
total: 0,
|
|
957
|
+
page,
|
|
958
|
+
perPage,
|
|
959
|
+
hasMore: false
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
const excludeIds = messages.map((m) => m.id);
|
|
963
|
+
const excludeCondition = excludeIds.length > 0 ? `AND id NOT IN (${excludeIds.map(() => "?").join(",")})` : "";
|
|
964
|
+
let query;
|
|
965
|
+
let queryParams = [threadId];
|
|
966
|
+
if (fromDate) {
|
|
967
|
+
queryParams.push(storage.serializeDate(fromDate));
|
|
968
|
+
}
|
|
969
|
+
if (toDate) {
|
|
970
|
+
queryParams.push(storage.serializeDate(toDate));
|
|
971
|
+
}
|
|
972
|
+
if (excludeIds.length > 0) {
|
|
973
|
+
queryParams.push(...excludeIds);
|
|
974
|
+
}
|
|
975
|
+
if (selectBy?.last && selectBy.last > 0) {
|
|
976
|
+
query = `
|
|
977
|
+
SELECT id, content, role, type, createdAt, thread_id AS threadId, resourceId
|
|
978
|
+
FROM ${fullTableName}
|
|
979
|
+
WHERE thread_id = ?
|
|
980
|
+
${fromDate ? "AND createdAt >= ?" : ""}
|
|
981
|
+
${toDate ? "AND createdAt <= ?" : ""}
|
|
982
|
+
${excludeCondition}
|
|
983
|
+
ORDER BY createdAt DESC
|
|
984
|
+
LIMIT ?
|
|
985
|
+
`;
|
|
986
|
+
queryParams.push(selectBy.last);
|
|
987
|
+
} else {
|
|
988
|
+
query = `
|
|
989
|
+
SELECT id, content, role, type, createdAt, thread_id AS threadId, resourceId
|
|
990
|
+
FROM ${fullTableName}
|
|
991
|
+
WHERE thread_id = ?
|
|
992
|
+
${fromDate ? "AND createdAt >= ?" : ""}
|
|
993
|
+
${toDate ? "AND createdAt <= ?" : ""}
|
|
994
|
+
${excludeCondition}
|
|
995
|
+
ORDER BY createdAt DESC
|
|
996
|
+
LIMIT ? OFFSET ?
|
|
997
|
+
`;
|
|
998
|
+
queryParams.push(perPage, page * perPage);
|
|
999
|
+
}
|
|
1000
|
+
const results = await this.operations.executeQuery({ sql: query, params: queryParams });
|
|
1001
|
+
const processedMessages = results.map((message) => {
|
|
1002
|
+
const processedMsg = {};
|
|
1003
|
+
for (const [key, value] of Object.entries(message)) {
|
|
1004
|
+
if (key === `type` && value === `v2`) continue;
|
|
1005
|
+
processedMsg[key] = deserializeValue(value);
|
|
1006
|
+
}
|
|
1007
|
+
return processedMsg;
|
|
1008
|
+
});
|
|
1009
|
+
if (selectBy?.last) {
|
|
1010
|
+
processedMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
1011
|
+
}
|
|
1012
|
+
const list = new agent.MessageList().add(processedMessages, "memory");
|
|
1013
|
+
messages.push(...format === `v2` ? list.get.all.v2() : list.get.all.v1());
|
|
1014
|
+
return {
|
|
1015
|
+
messages,
|
|
1016
|
+
total,
|
|
1017
|
+
page,
|
|
1018
|
+
perPage,
|
|
1019
|
+
hasMore: selectBy?.last ? false : page * perPage + messages.length < total
|
|
1020
|
+
};
|
|
1021
|
+
} catch (error$1) {
|
|
1022
|
+
const mastraError = new error.MastraError(
|
|
1023
|
+
{
|
|
1024
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_MESSAGES_PAGINATED_ERROR",
|
|
1025
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1026
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1027
|
+
text: `Failed to retrieve messages for thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1028
|
+
details: { threadId }
|
|
1029
|
+
},
|
|
1030
|
+
error$1
|
|
1031
|
+
);
|
|
1032
|
+
this.logger?.error(mastraError.toString());
|
|
1033
|
+
this.logger?.trackException(mastraError);
|
|
1034
|
+
return {
|
|
1035
|
+
messages: [],
|
|
1036
|
+
total: 0,
|
|
1037
|
+
page,
|
|
1038
|
+
perPage,
|
|
1039
|
+
hasMore: false
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
async updateMessages(args) {
|
|
1044
|
+
const { messages } = args;
|
|
1045
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
1046
|
+
if (!messages.length) {
|
|
1047
|
+
return [];
|
|
1048
|
+
}
|
|
1049
|
+
const messageIds = messages.map((m) => m.id);
|
|
1050
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_MESSAGES);
|
|
1051
|
+
const threadsTableName = this.operations.getTableName(storage.TABLE_THREADS);
|
|
1052
|
+
try {
|
|
1053
|
+
const placeholders = messageIds.map(() => "?").join(",");
|
|
1054
|
+
const selectQuery = `SELECT id, content, role, type, createdAt, thread_id AS threadId, resourceId FROM ${fullTableName} WHERE id IN (${placeholders})`;
|
|
1055
|
+
const existingMessages = await this.operations.executeQuery({ sql: selectQuery, params: messageIds });
|
|
1056
|
+
if (existingMessages.length === 0) {
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
const parsedExistingMessages = existingMessages.map((msg) => {
|
|
1060
|
+
if (typeof msg.content === "string") {
|
|
1061
|
+
try {
|
|
1062
|
+
msg.content = JSON.parse(msg.content);
|
|
1063
|
+
} catch {
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return msg;
|
|
1067
|
+
});
|
|
1068
|
+
const threadIdsToUpdate = /* @__PURE__ */ new Set();
|
|
1069
|
+
const updateQueries = [];
|
|
1070
|
+
for (const existingMessage of parsedExistingMessages) {
|
|
1071
|
+
const updatePayload = messages.find((m) => m.id === existingMessage.id);
|
|
1072
|
+
if (!updatePayload) continue;
|
|
1073
|
+
const { id, ...fieldsToUpdate } = updatePayload;
|
|
1074
|
+
if (Object.keys(fieldsToUpdate).length === 0) continue;
|
|
1075
|
+
threadIdsToUpdate.add(existingMessage.threadId);
|
|
1076
|
+
if ("threadId" in updatePayload && updatePayload.threadId && updatePayload.threadId !== existingMessage.threadId) {
|
|
1077
|
+
threadIdsToUpdate.add(updatePayload.threadId);
|
|
1078
|
+
}
|
|
1079
|
+
const setClauses = [];
|
|
1080
|
+
const values = [];
|
|
1081
|
+
const updatableFields = { ...fieldsToUpdate };
|
|
1082
|
+
if (updatableFields.content) {
|
|
1083
|
+
const existingContent = existingMessage.content || {};
|
|
1084
|
+
const newContent = {
|
|
1085
|
+
...existingContent,
|
|
1086
|
+
...updatableFields.content,
|
|
1087
|
+
// Deep merge metadata if it exists on both
|
|
1088
|
+
...existingContent?.metadata && updatableFields.content.metadata ? {
|
|
1089
|
+
metadata: {
|
|
1090
|
+
...existingContent.metadata,
|
|
1091
|
+
...updatableFields.content.metadata
|
|
1092
|
+
}
|
|
1093
|
+
} : {}
|
|
1094
|
+
};
|
|
1095
|
+
setClauses.push(`content = ?`);
|
|
1096
|
+
values.push(JSON.stringify(newContent));
|
|
1097
|
+
delete updatableFields.content;
|
|
1098
|
+
}
|
|
1099
|
+
for (const key in updatableFields) {
|
|
1100
|
+
if (Object.prototype.hasOwnProperty.call(updatableFields, key)) {
|
|
1101
|
+
const dbColumn = key === "threadId" ? "thread_id" : key;
|
|
1102
|
+
setClauses.push(`${dbColumn} = ?`);
|
|
1103
|
+
values.push(updatableFields[key]);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
if (setClauses.length > 0) {
|
|
1107
|
+
values.push(id);
|
|
1108
|
+
const updateQuery = `UPDATE ${fullTableName} SET ${setClauses.join(", ")} WHERE id = ?`;
|
|
1109
|
+
updateQueries.push({ sql: updateQuery, params: values });
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
for (const query of updateQueries) {
|
|
1113
|
+
await this.operations.executeQuery(query);
|
|
1114
|
+
}
|
|
1115
|
+
if (threadIdsToUpdate.size > 0) {
|
|
1116
|
+
const threadPlaceholders = Array.from(threadIdsToUpdate).map(() => "?").join(",");
|
|
1117
|
+
const threadUpdateQuery = `UPDATE ${threadsTableName} SET updatedAt = ? WHERE id IN (${threadPlaceholders})`;
|
|
1118
|
+
const threadUpdateParams = [(/* @__PURE__ */ new Date()).toISOString(), ...Array.from(threadIdsToUpdate)];
|
|
1119
|
+
await this.operations.executeQuery({ sql: threadUpdateQuery, params: threadUpdateParams });
|
|
1120
|
+
}
|
|
1121
|
+
const updatedMessages = await this.operations.executeQuery({ sql: selectQuery, params: messageIds });
|
|
1122
|
+
return updatedMessages.map((message) => {
|
|
1123
|
+
if (typeof message.content === "string") {
|
|
1124
|
+
try {
|
|
1125
|
+
message.content = JSON.parse(message.content);
|
|
1126
|
+
} catch {
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return message;
|
|
1130
|
+
});
|
|
1131
|
+
} catch (error$1) {
|
|
1132
|
+
throw new error.MastraError(
|
|
1133
|
+
{
|
|
1134
|
+
id: "CLOUDFLARE_D1_STORAGE_UPDATE_MESSAGES_FAILED",
|
|
1135
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1136
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1137
|
+
details: { count: messages.length }
|
|
1138
|
+
},
|
|
1139
|
+
error$1
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
var StoreOperationsD1 = class extends storage.StoreOperations {
|
|
1145
|
+
client;
|
|
1146
|
+
binding;
|
|
1147
|
+
tablePrefix;
|
|
1148
|
+
constructor(config) {
|
|
1149
|
+
super();
|
|
1150
|
+
this.client = config.client;
|
|
1151
|
+
this.binding = config.binding;
|
|
1152
|
+
this.tablePrefix = config.tablePrefix || "";
|
|
1153
|
+
}
|
|
1154
|
+
async hasColumn(table, column) {
|
|
1155
|
+
const fullTableName = table.startsWith(this.tablePrefix) ? table : `${this.tablePrefix}${table}`;
|
|
1156
|
+
const sql = `PRAGMA table_info(${fullTableName});`;
|
|
1157
|
+
const result = await this.executeQuery({ sql, params: [] });
|
|
1158
|
+
if (!result || !Array.isArray(result)) return false;
|
|
1159
|
+
return result.some((col) => col.name === column || col.name === column.toLowerCase());
|
|
1160
|
+
}
|
|
1161
|
+
getTableName(tableName) {
|
|
1162
|
+
return `${this.tablePrefix}${tableName}`;
|
|
1163
|
+
}
|
|
1164
|
+
formatSqlParams(params) {
|
|
1165
|
+
return params.map((p) => p === void 0 || p === null ? null : p);
|
|
1166
|
+
}
|
|
1167
|
+
async executeWorkersBindingQuery({
|
|
1168
|
+
sql,
|
|
1169
|
+
params = [],
|
|
1170
|
+
first = false
|
|
1171
|
+
}) {
|
|
1172
|
+
if (!this.binding) {
|
|
1173
|
+
throw new Error("Workers binding is not configured");
|
|
1174
|
+
}
|
|
1175
|
+
try {
|
|
1176
|
+
const statement = this.binding.prepare(sql);
|
|
1177
|
+
const formattedParams = this.formatSqlParams(params);
|
|
1178
|
+
let result;
|
|
1179
|
+
if (formattedParams.length > 0) {
|
|
1180
|
+
if (first) {
|
|
1181
|
+
result = await statement.bind(...formattedParams).first();
|
|
1182
|
+
if (!result) return null;
|
|
1183
|
+
return result;
|
|
1184
|
+
} else {
|
|
1185
|
+
result = await statement.bind(...formattedParams).all();
|
|
1186
|
+
const results = result.results || [];
|
|
1187
|
+
return results;
|
|
1188
|
+
}
|
|
1189
|
+
} else {
|
|
1190
|
+
if (first) {
|
|
1191
|
+
result = await statement.first();
|
|
1192
|
+
if (!result) return null;
|
|
1193
|
+
return result;
|
|
1194
|
+
} else {
|
|
1195
|
+
result = await statement.all();
|
|
1196
|
+
const results = result.results || [];
|
|
1197
|
+
return results;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
} catch (error$1) {
|
|
1201
|
+
throw new error.MastraError(
|
|
1202
|
+
{
|
|
1203
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_WORKERS_BINDING_QUERY_FAILED",
|
|
1204
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1205
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1206
|
+
details: { sql }
|
|
1207
|
+
},
|
|
1208
|
+
error$1
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
async executeRestQuery({
|
|
1213
|
+
sql,
|
|
1214
|
+
params = [],
|
|
1215
|
+
first = false
|
|
1216
|
+
}) {
|
|
1217
|
+
if (!this.client) {
|
|
1218
|
+
throw new Error("D1 client is not configured");
|
|
1219
|
+
}
|
|
1220
|
+
try {
|
|
1221
|
+
const formattedParams = this.formatSqlParams(params);
|
|
1222
|
+
const response = await this.client.query({
|
|
1223
|
+
sql,
|
|
1224
|
+
params: formattedParams
|
|
1225
|
+
});
|
|
1226
|
+
if (!response.result) {
|
|
1227
|
+
return first ? null : [];
|
|
1228
|
+
}
|
|
1229
|
+
if (first) {
|
|
1230
|
+
return response.result[0] || null;
|
|
1231
|
+
}
|
|
1232
|
+
return response.result;
|
|
1233
|
+
} catch (error$1) {
|
|
1234
|
+
throw new error.MastraError(
|
|
1235
|
+
{
|
|
1236
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_REST_QUERY_FAILED",
|
|
1237
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1238
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1239
|
+
details: { sql }
|
|
1240
|
+
},
|
|
1241
|
+
error$1
|
|
1242
|
+
);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
async executeQuery(options) {
|
|
1246
|
+
if (this.binding) {
|
|
1247
|
+
return this.executeWorkersBindingQuery(options);
|
|
1248
|
+
} else if (this.client) {
|
|
1249
|
+
return this.executeRestQuery(options);
|
|
1250
|
+
} else {
|
|
1251
|
+
throw new Error("Neither binding nor client is configured");
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
async getTableColumns(tableName) {
|
|
1255
|
+
try {
|
|
1256
|
+
const sql = `PRAGMA table_info(${tableName})`;
|
|
1257
|
+
const result = await this.executeQuery({ sql });
|
|
1258
|
+
if (!result || !Array.isArray(result)) {
|
|
1259
|
+
return [];
|
|
1260
|
+
}
|
|
1261
|
+
return result.map((row) => ({
|
|
1262
|
+
name: row.name,
|
|
1263
|
+
type: row.type
|
|
1264
|
+
}));
|
|
1265
|
+
} catch (error) {
|
|
1266
|
+
this.logger.warn(`Failed to get table columns for ${tableName}:`, error);
|
|
1267
|
+
return [];
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
serializeValue(value) {
|
|
1271
|
+
if (value === null || value === void 0) {
|
|
1272
|
+
return null;
|
|
1273
|
+
}
|
|
1274
|
+
if (value instanceof Date) {
|
|
1275
|
+
return value.toISOString();
|
|
1276
|
+
}
|
|
1277
|
+
if (typeof value === "object") {
|
|
1278
|
+
return JSON.stringify(value);
|
|
1279
|
+
}
|
|
1280
|
+
return value;
|
|
1281
|
+
}
|
|
1282
|
+
getSqlType(type) {
|
|
1283
|
+
switch (type) {
|
|
1284
|
+
case "bigint":
|
|
1285
|
+
return "INTEGER";
|
|
1286
|
+
// SQLite uses INTEGER for all integer sizes
|
|
1287
|
+
case "jsonb":
|
|
1288
|
+
return "TEXT";
|
|
1289
|
+
// Store JSON as TEXT in SQLite
|
|
1290
|
+
default:
|
|
1291
|
+
return super.getSqlType(type);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
async createTable({
|
|
1295
|
+
tableName,
|
|
1296
|
+
schema
|
|
1297
|
+
}) {
|
|
1298
|
+
try {
|
|
1299
|
+
const fullTableName = this.getTableName(tableName);
|
|
1300
|
+
const columnDefinitions = Object.entries(schema).map(([colName, colDef]) => {
|
|
1301
|
+
const type = this.getSqlType(colDef.type);
|
|
1302
|
+
const nullable = colDef.nullable === false ? "NOT NULL" : "";
|
|
1303
|
+
const primaryKey = colDef.primaryKey ? "PRIMARY KEY" : "";
|
|
1304
|
+
return `${colName} ${type} ${nullable} ${primaryKey}`.trim();
|
|
1305
|
+
});
|
|
1306
|
+
const tableConstraints = [];
|
|
1307
|
+
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
1308
|
+
tableConstraints.push("UNIQUE (workflow_name, run_id)");
|
|
1309
|
+
}
|
|
1310
|
+
const query = createSqlBuilder().createTable(fullTableName, columnDefinitions, tableConstraints);
|
|
1311
|
+
const { sql, params } = query.build();
|
|
1312
|
+
await this.executeQuery({ sql, params });
|
|
1313
|
+
this.logger.debug(`Created table ${fullTableName}`);
|
|
1314
|
+
} catch (error$1) {
|
|
1315
|
+
throw new error.MastraError(
|
|
1316
|
+
{
|
|
1317
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_CREATE_TABLE_FAILED",
|
|
1318
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1319
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1320
|
+
details: { tableName }
|
|
1321
|
+
},
|
|
1322
|
+
error$1
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
async clearTable({ tableName }) {
|
|
1327
|
+
try {
|
|
1328
|
+
const fullTableName = this.getTableName(tableName);
|
|
1329
|
+
const query = createSqlBuilder().delete(fullTableName);
|
|
1330
|
+
const { sql, params } = query.build();
|
|
1331
|
+
await this.executeQuery({ sql, params });
|
|
1332
|
+
this.logger.debug(`Cleared table ${fullTableName}`);
|
|
1333
|
+
} catch (error$1) {
|
|
1334
|
+
throw new error.MastraError(
|
|
1335
|
+
{
|
|
1336
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_CLEAR_TABLE_FAILED",
|
|
1337
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1338
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1339
|
+
details: { tableName }
|
|
1340
|
+
},
|
|
1341
|
+
error$1
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
async dropTable({ tableName }) {
|
|
1346
|
+
try {
|
|
1347
|
+
const fullTableName = this.getTableName(tableName);
|
|
1348
|
+
const sql = `DROP TABLE IF EXISTS ${fullTableName}`;
|
|
1349
|
+
await this.executeQuery({ sql });
|
|
1350
|
+
this.logger.debug(`Dropped table ${fullTableName}`);
|
|
1351
|
+
} catch (error$1) {
|
|
1352
|
+
throw new error.MastraError(
|
|
1353
|
+
{
|
|
1354
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_DROP_TABLE_FAILED",
|
|
1355
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1356
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1357
|
+
details: { tableName }
|
|
1358
|
+
},
|
|
1359
|
+
error$1
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
async alterTable(args) {
|
|
1364
|
+
try {
|
|
1365
|
+
const fullTableName = this.getTableName(args.tableName);
|
|
1366
|
+
const existingColumns = await this.getTableColumns(fullTableName);
|
|
1367
|
+
const existingColumnNames = new Set(existingColumns.map((col) => col.name));
|
|
1368
|
+
for (const [columnName, column] of Object.entries(args.schema)) {
|
|
1369
|
+
if (!existingColumnNames.has(columnName) && args.ifNotExists.includes(columnName)) {
|
|
1370
|
+
const sqlType = this.getSqlType(column.type);
|
|
1371
|
+
const defaultValue = this.getDefaultValue(column.type);
|
|
1372
|
+
const sql = `ALTER TABLE ${fullTableName} ADD COLUMN ${columnName} ${sqlType} ${defaultValue}`;
|
|
1373
|
+
await this.executeQuery({ sql });
|
|
1374
|
+
this.logger.debug(`Added column ${columnName} to table ${fullTableName}`);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
} catch (error$1) {
|
|
1378
|
+
throw new error.MastraError(
|
|
1379
|
+
{
|
|
1380
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_ALTER_TABLE_FAILED",
|
|
1381
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1382
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1383
|
+
details: { tableName: args.tableName }
|
|
1384
|
+
},
|
|
1385
|
+
error$1
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
async insert({ tableName, record }) {
|
|
1390
|
+
try {
|
|
1391
|
+
const fullTableName = this.getTableName(tableName);
|
|
1392
|
+
const processedRecord = await this.processRecord(record);
|
|
1393
|
+
const columns = Object.keys(processedRecord);
|
|
1394
|
+
const values = Object.values(processedRecord);
|
|
1395
|
+
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
1396
|
+
const { sql, params } = query.build();
|
|
1397
|
+
await this.executeQuery({ sql, params });
|
|
1398
|
+
} catch (error$1) {
|
|
1399
|
+
throw new error.MastraError(
|
|
1400
|
+
{
|
|
1401
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_INSERT_FAILED",
|
|
1402
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1403
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1404
|
+
details: { tableName }
|
|
1405
|
+
},
|
|
1406
|
+
error$1
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
async batchInsert({ tableName, records }) {
|
|
1411
|
+
try {
|
|
1412
|
+
if (records.length === 0) return;
|
|
1413
|
+
const fullTableName = this.getTableName(tableName);
|
|
1414
|
+
const processedRecords = await Promise.all(records.map((record) => this.processRecord(record)));
|
|
1415
|
+
const columns = Object.keys(processedRecords[0] || {});
|
|
1416
|
+
for (const record of processedRecords) {
|
|
1417
|
+
const values = Object.values(record);
|
|
1418
|
+
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
1419
|
+
const { sql, params } = query.build();
|
|
1420
|
+
await this.executeQuery({ sql, params });
|
|
1421
|
+
}
|
|
1422
|
+
} catch (error$1) {
|
|
1423
|
+
throw new error.MastraError(
|
|
1424
|
+
{
|
|
1425
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_BATCH_INSERT_FAILED",
|
|
1426
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1427
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1428
|
+
details: { tableName }
|
|
1429
|
+
},
|
|
1430
|
+
error$1
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
async load({ tableName, keys }) {
|
|
1435
|
+
try {
|
|
1436
|
+
const fullTableName = this.getTableName(tableName);
|
|
1437
|
+
const query = createSqlBuilder().select("*").from(fullTableName);
|
|
1438
|
+
let firstKey = true;
|
|
1439
|
+
for (const [key, value] of Object.entries(keys)) {
|
|
1440
|
+
if (firstKey) {
|
|
1441
|
+
query.where(`${key} = ?`, value);
|
|
1442
|
+
firstKey = false;
|
|
1443
|
+
} else {
|
|
1444
|
+
query.andWhere(`${key} = ?`, value);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
query.limit(1);
|
|
1448
|
+
const { sql, params } = query.build();
|
|
1449
|
+
const result = await this.executeQuery({ sql, params, first: true });
|
|
1450
|
+
if (!result) {
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1453
|
+
const deserializedResult = {};
|
|
1454
|
+
for (const [key, value] of Object.entries(result)) {
|
|
1455
|
+
deserializedResult[key] = deserializeValue(value);
|
|
1456
|
+
}
|
|
1457
|
+
return deserializedResult;
|
|
1458
|
+
} catch (error$1) {
|
|
1459
|
+
throw new error.MastraError(
|
|
1460
|
+
{
|
|
1461
|
+
id: "CLOUDFLARE_D1_STORE_OPERATIONS_LOAD_FAILED",
|
|
1462
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1463
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1464
|
+
details: { tableName }
|
|
1465
|
+
},
|
|
1466
|
+
error$1
|
|
1467
|
+
);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
async processRecord(record) {
|
|
1471
|
+
const processed = {};
|
|
1472
|
+
for (const [key, value] of Object.entries(record)) {
|
|
1473
|
+
processed[key] = this.serializeValue(value);
|
|
1474
|
+
}
|
|
1475
|
+
return processed;
|
|
1476
|
+
}
|
|
1477
|
+
/**
|
|
1478
|
+
* Upsert multiple records in a batch operation
|
|
1479
|
+
* @param tableName The table to insert into
|
|
1480
|
+
* @param records The records to insert
|
|
1481
|
+
*/
|
|
1482
|
+
async batchUpsert({ tableName, records }) {
|
|
1483
|
+
if (records.length === 0) return;
|
|
1484
|
+
const fullTableName = this.getTableName(tableName);
|
|
1485
|
+
try {
|
|
1486
|
+
const batchSize = 50;
|
|
1487
|
+
for (let i = 0; i < records.length; i += batchSize) {
|
|
1488
|
+
const batch = records.slice(i, i + batchSize);
|
|
1489
|
+
const recordsToInsert = batch;
|
|
1490
|
+
if (recordsToInsert.length > 0) {
|
|
1491
|
+
const firstRecord = recordsToInsert[0];
|
|
1492
|
+
const columns = Object.keys(firstRecord || {});
|
|
1493
|
+
for (const record of recordsToInsert) {
|
|
1494
|
+
const values = columns.map((col) => {
|
|
1495
|
+
if (!record) return null;
|
|
1496
|
+
const value = typeof col === "string" ? record[col] : null;
|
|
1497
|
+
return this.serializeValue(value);
|
|
1498
|
+
});
|
|
1499
|
+
const recordToUpsert = columns.reduce(
|
|
1500
|
+
(acc, col) => {
|
|
1501
|
+
if (col !== "createdAt") acc[col] = `excluded.${col}`;
|
|
1502
|
+
return acc;
|
|
1503
|
+
},
|
|
1504
|
+
{}
|
|
1505
|
+
);
|
|
1506
|
+
const query = createSqlBuilder().insert(fullTableName, columns, values, ["id"], recordToUpsert);
|
|
1507
|
+
const { sql, params } = query.build();
|
|
1508
|
+
await this.executeQuery({ sql, params });
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
this.logger.debug(
|
|
1512
|
+
`Processed batch ${Math.floor(i / batchSize) + 1} of ${Math.ceil(records.length / batchSize)}`
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
this.logger.debug(`Successfully batch upserted ${records.length} records into ${tableName}`);
|
|
1516
|
+
} catch (error$1) {
|
|
1517
|
+
throw new error.MastraError(
|
|
1518
|
+
{
|
|
1519
|
+
id: "CLOUDFLARE_D1_STORAGE_BATCH_UPSERT_ERROR",
|
|
1520
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1521
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1522
|
+
text: `Failed to batch upsert into ${tableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1523
|
+
details: { tableName }
|
|
1524
|
+
},
|
|
1525
|
+
error$1
|
|
1526
|
+
);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
function transformScoreRow(row) {
|
|
1531
|
+
let input = void 0;
|
|
1532
|
+
if (row.input) {
|
|
1533
|
+
try {
|
|
1534
|
+
input = JSON.parse(row.input);
|
|
1535
|
+
} catch {
|
|
1536
|
+
input = row.input;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
return {
|
|
1540
|
+
...row,
|
|
1541
|
+
input,
|
|
1542
|
+
createdAt: row.createdAtZ || row.createdAt,
|
|
1543
|
+
updatedAt: row.updatedAtZ || row.updatedAt
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
var ScoresStorageD1 = class extends storage.ScoresStorage {
|
|
1547
|
+
operations;
|
|
1548
|
+
constructor({ operations }) {
|
|
1549
|
+
super();
|
|
1550
|
+
this.operations = operations;
|
|
1551
|
+
}
|
|
1552
|
+
async getScoreById({ id }) {
|
|
1553
|
+
try {
|
|
1554
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_SCORERS);
|
|
1555
|
+
const query = createSqlBuilder().select("*").from(fullTableName).where("id = ?", id);
|
|
1556
|
+
const { sql, params } = query.build();
|
|
1557
|
+
const result = await this.operations.executeQuery({ sql, params, first: true });
|
|
1558
|
+
if (!result) {
|
|
1559
|
+
return null;
|
|
1560
|
+
}
|
|
1561
|
+
return transformScoreRow(result);
|
|
1562
|
+
} catch (error$1) {
|
|
1563
|
+
throw new error.MastraError(
|
|
1564
|
+
{
|
|
1565
|
+
id: "CLOUDFLARE_D1_STORE_SCORES_GET_SCORE_BY_ID_FAILED",
|
|
1566
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1567
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1568
|
+
},
|
|
1569
|
+
error$1
|
|
1570
|
+
);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
async saveScore(score) {
|
|
1574
|
+
try {
|
|
1575
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_SCORERS);
|
|
1576
|
+
const { input, ...rest } = score;
|
|
1577
|
+
const serializedRecord = {};
|
|
1578
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
1579
|
+
if (value !== null && value !== void 0) {
|
|
1580
|
+
if (typeof value === "object") {
|
|
1581
|
+
serializedRecord[key] = JSON.stringify(value);
|
|
1582
|
+
} else {
|
|
1583
|
+
serializedRecord[key] = value;
|
|
1584
|
+
}
|
|
1585
|
+
} else {
|
|
1586
|
+
serializedRecord[key] = null;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
serializedRecord.input = JSON.stringify(input);
|
|
1590
|
+
serializedRecord.createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1591
|
+
serializedRecord.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1592
|
+
const columns = Object.keys(serializedRecord);
|
|
1593
|
+
const values = Object.values(serializedRecord);
|
|
1594
|
+
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
1595
|
+
const { sql, params } = query.build();
|
|
1596
|
+
await this.operations.executeQuery({ sql, params });
|
|
1597
|
+
const scoreFromDb = await this.getScoreById({ id: score.id });
|
|
1598
|
+
return { score: scoreFromDb };
|
|
1599
|
+
} catch (error$1) {
|
|
1600
|
+
throw new error.MastraError(
|
|
1601
|
+
{
|
|
1602
|
+
id: "CLOUDFLARE_D1_STORE_SCORES_SAVE_SCORE_FAILED",
|
|
1603
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1604
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1605
|
+
},
|
|
1606
|
+
error$1
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
async getScoresByScorerId({
|
|
1611
|
+
scorerId,
|
|
1612
|
+
pagination
|
|
1613
|
+
}) {
|
|
1614
|
+
try {
|
|
1615
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_SCORERS);
|
|
1616
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("scorerId = ?", scorerId);
|
|
1617
|
+
const countResult = await this.operations.executeQuery(countQuery.build());
|
|
1618
|
+
const total = Array.isArray(countResult) ? Number(countResult?.[0]?.count ?? 0) : Number(countResult?.count ?? 0);
|
|
1619
|
+
if (total === 0) {
|
|
1620
|
+
return {
|
|
1621
|
+
pagination: {
|
|
1622
|
+
total: 0,
|
|
1623
|
+
page: pagination.page,
|
|
1624
|
+
perPage: pagination.perPage,
|
|
1625
|
+
hasMore: false
|
|
1626
|
+
},
|
|
1627
|
+
scores: []
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("scorerId = ?", scorerId).limit(pagination.perPage).offset(pagination.page * pagination.perPage);
|
|
1631
|
+
const { sql, params } = selectQuery.build();
|
|
1632
|
+
const results = await this.operations.executeQuery({ sql, params });
|
|
1633
|
+
const scores = Array.isArray(results) ? results.map(transformScoreRow) : [];
|
|
1634
|
+
return {
|
|
1635
|
+
pagination: {
|
|
1636
|
+
total,
|
|
1637
|
+
page: pagination.page,
|
|
1638
|
+
perPage: pagination.perPage,
|
|
1639
|
+
hasMore: total > (pagination.page + 1) * pagination.perPage
|
|
1640
|
+
},
|
|
1641
|
+
scores
|
|
1642
|
+
};
|
|
1643
|
+
} catch (error$1) {
|
|
1644
|
+
throw new error.MastraError(
|
|
1645
|
+
{
|
|
1646
|
+
id: "CLOUDFLARE_D1_STORE_SCORES_GET_SCORES_BY_SCORER_ID_FAILED",
|
|
1647
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1648
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1649
|
+
},
|
|
1650
|
+
error$1
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
async getScoresByRunId({
|
|
1655
|
+
runId,
|
|
1656
|
+
pagination
|
|
1657
|
+
}) {
|
|
1658
|
+
try {
|
|
1659
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_SCORERS);
|
|
1660
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("runId = ?", runId);
|
|
1661
|
+
const countResult = await this.operations.executeQuery(countQuery.build());
|
|
1662
|
+
const total = Array.isArray(countResult) ? Number(countResult?.[0]?.count ?? 0) : Number(countResult?.count ?? 0);
|
|
1663
|
+
if (total === 0) {
|
|
1664
|
+
return {
|
|
1665
|
+
pagination: {
|
|
1666
|
+
total: 0,
|
|
1667
|
+
page: pagination.page,
|
|
1668
|
+
perPage: pagination.perPage,
|
|
1669
|
+
hasMore: false
|
|
1670
|
+
},
|
|
1671
|
+
scores: []
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("runId = ?", runId).limit(pagination.perPage).offset(pagination.page * pagination.perPage);
|
|
1675
|
+
const { sql, params } = selectQuery.build();
|
|
1676
|
+
const results = await this.operations.executeQuery({ sql, params });
|
|
1677
|
+
const scores = Array.isArray(results) ? results.map(transformScoreRow) : [];
|
|
1678
|
+
return {
|
|
1679
|
+
pagination: {
|
|
1680
|
+
total,
|
|
1681
|
+
page: pagination.page,
|
|
1682
|
+
perPage: pagination.perPage,
|
|
1683
|
+
hasMore: total > (pagination.page + 1) * pagination.perPage
|
|
1684
|
+
},
|
|
1685
|
+
scores
|
|
1686
|
+
};
|
|
1687
|
+
} catch (error$1) {
|
|
1688
|
+
throw new error.MastraError(
|
|
1689
|
+
{
|
|
1690
|
+
id: "CLOUDFLARE_D1_STORE_SCORES_GET_SCORES_BY_RUN_ID_FAILED",
|
|
1691
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1692
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1693
|
+
},
|
|
1694
|
+
error$1
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
async getScoresByEntityId({
|
|
1699
|
+
entityId,
|
|
1700
|
+
entityType,
|
|
1701
|
+
pagination
|
|
1702
|
+
}) {
|
|
1703
|
+
try {
|
|
1704
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_SCORERS);
|
|
1705
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("entityId = ?", entityId).andWhere("entityType = ?", entityType);
|
|
1706
|
+
const countResult = await this.operations.executeQuery(countQuery.build());
|
|
1707
|
+
const total = Array.isArray(countResult) ? Number(countResult?.[0]?.count ?? 0) : Number(countResult?.count ?? 0);
|
|
1708
|
+
if (total === 0) {
|
|
1709
|
+
return {
|
|
1710
|
+
pagination: {
|
|
1711
|
+
total: 0,
|
|
1712
|
+
page: pagination.page,
|
|
1713
|
+
perPage: pagination.perPage,
|
|
1714
|
+
hasMore: false
|
|
1715
|
+
},
|
|
1716
|
+
scores: []
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("entityId = ?", entityId).andWhere("entityType = ?", entityType).limit(pagination.perPage).offset(pagination.page * pagination.perPage);
|
|
1720
|
+
const { sql, params } = selectQuery.build();
|
|
1721
|
+
const results = await this.operations.executeQuery({ sql, params });
|
|
1722
|
+
const scores = Array.isArray(results) ? results.map(transformScoreRow) : [];
|
|
1723
|
+
return {
|
|
1724
|
+
pagination: {
|
|
1725
|
+
total,
|
|
1726
|
+
page: pagination.page,
|
|
1727
|
+
perPage: pagination.perPage,
|
|
1728
|
+
hasMore: total > (pagination.page + 1) * pagination.perPage
|
|
1729
|
+
},
|
|
1730
|
+
scores
|
|
1731
|
+
};
|
|
1732
|
+
} catch (error$1) {
|
|
1733
|
+
throw new error.MastraError(
|
|
1734
|
+
{
|
|
1735
|
+
id: "CLOUDFLARE_D1_STORE_SCORES_GET_SCORES_BY_ENTITY_ID_FAILED",
|
|
1736
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1737
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1738
|
+
},
|
|
1739
|
+
error$1
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1744
|
+
function isArrayOfRecords2(value) {
|
|
1745
|
+
return value && Array.isArray(value) && value.length > 0;
|
|
1746
|
+
}
|
|
1747
|
+
var TracesStorageD1 = class extends storage.TracesStorage {
|
|
1748
|
+
operations;
|
|
1749
|
+
constructor({ operations }) {
|
|
1750
|
+
super();
|
|
1751
|
+
this.operations = operations;
|
|
1752
|
+
}
|
|
1753
|
+
async getTraces(args) {
|
|
1754
|
+
const paginatedArgs = {
|
|
1755
|
+
name: args.name,
|
|
1756
|
+
scope: args.scope,
|
|
1757
|
+
page: args.page,
|
|
1758
|
+
perPage: args.perPage,
|
|
1759
|
+
attributes: args.attributes,
|
|
1760
|
+
filters: args.filters,
|
|
1761
|
+
dateRange: args.fromDate || args.toDate ? {
|
|
1762
|
+
start: args.fromDate,
|
|
1763
|
+
end: args.toDate
|
|
1764
|
+
} : void 0
|
|
1765
|
+
};
|
|
1766
|
+
try {
|
|
1767
|
+
const result = await this.getTracesPaginated(paginatedArgs);
|
|
1768
|
+
return result.traces;
|
|
1769
|
+
} catch (error$1) {
|
|
1770
|
+
throw new error.MastraError(
|
|
1771
|
+
{
|
|
1772
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_TRACES_ERROR",
|
|
1773
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1774
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1775
|
+
text: `Failed to retrieve traces: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1776
|
+
details: {
|
|
1777
|
+
name: args.name ?? "",
|
|
1778
|
+
scope: args.scope ?? ""
|
|
1779
|
+
}
|
|
1780
|
+
},
|
|
1781
|
+
error$1
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
async getTracesPaginated(args) {
|
|
1786
|
+
const { name, scope, page = 0, perPage = 100, attributes, dateRange } = args;
|
|
1787
|
+
const fromDate = dateRange?.start;
|
|
1788
|
+
const toDate = dateRange?.end;
|
|
1789
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_TRACES);
|
|
1790
|
+
try {
|
|
1791
|
+
const dataQuery = createSqlBuilder().select("*").from(fullTableName).where("1=1");
|
|
1792
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("1=1");
|
|
1793
|
+
if (name) {
|
|
1794
|
+
dataQuery.andWhere("name LIKE ?", `%${name}%`);
|
|
1795
|
+
countQuery.andWhere("name LIKE ?", `%${name}%`);
|
|
1796
|
+
}
|
|
1797
|
+
if (scope) {
|
|
1798
|
+
dataQuery.andWhere("scope = ?", scope);
|
|
1799
|
+
countQuery.andWhere("scope = ?", scope);
|
|
1800
|
+
}
|
|
1801
|
+
if (attributes && Object.keys(attributes).length > 0) {
|
|
1802
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1803
|
+
dataQuery.jsonLike("attributes", key, value);
|
|
1804
|
+
countQuery.jsonLike("attributes", key, value);
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
if (fromDate) {
|
|
1808
|
+
const fromDateStr = fromDate instanceof Date ? fromDate.toISOString() : fromDate;
|
|
1809
|
+
dataQuery.andWhere("createdAt >= ?", fromDateStr);
|
|
1810
|
+
countQuery.andWhere("createdAt >= ?", fromDateStr);
|
|
1811
|
+
}
|
|
1812
|
+
if (toDate) {
|
|
1813
|
+
const toDateStr = toDate instanceof Date ? toDate.toISOString() : toDate;
|
|
1814
|
+
dataQuery.andWhere("createdAt <= ?", toDateStr);
|
|
1815
|
+
countQuery.andWhere("createdAt <= ?", toDateStr);
|
|
1816
|
+
}
|
|
1817
|
+
const allDataResult = await this.operations.executeQuery(
|
|
1818
|
+
createSqlBuilder().select("*").from(fullTableName).where("1=1").build()
|
|
1819
|
+
);
|
|
1820
|
+
console.log("allDataResult", allDataResult);
|
|
1821
|
+
const countResult = await this.operations.executeQuery(countQuery.build());
|
|
1822
|
+
const total = Number(countResult?.[0]?.count ?? 0);
|
|
1823
|
+
dataQuery.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
|
|
1824
|
+
const results = await this.operations.executeQuery(dataQuery.build());
|
|
1825
|
+
const traces = isArrayOfRecords2(results) ? results.map(
|
|
1826
|
+
(trace) => ({
|
|
1827
|
+
...trace,
|
|
1828
|
+
attributes: deserializeValue(trace.attributes, "jsonb"),
|
|
1829
|
+
status: deserializeValue(trace.status, "jsonb"),
|
|
1830
|
+
events: deserializeValue(trace.events, "jsonb"),
|
|
1831
|
+
links: deserializeValue(trace.links, "jsonb"),
|
|
1832
|
+
other: deserializeValue(trace.other, "jsonb")
|
|
1833
|
+
})
|
|
1834
|
+
) : [];
|
|
1835
|
+
return {
|
|
1836
|
+
traces,
|
|
1837
|
+
total,
|
|
1838
|
+
page,
|
|
1839
|
+
perPage,
|
|
1840
|
+
hasMore: page * perPage + traces.length < total
|
|
1841
|
+
};
|
|
1842
|
+
} catch (error$1) {
|
|
1843
|
+
const mastraError = new error.MastraError(
|
|
1844
|
+
{
|
|
1845
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_TRACES_PAGINATED_ERROR",
|
|
1846
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1847
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1848
|
+
text: `Failed to retrieve traces: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1849
|
+
details: { name: name ?? "", scope: scope ?? "" }
|
|
1850
|
+
},
|
|
1851
|
+
error$1
|
|
1852
|
+
);
|
|
1853
|
+
this.logger?.error(mastraError.toString());
|
|
1854
|
+
this.logger?.trackException(mastraError);
|
|
1855
|
+
return { traces: [], total: 0, page, perPage, hasMore: false };
|
|
790
1856
|
}
|
|
791
1857
|
}
|
|
1858
|
+
async batchTraceInsert({ records }) {
|
|
1859
|
+
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1860
|
+
await this.operations.batchInsert({
|
|
1861
|
+
tableName: storage.TABLE_TRACES,
|
|
1862
|
+
records
|
|
1863
|
+
});
|
|
1864
|
+
}
|
|
1865
|
+
};
|
|
1866
|
+
var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
1867
|
+
operations;
|
|
1868
|
+
constructor({ operations }) {
|
|
1869
|
+
super();
|
|
1870
|
+
this.operations = operations;
|
|
1871
|
+
}
|
|
792
1872
|
async persistWorkflowSnapshot({
|
|
793
1873
|
workflowName,
|
|
794
1874
|
runId,
|
|
795
1875
|
snapshot
|
|
796
1876
|
}) {
|
|
797
|
-
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1877
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
798
1878
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
799
|
-
const currentSnapshot = await this.load({
|
|
1879
|
+
const currentSnapshot = await this.operations.load({
|
|
800
1880
|
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
801
1881
|
keys: { workflow_name: workflowName, run_id: runId }
|
|
802
1882
|
});
|
|
@@ -811,7 +1891,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
811
1891
|
createdAt: now,
|
|
812
1892
|
updatedAt: now
|
|
813
1893
|
};
|
|
814
|
-
const processedRecord = await this.processRecord(persisting);
|
|
1894
|
+
const processedRecord = await this.operations.processRecord(persisting);
|
|
815
1895
|
const columns = Object.keys(processedRecord);
|
|
816
1896
|
const values = Object.values(processedRecord);
|
|
817
1897
|
const updateMap = {
|
|
@@ -822,143 +1902,43 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
822
1902
|
const query = createSqlBuilder().insert(fullTableName, columns, values, ["workflow_name", "run_id"], updateMap);
|
|
823
1903
|
const { sql, params } = query.build();
|
|
824
1904
|
try {
|
|
825
|
-
await this.executeQuery({ sql, params });
|
|
826
|
-
} catch (error) {
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
1905
|
+
await this.operations.executeQuery({ sql, params });
|
|
1906
|
+
} catch (error$1) {
|
|
1907
|
+
throw new error.MastraError(
|
|
1908
|
+
{
|
|
1909
|
+
id: "CLOUDFLARE_D1_STORAGE_PERSIST_WORKFLOW_SNAPSHOT_ERROR",
|
|
1910
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1911
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1912
|
+
text: `Failed to persist workflow snapshot: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1913
|
+
details: { workflowName, runId }
|
|
1914
|
+
},
|
|
1915
|
+
error$1
|
|
1916
|
+
);
|
|
831
1917
|
}
|
|
832
1918
|
}
|
|
833
1919
|
async loadWorkflowSnapshot(params) {
|
|
834
1920
|
const { workflowName, runId } = params;
|
|
835
1921
|
this.logger.debug("Loading workflow snapshot", { workflowName, runId });
|
|
836
|
-
const d = await this.load({
|
|
837
|
-
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
838
|
-
keys: {
|
|
839
|
-
workflow_name: workflowName,
|
|
840
|
-
run_id: runId
|
|
841
|
-
}
|
|
842
|
-
});
|
|
843
|
-
return d ? d.snapshot : null;
|
|
844
|
-
}
|
|
845
|
-
/**
|
|
846
|
-
* Insert multiple records in a batch operation
|
|
847
|
-
* @param tableName The table to insert into
|
|
848
|
-
* @param records The records to insert
|
|
849
|
-
*/
|
|
850
|
-
async batchInsert({ tableName, records }) {
|
|
851
|
-
if (records.length === 0) return;
|
|
852
|
-
const fullTableName = this.getTableName(tableName);
|
|
853
|
-
try {
|
|
854
|
-
const batchSize = 50;
|
|
855
|
-
for (let i = 0; i < records.length; i += batchSize) {
|
|
856
|
-
const batch = records.slice(i, i + batchSize);
|
|
857
|
-
const recordsToInsert = batch;
|
|
858
|
-
if (recordsToInsert.length > 0) {
|
|
859
|
-
const firstRecord = recordsToInsert[0];
|
|
860
|
-
const columns = Object.keys(firstRecord || {});
|
|
861
|
-
for (const record of recordsToInsert) {
|
|
862
|
-
const values = columns.map((col) => {
|
|
863
|
-
if (!record) return null;
|
|
864
|
-
const value = typeof col === "string" ? record[col] : null;
|
|
865
|
-
return this.serializeValue(value);
|
|
866
|
-
});
|
|
867
|
-
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
868
|
-
const { sql, params } = query.build();
|
|
869
|
-
await this.executeQuery({ sql, params });
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
this.logger.debug(
|
|
873
|
-
`Processed batch ${Math.floor(i / batchSize) + 1} of ${Math.ceil(records.length / batchSize)}`
|
|
874
|
-
);
|
|
875
|
-
}
|
|
876
|
-
this.logger.debug(`Successfully batch inserted ${records.length} records into ${tableName}`);
|
|
877
|
-
} catch (error) {
|
|
878
|
-
this.logger.error(`Error batch inserting into ${tableName}:`, {
|
|
879
|
-
message: error instanceof Error ? error.message : String(error)
|
|
880
|
-
});
|
|
881
|
-
throw new Error(`Failed to batch insert into ${tableName}: ${error}`);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
async getTraces({
|
|
885
|
-
name,
|
|
886
|
-
scope,
|
|
887
|
-
page,
|
|
888
|
-
perPage,
|
|
889
|
-
attributes,
|
|
890
|
-
fromDate,
|
|
891
|
-
toDate
|
|
892
|
-
}) {
|
|
893
|
-
const fullTableName = this.getTableName(storage.TABLE_TRACES);
|
|
894
1922
|
try {
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
query.andWhere("scope = ?", scope);
|
|
901
|
-
}
|
|
902
|
-
if (attributes && Object.keys(attributes).length > 0) {
|
|
903
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
904
|
-
query.jsonLike("attributes", key, value);
|
|
1923
|
+
const d = await this.operations.load({
|
|
1924
|
+
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
1925
|
+
keys: {
|
|
1926
|
+
workflow_name: workflowName,
|
|
1927
|
+
run_id: runId
|
|
905
1928
|
}
|
|
906
|
-
}
|
|
907
|
-
if (fromDate) {
|
|
908
|
-
query.andWhere("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
909
|
-
}
|
|
910
|
-
if (toDate) {
|
|
911
|
-
query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
912
|
-
}
|
|
913
|
-
query.orderBy("startTime", "DESC").limit(perPage).offset((page - 1) * perPage);
|
|
914
|
-
const { sql, params } = query.build();
|
|
915
|
-
const results = await this.executeQuery({ sql, params });
|
|
916
|
-
return isArrayOfRecords(results) ? results.map((trace) => ({
|
|
917
|
-
...trace,
|
|
918
|
-
attributes: this.deserializeValue(trace.attributes, "jsonb"),
|
|
919
|
-
status: this.deserializeValue(trace.status, "jsonb"),
|
|
920
|
-
events: this.deserializeValue(trace.events, "jsonb"),
|
|
921
|
-
links: this.deserializeValue(trace.links, "jsonb"),
|
|
922
|
-
other: this.deserializeValue(trace.other, "jsonb")
|
|
923
|
-
})) : [];
|
|
924
|
-
} catch (error) {
|
|
925
|
-
this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
|
|
926
|
-
return [];
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
async getEvalsByAgentName(agentName, type) {
|
|
930
|
-
const fullTableName = this.getTableName(storage.TABLE_EVALS);
|
|
931
|
-
try {
|
|
932
|
-
let query = createSqlBuilder().select("*").from(fullTableName).where("agent_name = ?", agentName);
|
|
933
|
-
if (type === "test") {
|
|
934
|
-
query = query.andWhere("test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL");
|
|
935
|
-
} else if (type === "live") {
|
|
936
|
-
query = query.andWhere("(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)");
|
|
937
|
-
}
|
|
938
|
-
query.orderBy("created_at", "DESC");
|
|
939
|
-
const { sql, params } = query.build();
|
|
940
|
-
const results = await this.executeQuery({ sql, params });
|
|
941
|
-
return isArrayOfRecords(results) ? results.map((row) => {
|
|
942
|
-
const result = this.deserializeValue(row.result);
|
|
943
|
-
const testInfo = row.test_info ? this.deserializeValue(row.test_info) : void 0;
|
|
944
|
-
return {
|
|
945
|
-
input: row.input || "",
|
|
946
|
-
output: row.output || "",
|
|
947
|
-
result,
|
|
948
|
-
agentName: row.agent_name || "",
|
|
949
|
-
metricName: row.metric_name || "",
|
|
950
|
-
instructions: row.instructions || "",
|
|
951
|
-
runId: row.run_id || "",
|
|
952
|
-
globalRunId: row.global_run_id || "",
|
|
953
|
-
createdAt: row.created_at || "",
|
|
954
|
-
testInfo
|
|
955
|
-
};
|
|
956
|
-
}) : [];
|
|
957
|
-
} catch (error) {
|
|
958
|
-
this.logger.error(`Error getting evals for agent ${agentName}:`, {
|
|
959
|
-
message: error instanceof Error ? error.message : String(error)
|
|
960
1929
|
});
|
|
961
|
-
return
|
|
1930
|
+
return d ? d.snapshot : null;
|
|
1931
|
+
} catch (error$1) {
|
|
1932
|
+
throw new error.MastraError(
|
|
1933
|
+
{
|
|
1934
|
+
id: "CLOUDFLARE_D1_STORAGE_LOAD_WORKFLOW_SNAPSHOT_ERROR",
|
|
1935
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1936
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1937
|
+
text: `Failed to load workflow snapshot: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1938
|
+
details: { workflowName, runId }
|
|
1939
|
+
},
|
|
1940
|
+
error$1
|
|
1941
|
+
);
|
|
962
1942
|
}
|
|
963
1943
|
}
|
|
964
1944
|
parseWorkflowRun(row) {
|
|
@@ -974,17 +1954,11 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
974
1954
|
workflowName: row.workflow_name,
|
|
975
1955
|
runId: row.run_id,
|
|
976
1956
|
snapshot: parsedSnapshot,
|
|
977
|
-
createdAt:
|
|
978
|
-
updatedAt:
|
|
1957
|
+
createdAt: storage.ensureDate(row.createdAt),
|
|
1958
|
+
updatedAt: storage.ensureDate(row.updatedAt),
|
|
979
1959
|
resourceId: row.resourceId
|
|
980
1960
|
};
|
|
981
1961
|
}
|
|
982
|
-
async hasColumn(table, column) {
|
|
983
|
-
const sql = `PRAGMA table_info(${table});`;
|
|
984
|
-
const result = await this.executeQuery({ sql, params: [] });
|
|
985
|
-
if (!result || !Array.isArray(result)) return false;
|
|
986
|
-
return result.some((col) => col.name === column || col.name === column.toLowerCase());
|
|
987
|
-
}
|
|
988
1962
|
async getWorkflowRuns({
|
|
989
1963
|
workflowName,
|
|
990
1964
|
fromDate,
|
|
@@ -993,13 +1967,13 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
993
1967
|
offset,
|
|
994
1968
|
resourceId
|
|
995
1969
|
} = {}) {
|
|
996
|
-
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1970
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
997
1971
|
try {
|
|
998
1972
|
const builder = createSqlBuilder().select().from(fullTableName);
|
|
999
1973
|
const countBuilder = createSqlBuilder().count().from(fullTableName);
|
|
1000
1974
|
if (workflowName) builder.whereAnd("workflow_name = ?", workflowName);
|
|
1001
1975
|
if (resourceId) {
|
|
1002
|
-
const hasResourceId = await this.hasColumn(fullTableName, "resourceId");
|
|
1976
|
+
const hasResourceId = await this.operations.hasColumn(fullTableName, "resourceId");
|
|
1003
1977
|
if (hasResourceId) {
|
|
1004
1978
|
builder.whereAnd("resourceId = ?", resourceId);
|
|
1005
1979
|
countBuilder.whereAnd("resourceId = ?", resourceId);
|
|
@@ -1022,24 +1996,37 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
1022
1996
|
let total = 0;
|
|
1023
1997
|
if (limit !== void 0 && offset !== void 0) {
|
|
1024
1998
|
const { sql: countSql, params: countParams } = countBuilder.build();
|
|
1025
|
-
const countResult = await this.executeQuery({
|
|
1999
|
+
const countResult = await this.operations.executeQuery({
|
|
2000
|
+
sql: countSql,
|
|
2001
|
+
params: countParams,
|
|
2002
|
+
first: true
|
|
2003
|
+
});
|
|
1026
2004
|
total = Number(countResult?.count ?? 0);
|
|
1027
2005
|
}
|
|
1028
|
-
const results = await this.executeQuery({ sql, params });
|
|
2006
|
+
const results = await this.operations.executeQuery({ sql, params });
|
|
1029
2007
|
const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
|
|
1030
2008
|
return { runs, total: total || runs.length };
|
|
1031
|
-
} catch (error) {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
2009
|
+
} catch (error$1) {
|
|
2010
|
+
throw new error.MastraError(
|
|
2011
|
+
{
|
|
2012
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_WORKFLOW_RUNS_ERROR",
|
|
2013
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2014
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2015
|
+
text: `Failed to retrieve workflow runs: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
2016
|
+
details: {
|
|
2017
|
+
workflowName: workflowName ?? "",
|
|
2018
|
+
resourceId: resourceId ?? ""
|
|
2019
|
+
}
|
|
2020
|
+
},
|
|
2021
|
+
error$1
|
|
2022
|
+
);
|
|
1036
2023
|
}
|
|
1037
2024
|
}
|
|
1038
2025
|
async getWorkflowRunById({
|
|
1039
2026
|
runId,
|
|
1040
2027
|
workflowName
|
|
1041
2028
|
}) {
|
|
1042
|
-
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
2029
|
+
const fullTableName = this.operations.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1043
2030
|
try {
|
|
1044
2031
|
const conditions = [];
|
|
1045
2032
|
const params = [];
|
|
@@ -1053,15 +2040,292 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
1053
2040
|
}
|
|
1054
2041
|
const whereClause = conditions.length > 0 ? "WHERE " + conditions.join(" AND ") : "";
|
|
1055
2042
|
const sql = `SELECT * FROM ${fullTableName} ${whereClause} ORDER BY createdAt DESC LIMIT 1`;
|
|
1056
|
-
const result = await this.executeQuery({ sql, params, first: true });
|
|
2043
|
+
const result = await this.operations.executeQuery({ sql, params, first: true });
|
|
1057
2044
|
if (!result) return null;
|
|
1058
2045
|
return this.parseWorkflowRun(result);
|
|
1059
|
-
} catch (error) {
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
2046
|
+
} catch (error$1) {
|
|
2047
|
+
throw new error.MastraError(
|
|
2048
|
+
{
|
|
2049
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_WORKFLOW_RUN_BY_ID_ERROR",
|
|
2050
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2051
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2052
|
+
text: `Failed to retrieve workflow run by ID: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
2053
|
+
details: { runId, workflowName: workflowName ?? "" }
|
|
2054
|
+
},
|
|
2055
|
+
error$1
|
|
2056
|
+
);
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
};
|
|
2060
|
+
|
|
2061
|
+
// src/storage/index.ts
|
|
2062
|
+
var D1Store = class extends storage.MastraStorage {
|
|
2063
|
+
client;
|
|
2064
|
+
binding;
|
|
2065
|
+
// D1Database binding
|
|
2066
|
+
tablePrefix;
|
|
2067
|
+
stores;
|
|
2068
|
+
/**
|
|
2069
|
+
* Creates a new D1Store instance
|
|
2070
|
+
* @param config Configuration for D1 access (either REST API or Workers Binding API)
|
|
2071
|
+
*/
|
|
2072
|
+
constructor(config) {
|
|
2073
|
+
try {
|
|
2074
|
+
super({ name: "D1" });
|
|
2075
|
+
if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
|
|
2076
|
+
throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
|
|
2077
|
+
}
|
|
2078
|
+
this.tablePrefix = config.tablePrefix || "";
|
|
2079
|
+
if ("binding" in config) {
|
|
2080
|
+
if (!config.binding) {
|
|
2081
|
+
throw new Error("D1 binding is required when using Workers Binding API");
|
|
2082
|
+
}
|
|
2083
|
+
this.binding = config.binding;
|
|
2084
|
+
this.logger.info("Using D1 Workers Binding API");
|
|
2085
|
+
} else if ("client" in config) {
|
|
2086
|
+
if (!config.client) {
|
|
2087
|
+
throw new Error("D1 client is required when using D1ClientConfig");
|
|
2088
|
+
}
|
|
2089
|
+
this.client = config.client;
|
|
2090
|
+
this.logger.info("Using D1 Client");
|
|
2091
|
+
} else {
|
|
2092
|
+
if (!config.accountId || !config.databaseId || !config.apiToken) {
|
|
2093
|
+
throw new Error("accountId, databaseId, and apiToken are required when using REST API");
|
|
2094
|
+
}
|
|
2095
|
+
const cfClient = new Cloudflare__default.default({
|
|
2096
|
+
apiToken: config.apiToken
|
|
2097
|
+
});
|
|
2098
|
+
this.client = {
|
|
2099
|
+
query: ({ sql, params }) => {
|
|
2100
|
+
return cfClient.d1.database.query(config.databaseId, {
|
|
2101
|
+
account_id: config.accountId,
|
|
2102
|
+
sql,
|
|
2103
|
+
params
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
this.logger.info("Using D1 REST API");
|
|
2108
|
+
}
|
|
2109
|
+
} catch (error$1) {
|
|
2110
|
+
throw new error.MastraError(
|
|
2111
|
+
{
|
|
2112
|
+
id: "CLOUDFLARE_D1_STORAGE_INITIALIZATION_ERROR",
|
|
2113
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2114
|
+
category: error.ErrorCategory.SYSTEM,
|
|
2115
|
+
text: "Error initializing D1Store"
|
|
2116
|
+
},
|
|
2117
|
+
error$1
|
|
2118
|
+
);
|
|
1064
2119
|
}
|
|
2120
|
+
const operations = new StoreOperationsD1({
|
|
2121
|
+
client: this.client,
|
|
2122
|
+
binding: this.binding,
|
|
2123
|
+
tablePrefix: this.tablePrefix
|
|
2124
|
+
});
|
|
2125
|
+
const scores = new ScoresStorageD1({
|
|
2126
|
+
operations
|
|
2127
|
+
});
|
|
2128
|
+
const legacyEvals = new LegacyEvalsStorageD1({
|
|
2129
|
+
operations
|
|
2130
|
+
});
|
|
2131
|
+
const traces = new TracesStorageD1({
|
|
2132
|
+
operations
|
|
2133
|
+
});
|
|
2134
|
+
const workflows = new WorkflowsStorageD1({
|
|
2135
|
+
operations
|
|
2136
|
+
});
|
|
2137
|
+
const memory = new MemoryStorageD1({
|
|
2138
|
+
operations
|
|
2139
|
+
});
|
|
2140
|
+
this.stores = {
|
|
2141
|
+
operations,
|
|
2142
|
+
scores,
|
|
2143
|
+
legacyEvals,
|
|
2144
|
+
traces,
|
|
2145
|
+
workflows,
|
|
2146
|
+
memory
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
get supports() {
|
|
2150
|
+
return {
|
|
2151
|
+
selectByIncludeResourceScope: true,
|
|
2152
|
+
resourceWorkingMemory: true,
|
|
2153
|
+
hasColumn: true,
|
|
2154
|
+
createTable: true
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
async createTable({
|
|
2158
|
+
tableName,
|
|
2159
|
+
schema
|
|
2160
|
+
}) {
|
|
2161
|
+
return this.stores.operations.createTable({ tableName, schema });
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Alters table schema to add columns if they don't exist
|
|
2165
|
+
* @param tableName Name of the table
|
|
2166
|
+
* @param schema Schema of the table
|
|
2167
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
2168
|
+
*/
|
|
2169
|
+
async alterTable({
|
|
2170
|
+
tableName,
|
|
2171
|
+
schema,
|
|
2172
|
+
ifNotExists
|
|
2173
|
+
}) {
|
|
2174
|
+
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
2175
|
+
}
|
|
2176
|
+
async clearTable({ tableName }) {
|
|
2177
|
+
return this.stores.operations.clearTable({ tableName });
|
|
2178
|
+
}
|
|
2179
|
+
async dropTable({ tableName }) {
|
|
2180
|
+
return this.stores.operations.dropTable({ tableName });
|
|
2181
|
+
}
|
|
2182
|
+
async hasColumn(table, column) {
|
|
2183
|
+
return this.stores.operations.hasColumn(table, column);
|
|
2184
|
+
}
|
|
2185
|
+
async insert({ tableName, record }) {
|
|
2186
|
+
return this.stores.operations.insert({ tableName, record });
|
|
2187
|
+
}
|
|
2188
|
+
async load({ tableName, keys }) {
|
|
2189
|
+
return this.stores.operations.load({ tableName, keys });
|
|
2190
|
+
}
|
|
2191
|
+
async getThreadById({ threadId }) {
|
|
2192
|
+
return this.stores.memory.getThreadById({ threadId });
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
2196
|
+
*/
|
|
2197
|
+
async getThreadsByResourceId({ resourceId }) {
|
|
2198
|
+
return this.stores.memory.getThreadsByResourceId({ resourceId });
|
|
2199
|
+
}
|
|
2200
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
2201
|
+
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2202
|
+
}
|
|
2203
|
+
async saveThread({ thread }) {
|
|
2204
|
+
return this.stores.memory.saveThread({ thread });
|
|
2205
|
+
}
|
|
2206
|
+
async updateThread({
|
|
2207
|
+
id,
|
|
2208
|
+
title,
|
|
2209
|
+
metadata
|
|
2210
|
+
}) {
|
|
2211
|
+
return this.stores.memory.updateThread({ id, title, metadata });
|
|
2212
|
+
}
|
|
2213
|
+
async deleteThread({ threadId }) {
|
|
2214
|
+
return this.stores.memory.deleteThread({ threadId });
|
|
2215
|
+
}
|
|
2216
|
+
async saveMessages(args) {
|
|
2217
|
+
return this.stores.memory.saveMessages(args);
|
|
2218
|
+
}
|
|
2219
|
+
async getMessages({
|
|
2220
|
+
threadId,
|
|
2221
|
+
selectBy,
|
|
2222
|
+
format
|
|
2223
|
+
}) {
|
|
2224
|
+
return this.stores.memory.getMessages({ threadId, selectBy, format });
|
|
2225
|
+
}
|
|
2226
|
+
async getMessagesPaginated({
|
|
2227
|
+
threadId,
|
|
2228
|
+
selectBy,
|
|
2229
|
+
format
|
|
2230
|
+
}) {
|
|
2231
|
+
return this.stores.memory.getMessagesPaginated({ threadId, selectBy, format });
|
|
2232
|
+
}
|
|
2233
|
+
async persistWorkflowSnapshot({
|
|
2234
|
+
workflowName,
|
|
2235
|
+
runId,
|
|
2236
|
+
snapshot
|
|
2237
|
+
}) {
|
|
2238
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
2239
|
+
}
|
|
2240
|
+
async loadWorkflowSnapshot(params) {
|
|
2241
|
+
return this.stores.workflows.loadWorkflowSnapshot(params);
|
|
2242
|
+
}
|
|
2243
|
+
async getWorkflowRuns({
|
|
2244
|
+
workflowName,
|
|
2245
|
+
fromDate,
|
|
2246
|
+
toDate,
|
|
2247
|
+
limit,
|
|
2248
|
+
offset,
|
|
2249
|
+
resourceId
|
|
2250
|
+
} = {}) {
|
|
2251
|
+
return this.stores.workflows.getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
|
|
2252
|
+
}
|
|
2253
|
+
async getWorkflowRunById({
|
|
2254
|
+
runId,
|
|
2255
|
+
workflowName
|
|
2256
|
+
}) {
|
|
2257
|
+
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
2258
|
+
}
|
|
2259
|
+
/**
|
|
2260
|
+
* Insert multiple records in a batch operation
|
|
2261
|
+
* @param tableName The table to insert into
|
|
2262
|
+
* @param records The records to insert
|
|
2263
|
+
*/
|
|
2264
|
+
async batchInsert({ tableName, records }) {
|
|
2265
|
+
return this.stores.operations.batchInsert({ tableName, records });
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* @deprecated use getTracesPaginated instead
|
|
2269
|
+
*/
|
|
2270
|
+
async getTraces(args) {
|
|
2271
|
+
return this.stores.traces.getTraces(args);
|
|
2272
|
+
}
|
|
2273
|
+
async getTracesPaginated(args) {
|
|
2274
|
+
return this.stores.traces.getTracesPaginated(args);
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* @deprecated use getEvals instead
|
|
2278
|
+
*/
|
|
2279
|
+
async getEvalsByAgentName(agentName, type) {
|
|
2280
|
+
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2281
|
+
}
|
|
2282
|
+
async getEvals(options) {
|
|
2283
|
+
return this.stores.legacyEvals.getEvals(options);
|
|
2284
|
+
}
|
|
2285
|
+
async updateMessages(_args) {
|
|
2286
|
+
return this.stores.memory.updateMessages(_args);
|
|
2287
|
+
}
|
|
2288
|
+
async getResourceById({ resourceId }) {
|
|
2289
|
+
return this.stores.memory.getResourceById({ resourceId });
|
|
2290
|
+
}
|
|
2291
|
+
async saveResource({ resource }) {
|
|
2292
|
+
return this.stores.memory.saveResource({ resource });
|
|
2293
|
+
}
|
|
2294
|
+
async updateResource({
|
|
2295
|
+
resourceId,
|
|
2296
|
+
workingMemory,
|
|
2297
|
+
metadata
|
|
2298
|
+
}) {
|
|
2299
|
+
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
2300
|
+
}
|
|
2301
|
+
async getScoreById({ id: _id }) {
|
|
2302
|
+
return this.stores.scores.getScoreById({ id: _id });
|
|
2303
|
+
}
|
|
2304
|
+
async saveScore(_score) {
|
|
2305
|
+
return this.stores.scores.saveScore(_score);
|
|
2306
|
+
}
|
|
2307
|
+
async getScoresByRunId({
|
|
2308
|
+
runId: _runId,
|
|
2309
|
+
pagination: _pagination
|
|
2310
|
+
}) {
|
|
2311
|
+
return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
|
|
2312
|
+
}
|
|
2313
|
+
async getScoresByEntityId({
|
|
2314
|
+
entityId: _entityId,
|
|
2315
|
+
entityType: _entityType,
|
|
2316
|
+
pagination: _pagination
|
|
2317
|
+
}) {
|
|
2318
|
+
return this.stores.scores.getScoresByEntityId({
|
|
2319
|
+
entityId: _entityId,
|
|
2320
|
+
entityType: _entityType,
|
|
2321
|
+
pagination: _pagination
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
async getScoresByScorerId({
|
|
2325
|
+
scorerId: _scorerId,
|
|
2326
|
+
pagination: _pagination
|
|
2327
|
+
}) {
|
|
2328
|
+
return this.stores.scores.getScoresByScorerId({ scorerId: _scorerId, pagination: _pagination });
|
|
1065
2329
|
}
|
|
1066
2330
|
/**
|
|
1067
2331
|
* Close the database connection
|