@mastra/cloudflare-d1 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-tool-call-parts-20250630193309
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/dist/_tsup-dts-rollup.d.cts +78 -38
- package/dist/_tsup-dts-rollup.d.ts +78 -38
- package/dist/index.cjs +728 -181
- package/dist/index.js +710 -163
- package/package.json +15 -14
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MessageList } from '@mastra/core/agent';
|
|
2
|
+
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
2
3
|
import { MastraStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT, TABLE_TRACES, TABLE_EVALS } from '@mastra/core/storage';
|
|
3
4
|
import Cloudflare from 'cloudflare';
|
|
4
5
|
import { parseSqlIdentifier } from '@mastra/core/utils';
|
|
@@ -250,27 +251,39 @@ var D1Store = class extends MastraStorage {
|
|
|
250
251
|
* @param config Configuration for D1 access (either REST API or Workers Binding API)
|
|
251
252
|
*/
|
|
252
253
|
constructor(config) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
this.tablePrefix = config.tablePrefix || "";
|
|
258
|
-
if ("binding" in config) {
|
|
259
|
-
if (!config.binding) {
|
|
260
|
-
throw new Error("D1 binding is required when using Workers Binding API");
|
|
254
|
+
try {
|
|
255
|
+
super({ name: "D1" });
|
|
256
|
+
if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
|
|
257
|
+
throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
|
|
261
258
|
}
|
|
262
|
-
this.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
259
|
+
this.tablePrefix = config.tablePrefix || "";
|
|
260
|
+
if ("binding" in config) {
|
|
261
|
+
if (!config.binding) {
|
|
262
|
+
throw new Error("D1 binding is required when using Workers Binding API");
|
|
263
|
+
}
|
|
264
|
+
this.binding = config.binding;
|
|
265
|
+
this.logger.info("Using D1 Workers Binding API");
|
|
266
|
+
} else {
|
|
267
|
+
if (!config.accountId || !config.databaseId || !config.apiToken) {
|
|
268
|
+
throw new Error("accountId, databaseId, and apiToken are required when using REST API");
|
|
269
|
+
}
|
|
270
|
+
this.accountId = config.accountId;
|
|
271
|
+
this.databaseId = config.databaseId;
|
|
272
|
+
this.client = new Cloudflare({
|
|
273
|
+
apiToken: config.apiToken
|
|
274
|
+
});
|
|
275
|
+
this.logger.info("Using D1 REST API");
|
|
267
276
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
277
|
+
} catch (error) {
|
|
278
|
+
throw new MastraError(
|
|
279
|
+
{
|
|
280
|
+
id: "CLOUDFLARE_D1_STORAGE_INITIALIZATION_ERROR",
|
|
281
|
+
domain: ErrorDomain.STORAGE,
|
|
282
|
+
category: ErrorCategory.SYSTEM,
|
|
283
|
+
text: "Error initializing D1Store"
|
|
284
|
+
},
|
|
285
|
+
error
|
|
286
|
+
);
|
|
274
287
|
}
|
|
275
288
|
}
|
|
276
289
|
// Helper method to get the full table name with prefix
|
|
@@ -383,34 +396,25 @@ var D1Store = class extends MastraStorage {
|
|
|
383
396
|
throw new Error(`D1 query error: ${error.message}`);
|
|
384
397
|
}
|
|
385
398
|
}
|
|
386
|
-
// Helper to
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
return
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
399
|
+
// Helper to get existing table columns
|
|
400
|
+
async getTableColumns(tableName) {
|
|
401
|
+
try {
|
|
402
|
+
const sql = `PRAGMA table_info(${tableName})`;
|
|
403
|
+
const result = await this.executeQuery({ sql, params: [] });
|
|
404
|
+
if (!result || !Array.isArray(result)) {
|
|
405
|
+
return [];
|
|
406
|
+
}
|
|
407
|
+
return result.map((row) => ({
|
|
408
|
+
name: row.name,
|
|
409
|
+
type: row.type
|
|
410
|
+
}));
|
|
411
|
+
} catch (error) {
|
|
412
|
+
this.logger.error(`Error getting table columns for ${tableName}:`, {
|
|
413
|
+
message: error instanceof Error ? error.message : String(error)
|
|
414
|
+
});
|
|
415
|
+
return [];
|
|
403
416
|
}
|
|
404
417
|
}
|
|
405
|
-
ensureDate(date) {
|
|
406
|
-
if (!date) return void 0;
|
|
407
|
-
return date instanceof Date ? date : new Date(date);
|
|
408
|
-
}
|
|
409
|
-
serializeDate(date) {
|
|
410
|
-
if (!date) return void 0;
|
|
411
|
-
const dateObj = this.ensureDate(date);
|
|
412
|
-
return dateObj?.toISOString();
|
|
413
|
-
}
|
|
414
418
|
// Helper to serialize objects to JSON strings
|
|
415
419
|
serializeValue(value) {
|
|
416
420
|
if (value === null || value === void 0) return null;
|
|
@@ -444,6 +448,18 @@ var D1Store = class extends MastraStorage {
|
|
|
444
448
|
}
|
|
445
449
|
return value;
|
|
446
450
|
}
|
|
451
|
+
getSqlType(type) {
|
|
452
|
+
switch (type) {
|
|
453
|
+
case "bigint":
|
|
454
|
+
return "INTEGER";
|
|
455
|
+
// SQLite uses INTEGER for all integer sizes
|
|
456
|
+
case "jsonb":
|
|
457
|
+
return "TEXT";
|
|
458
|
+
// Store JSON as TEXT in SQLite
|
|
459
|
+
default:
|
|
460
|
+
return super.getSqlType(type);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
447
463
|
async createTable({
|
|
448
464
|
tableName,
|
|
449
465
|
schema
|
|
@@ -459,16 +475,64 @@ var D1Store = class extends MastraStorage {
|
|
|
459
475
|
if (tableName === TABLE_WORKFLOW_SNAPSHOT) {
|
|
460
476
|
tableConstraints.push("UNIQUE (workflow_name, run_id)");
|
|
461
477
|
}
|
|
462
|
-
const query = createSqlBuilder().createTable(fullTableName, columnDefinitions, tableConstraints);
|
|
463
|
-
const { sql, params } = query.build();
|
|
464
478
|
try {
|
|
479
|
+
const query = createSqlBuilder().createTable(fullTableName, columnDefinitions, tableConstraints);
|
|
480
|
+
const { sql, params } = query.build();
|
|
465
481
|
await this.executeQuery({ sql, params });
|
|
466
482
|
this.logger.debug(`Created table ${fullTableName}`);
|
|
467
483
|
} catch (error) {
|
|
468
484
|
this.logger.error(`Error creating table ${fullTableName}:`, {
|
|
469
485
|
message: error instanceof Error ? error.message : String(error)
|
|
470
486
|
});
|
|
471
|
-
throw new
|
|
487
|
+
throw new MastraError(
|
|
488
|
+
{
|
|
489
|
+
id: "CLOUDFLARE_D1_STORAGE_CREATE_TABLE_ERROR",
|
|
490
|
+
domain: ErrorDomain.STORAGE,
|
|
491
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
492
|
+
text: `Failed to create table ${fullTableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
493
|
+
details: { tableName }
|
|
494
|
+
},
|
|
495
|
+
error
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Alters table schema to add columns if they don't exist
|
|
501
|
+
* @param tableName Name of the table
|
|
502
|
+
* @param schema Schema of the table
|
|
503
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
504
|
+
*/
|
|
505
|
+
async alterTable({
|
|
506
|
+
tableName,
|
|
507
|
+
schema,
|
|
508
|
+
ifNotExists
|
|
509
|
+
}) {
|
|
510
|
+
const fullTableName = this.getTableName(tableName);
|
|
511
|
+
try {
|
|
512
|
+
const existingColumns = await this.getTableColumns(fullTableName);
|
|
513
|
+
const existingColumnNames = new Set(existingColumns.map((col) => col.name.toLowerCase()));
|
|
514
|
+
for (const columnName of ifNotExists) {
|
|
515
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
516
|
+
const columnDef = schema[columnName];
|
|
517
|
+
const sqlType = this.getSqlType(columnDef.type);
|
|
518
|
+
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
519
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
520
|
+
const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN ${columnName} ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
521
|
+
await this.executeQuery({ sql: alterSql, params: [] });
|
|
522
|
+
this.logger.debug(`Added column ${columnName} to table ${fullTableName}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
} catch (error) {
|
|
526
|
+
throw new MastraError(
|
|
527
|
+
{
|
|
528
|
+
id: "CLOUDFLARE_D1_STORAGE_ALTER_TABLE_ERROR",
|
|
529
|
+
domain: ErrorDomain.STORAGE,
|
|
530
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
531
|
+
text: `Failed to alter table ${fullTableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
532
|
+
details: { tableName }
|
|
533
|
+
},
|
|
534
|
+
error
|
|
535
|
+
);
|
|
472
536
|
}
|
|
473
537
|
}
|
|
474
538
|
async clearTable({ tableName }) {
|
|
@@ -479,10 +543,16 @@ var D1Store = class extends MastraStorage {
|
|
|
479
543
|
await this.executeQuery({ sql, params });
|
|
480
544
|
this.logger.debug(`Cleared table ${fullTableName}`);
|
|
481
545
|
} catch (error) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
546
|
+
throw new MastraError(
|
|
547
|
+
{
|
|
548
|
+
id: "CLOUDFLARE_D1_STORAGE_CLEAR_TABLE_ERROR",
|
|
549
|
+
domain: ErrorDomain.STORAGE,
|
|
550
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
551
|
+
text: `Failed to clear table ${fullTableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
552
|
+
details: { tableName }
|
|
553
|
+
},
|
|
554
|
+
error
|
|
555
|
+
);
|
|
486
556
|
}
|
|
487
557
|
}
|
|
488
558
|
async processRecord(record) {
|
|
@@ -502,9 +572,16 @@ var D1Store = class extends MastraStorage {
|
|
|
502
572
|
try {
|
|
503
573
|
await this.executeQuery({ sql, params });
|
|
504
574
|
} catch (error) {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
575
|
+
throw new MastraError(
|
|
576
|
+
{
|
|
577
|
+
id: "CLOUDFLARE_D1_STORAGE_INSERT_ERROR",
|
|
578
|
+
domain: ErrorDomain.STORAGE,
|
|
579
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
580
|
+
text: `Failed to insert into ${fullTableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
581
|
+
details: { tableName }
|
|
582
|
+
},
|
|
583
|
+
error
|
|
584
|
+
);
|
|
508
585
|
}
|
|
509
586
|
}
|
|
510
587
|
async load({ tableName, keys }) {
|
|
@@ -530,10 +607,16 @@ var D1Store = class extends MastraStorage {
|
|
|
530
607
|
}
|
|
531
608
|
return processedResult;
|
|
532
609
|
} catch (error) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
610
|
+
throw new MastraError(
|
|
611
|
+
{
|
|
612
|
+
id: "CLOUDFLARE_D1_STORAGE_LOAD_ERROR",
|
|
613
|
+
domain: ErrorDomain.STORAGE,
|
|
614
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
615
|
+
text: `Failed to load from ${fullTableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
616
|
+
details: { tableName }
|
|
617
|
+
},
|
|
618
|
+
error
|
|
619
|
+
);
|
|
537
620
|
}
|
|
538
621
|
}
|
|
539
622
|
async getThreadById({ threadId }) {
|
|
@@ -550,12 +633,24 @@ var D1Store = class extends MastraStorage {
|
|
|
550
633
|
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata || "{}") : thread.metadata || {}
|
|
551
634
|
};
|
|
552
635
|
} catch (error) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
636
|
+
const mastraError = new MastraError(
|
|
637
|
+
{
|
|
638
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_THREAD_BY_ID_ERROR",
|
|
639
|
+
domain: ErrorDomain.STORAGE,
|
|
640
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
641
|
+
text: `Error processing thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
642
|
+
details: { threadId }
|
|
643
|
+
},
|
|
644
|
+
error
|
|
645
|
+
);
|
|
646
|
+
this.logger?.error(mastraError.toString());
|
|
647
|
+
this.logger?.trackException(mastraError);
|
|
556
648
|
return null;
|
|
557
649
|
}
|
|
558
650
|
}
|
|
651
|
+
/**
|
|
652
|
+
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
653
|
+
*/
|
|
559
654
|
async getThreadsByResourceId({ resourceId }) {
|
|
560
655
|
const fullTableName = this.getTableName(TABLE_THREADS);
|
|
561
656
|
try {
|
|
@@ -569,12 +664,66 @@ var D1Store = class extends MastraStorage {
|
|
|
569
664
|
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata || "{}") : thread.metadata || {}
|
|
570
665
|
}));
|
|
571
666
|
} catch (error) {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
667
|
+
const mastraError = new MastraError(
|
|
668
|
+
{
|
|
669
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_THREADS_BY_RESOURCE_ID_ERROR",
|
|
670
|
+
domain: ErrorDomain.STORAGE,
|
|
671
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
672
|
+
text: `Error getting threads by resourceId ${resourceId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
673
|
+
details: { resourceId }
|
|
674
|
+
},
|
|
675
|
+
error
|
|
676
|
+
);
|
|
677
|
+
this.logger?.error(mastraError.toString());
|
|
678
|
+
this.logger?.trackException(mastraError);
|
|
575
679
|
return [];
|
|
576
680
|
}
|
|
577
681
|
}
|
|
682
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
683
|
+
const { resourceId, page, perPage } = args;
|
|
684
|
+
const fullTableName = this.getTableName(TABLE_THREADS);
|
|
685
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
686
|
+
...row,
|
|
687
|
+
createdAt: this.ensureDate(row.createdAt),
|
|
688
|
+
updatedAt: this.ensureDate(row.updatedAt),
|
|
689
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
|
|
690
|
+
});
|
|
691
|
+
try {
|
|
692
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
|
|
693
|
+
const countResult = await this.executeQuery(countQuery.build());
|
|
694
|
+
const total = Number(countResult?.[0]?.count ?? 0);
|
|
695
|
+
const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
|
|
696
|
+
const results = await this.executeQuery(selectQuery.build());
|
|
697
|
+
const threads = results.map(mapRowToStorageThreadType);
|
|
698
|
+
return {
|
|
699
|
+
threads,
|
|
700
|
+
total,
|
|
701
|
+
page,
|
|
702
|
+
perPage,
|
|
703
|
+
hasMore: page * perPage + threads.length < total
|
|
704
|
+
};
|
|
705
|
+
} catch (error) {
|
|
706
|
+
const mastraError = new MastraError(
|
|
707
|
+
{
|
|
708
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_ERROR",
|
|
709
|
+
domain: ErrorDomain.STORAGE,
|
|
710
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
711
|
+
text: `Error getting threads by resourceId ${resourceId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
712
|
+
details: { resourceId }
|
|
713
|
+
},
|
|
714
|
+
error
|
|
715
|
+
);
|
|
716
|
+
this.logger?.error(mastraError.toString());
|
|
717
|
+
this.logger?.trackException(mastraError);
|
|
718
|
+
return {
|
|
719
|
+
threads: [],
|
|
720
|
+
total: 0,
|
|
721
|
+
page,
|
|
722
|
+
perPage,
|
|
723
|
+
hasMore: false
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
}
|
|
578
727
|
async saveThread({ thread }) {
|
|
579
728
|
const fullTableName = this.getTableName(TABLE_THREADS);
|
|
580
729
|
const threadToSave = {
|
|
@@ -601,9 +750,16 @@ var D1Store = class extends MastraStorage {
|
|
|
601
750
|
await this.executeQuery({ sql, params });
|
|
602
751
|
return thread;
|
|
603
752
|
} catch (error) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
753
|
+
throw new MastraError(
|
|
754
|
+
{
|
|
755
|
+
id: "CLOUDFLARE_D1_STORAGE_SAVE_THREAD_ERROR",
|
|
756
|
+
domain: ErrorDomain.STORAGE,
|
|
757
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
758
|
+
text: `Failed to save thread to ${fullTableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
759
|
+
details: { threadId: thread.id }
|
|
760
|
+
},
|
|
761
|
+
error
|
|
762
|
+
);
|
|
607
763
|
}
|
|
608
764
|
}
|
|
609
765
|
async updateThread({
|
|
@@ -612,19 +768,19 @@ var D1Store = class extends MastraStorage {
|
|
|
612
768
|
metadata
|
|
613
769
|
}) {
|
|
614
770
|
const thread = await this.getThreadById({ threadId: id });
|
|
615
|
-
if (!thread) {
|
|
616
|
-
throw new Error(`Thread ${id} not found`);
|
|
617
|
-
}
|
|
618
|
-
const fullTableName = this.getTableName(TABLE_THREADS);
|
|
619
|
-
const mergedMetadata = {
|
|
620
|
-
...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
621
|
-
...metadata
|
|
622
|
-
};
|
|
623
|
-
const columns = ["title", "metadata", "updatedAt"];
|
|
624
|
-
const values = [title, JSON.stringify(mergedMetadata), (/* @__PURE__ */ new Date()).toISOString()];
|
|
625
|
-
const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", id);
|
|
626
|
-
const { sql, params } = query.build();
|
|
627
771
|
try {
|
|
772
|
+
if (!thread) {
|
|
773
|
+
throw new Error(`Thread ${id} not found`);
|
|
774
|
+
}
|
|
775
|
+
const fullTableName = this.getTableName(TABLE_THREADS);
|
|
776
|
+
const mergedMetadata = {
|
|
777
|
+
...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
778
|
+
...metadata
|
|
779
|
+
};
|
|
780
|
+
const columns = ["title", "metadata", "updatedAt"];
|
|
781
|
+
const values = [title, JSON.stringify(mergedMetadata), (/* @__PURE__ */ new Date()).toISOString()];
|
|
782
|
+
const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", id);
|
|
783
|
+
const { sql, params } = query.build();
|
|
628
784
|
await this.executeQuery({ sql, params });
|
|
629
785
|
return {
|
|
630
786
|
...thread,
|
|
@@ -636,9 +792,16 @@ var D1Store = class extends MastraStorage {
|
|
|
636
792
|
updatedAt: /* @__PURE__ */ new Date()
|
|
637
793
|
};
|
|
638
794
|
} catch (error) {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
795
|
+
throw new MastraError(
|
|
796
|
+
{
|
|
797
|
+
id: "CLOUDFLARE_D1_STORAGE_UPDATE_THREAD_ERROR",
|
|
798
|
+
domain: ErrorDomain.STORAGE,
|
|
799
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
800
|
+
text: `Failed to update thread ${id}: ${error instanceof Error ? error.message : String(error)}`,
|
|
801
|
+
details: { threadId: id }
|
|
802
|
+
},
|
|
803
|
+
error
|
|
804
|
+
);
|
|
642
805
|
}
|
|
643
806
|
}
|
|
644
807
|
async deleteThread({ threadId }) {
|
|
@@ -652,10 +815,16 @@ var D1Store = class extends MastraStorage {
|
|
|
652
815
|
const { sql: messagesSql, params: messagesParams } = deleteMessagesQuery.build();
|
|
653
816
|
await this.executeQuery({ sql: messagesSql, params: messagesParams });
|
|
654
817
|
} catch (error) {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
818
|
+
throw new MastraError(
|
|
819
|
+
{
|
|
820
|
+
id: "CLOUDFLARE_D1_STORAGE_DELETE_THREAD_ERROR",
|
|
821
|
+
domain: ErrorDomain.STORAGE,
|
|
822
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
823
|
+
text: `Failed to delete thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
824
|
+
details: { threadId }
|
|
825
|
+
},
|
|
826
|
+
error
|
|
827
|
+
);
|
|
659
828
|
}
|
|
660
829
|
}
|
|
661
830
|
async saveMessages(args) {
|
|
@@ -663,6 +832,7 @@ var D1Store = class extends MastraStorage {
|
|
|
663
832
|
if (messages.length === 0) return [];
|
|
664
833
|
try {
|
|
665
834
|
const now = /* @__PURE__ */ new Date();
|
|
835
|
+
const threadId = messages[0]?.threadId;
|
|
666
836
|
for (const [i, message] of messages.entries()) {
|
|
667
837
|
if (!message.id) throw new Error(`Message at index ${i} missing id`);
|
|
668
838
|
if (!message.threadId) throw new Error(`Message at index ${i} missing threadId`);
|
|
@@ -681,42 +851,49 @@ var D1Store = class extends MastraStorage {
|
|
|
681
851
|
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
682
852
|
createdAt: createdAt.toISOString(),
|
|
683
853
|
role: message.role,
|
|
684
|
-
type: message.type || "v2"
|
|
854
|
+
type: message.type || "v2",
|
|
855
|
+
resourceId: message.resourceId
|
|
685
856
|
};
|
|
686
857
|
});
|
|
687
|
-
await
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
858
|
+
await Promise.all([
|
|
859
|
+
this.batchUpsert({
|
|
860
|
+
tableName: TABLE_MESSAGES,
|
|
861
|
+
records: messagesToInsert
|
|
862
|
+
}),
|
|
863
|
+
// Update thread's updatedAt timestamp
|
|
864
|
+
this.executeQuery({
|
|
865
|
+
sql: `UPDATE ${this.getTableName(TABLE_THREADS)} SET updatedAt = ? WHERE id = ?`,
|
|
866
|
+
params: [now.toISOString(), threadId]
|
|
867
|
+
})
|
|
868
|
+
]);
|
|
691
869
|
this.logger.debug(`Saved ${messages.length} messages`);
|
|
692
870
|
const list = new MessageList().add(messages, "memory");
|
|
693
871
|
if (format === `v2`) return list.get.all.v2();
|
|
694
872
|
return list.get.all.v1();
|
|
695
873
|
} catch (error) {
|
|
696
|
-
|
|
697
|
-
|
|
874
|
+
throw new MastraError(
|
|
875
|
+
{
|
|
876
|
+
id: "CLOUDFLARE_D1_STORAGE_SAVE_MESSAGES_ERROR",
|
|
877
|
+
domain: ErrorDomain.STORAGE,
|
|
878
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
879
|
+
text: `Failed to save messages: ${error instanceof Error ? error.message : String(error)}`
|
|
880
|
+
},
|
|
881
|
+
error
|
|
882
|
+
);
|
|
698
883
|
}
|
|
699
884
|
}
|
|
700
|
-
async
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
const
|
|
706
|
-
const
|
|
707
|
-
const include = selectBy?.include || [];
|
|
708
|
-
const messages = [];
|
|
709
|
-
try {
|
|
710
|
-
if (include.length) {
|
|
711
|
-
const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
|
|
712
|
-
const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
|
|
713
|
-
const includeIds = include.map((i) => i.id);
|
|
714
|
-
const sql2 = `
|
|
885
|
+
async _getIncludedMessages(threadId, selectBy) {
|
|
886
|
+
const include = selectBy?.include;
|
|
887
|
+
if (!include) return null;
|
|
888
|
+
const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
|
|
889
|
+
const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
|
|
890
|
+
const includeIds = include.map((i) => i.id);
|
|
891
|
+
const sql = `
|
|
715
892
|
WITH ordered_messages AS (
|
|
716
893
|
SELECT
|
|
717
894
|
*,
|
|
718
895
|
ROW_NUMBER() OVER (ORDER BY createdAt DESC) AS row_num
|
|
719
|
-
FROM ${
|
|
896
|
+
FROM ${this.getTableName(TABLE_MESSAGES)}
|
|
720
897
|
WHERE thread_id = ?
|
|
721
898
|
)
|
|
722
899
|
SELECT
|
|
@@ -739,20 +916,38 @@ var D1Store = class extends MastraStorage {
|
|
|
739
916
|
)
|
|
740
917
|
ORDER BY m.createdAt DESC
|
|
741
918
|
`;
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
919
|
+
const params = [
|
|
920
|
+
threadId,
|
|
921
|
+
...includeIds,
|
|
922
|
+
// for m.id IN (...)
|
|
923
|
+
...includeIds,
|
|
924
|
+
// for target.id IN (...)
|
|
925
|
+
prevMax,
|
|
926
|
+
nextMax
|
|
927
|
+
];
|
|
928
|
+
const messages = await this.executeQuery({ sql, params });
|
|
929
|
+
return messages;
|
|
930
|
+
}
|
|
931
|
+
async getMessages({
|
|
932
|
+
threadId,
|
|
933
|
+
selectBy,
|
|
934
|
+
format
|
|
935
|
+
}) {
|
|
936
|
+
const fullTableName = this.getTableName(TABLE_MESSAGES);
|
|
937
|
+
const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
938
|
+
const include = selectBy?.include || [];
|
|
939
|
+
const messages = [];
|
|
940
|
+
try {
|
|
941
|
+
if (include.length) {
|
|
942
|
+
const includeResult = await this._getIncludedMessages(threadId, selectBy);
|
|
752
943
|
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
753
944
|
}
|
|
754
945
|
const excludeIds = messages.map((m) => m.id);
|
|
755
|
-
|
|
946
|
+
const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
|
|
947
|
+
if (excludeIds.length > 0) {
|
|
948
|
+
query.andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds);
|
|
949
|
+
}
|
|
950
|
+
query.orderBy("createdAt", "DESC").limit(limit);
|
|
756
951
|
const { sql, params } = query.build();
|
|
757
952
|
const result = await this.executeQuery({ sql, params });
|
|
758
953
|
if (Array.isArray(result)) messages.push(...result);
|
|
@@ -776,11 +971,82 @@ var D1Store = class extends MastraStorage {
|
|
|
776
971
|
if (format === `v2`) return list.get.all.v2();
|
|
777
972
|
return list.get.all.v1();
|
|
778
973
|
} catch (error) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
974
|
+
const mastraError = new MastraError(
|
|
975
|
+
{
|
|
976
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_MESSAGES_ERROR",
|
|
977
|
+
domain: ErrorDomain.STORAGE,
|
|
978
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
979
|
+
text: `Failed to retrieve messages for thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
980
|
+
details: { threadId }
|
|
981
|
+
},
|
|
982
|
+
error
|
|
983
|
+
);
|
|
984
|
+
this.logger?.error(mastraError.toString());
|
|
985
|
+
this.logger?.trackException(mastraError);
|
|
986
|
+
throw mastraError;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
async getMessagesPaginated({
|
|
990
|
+
threadId,
|
|
991
|
+
selectBy,
|
|
992
|
+
format
|
|
993
|
+
}) {
|
|
994
|
+
const { dateRange, page = 0, perPage = 40 } = selectBy?.pagination || {};
|
|
995
|
+
const { start: fromDate, end: toDate } = dateRange || {};
|
|
996
|
+
const fullTableName = this.getTableName(TABLE_MESSAGES);
|
|
997
|
+
const messages = [];
|
|
998
|
+
try {
|
|
999
|
+
if (selectBy?.include?.length) {
|
|
1000
|
+
const includeResult = await this._getIncludedMessages(threadId, selectBy);
|
|
1001
|
+
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
1002
|
+
}
|
|
1003
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("thread_id = ?", threadId);
|
|
1004
|
+
if (fromDate) {
|
|
1005
|
+
countQuery.andWhere("createdAt >= ?", this.serializeDate(fromDate));
|
|
1006
|
+
}
|
|
1007
|
+
if (toDate) {
|
|
1008
|
+
countQuery.andWhere("createdAt <= ?", this.serializeDate(toDate));
|
|
1009
|
+
}
|
|
1010
|
+
const countResult = await this.executeQuery(countQuery.build());
|
|
1011
|
+
const total = Number(countResult[0]?.count ?? 0);
|
|
1012
|
+
const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
|
|
1013
|
+
if (fromDate) {
|
|
1014
|
+
query.andWhere("createdAt >= ?", this.serializeDate(fromDate));
|
|
1015
|
+
}
|
|
1016
|
+
if (toDate) {
|
|
1017
|
+
query.andWhere("createdAt <= ?", this.serializeDate(toDate));
|
|
1018
|
+
}
|
|
1019
|
+
query.orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
|
|
1020
|
+
const results = await this.executeQuery(query.build());
|
|
1021
|
+
const list = new MessageList().add(results, "memory");
|
|
1022
|
+
messages.push(...format === `v2` ? list.get.all.v2() : list.get.all.v1());
|
|
1023
|
+
return {
|
|
1024
|
+
messages,
|
|
1025
|
+
total,
|
|
1026
|
+
page,
|
|
1027
|
+
perPage,
|
|
1028
|
+
hasMore: page * perPage + messages.length < total
|
|
1029
|
+
};
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
const mastraError = new MastraError(
|
|
1032
|
+
{
|
|
1033
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_MESSAGES_PAGINATED_ERROR",
|
|
1034
|
+
domain: ErrorDomain.STORAGE,
|
|
1035
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1036
|
+
text: `Failed to retrieve messages for thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1037
|
+
details: { threadId }
|
|
1038
|
+
},
|
|
1039
|
+
error
|
|
1040
|
+
);
|
|
1041
|
+
this.logger?.error(mastraError.toString());
|
|
1042
|
+
this.logger?.trackException(mastraError);
|
|
1043
|
+
return {
|
|
1044
|
+
messages: [],
|
|
1045
|
+
total: 0,
|
|
1046
|
+
page,
|
|
1047
|
+
perPage,
|
|
1048
|
+
hasMore: false
|
|
1049
|
+
};
|
|
784
1050
|
}
|
|
785
1051
|
}
|
|
786
1052
|
async persistWorkflowSnapshot({
|
|
@@ -818,23 +1084,42 @@ var D1Store = class extends MastraStorage {
|
|
|
818
1084
|
try {
|
|
819
1085
|
await this.executeQuery({ sql, params });
|
|
820
1086
|
} catch (error) {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1087
|
+
throw new MastraError(
|
|
1088
|
+
{
|
|
1089
|
+
id: "CLOUDFLARE_D1_STORAGE_PERSIST_WORKFLOW_SNAPSHOT_ERROR",
|
|
1090
|
+
domain: ErrorDomain.STORAGE,
|
|
1091
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1092
|
+
text: `Failed to persist workflow snapshot: ${error instanceof Error ? error.message : String(error)}`,
|
|
1093
|
+
details: { workflowName, runId }
|
|
1094
|
+
},
|
|
1095
|
+
error
|
|
1096
|
+
);
|
|
825
1097
|
}
|
|
826
1098
|
}
|
|
827
1099
|
async loadWorkflowSnapshot(params) {
|
|
828
1100
|
const { workflowName, runId } = params;
|
|
829
1101
|
this.logger.debug("Loading workflow snapshot", { workflowName, runId });
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1102
|
+
try {
|
|
1103
|
+
const d = await this.load({
|
|
1104
|
+
tableName: TABLE_WORKFLOW_SNAPSHOT,
|
|
1105
|
+
keys: {
|
|
1106
|
+
workflow_name: workflowName,
|
|
1107
|
+
run_id: runId
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
return d ? d.snapshot : null;
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
throw new MastraError(
|
|
1113
|
+
{
|
|
1114
|
+
id: "CLOUDFLARE_D1_STORAGE_LOAD_WORKFLOW_SNAPSHOT_ERROR",
|
|
1115
|
+
domain: ErrorDomain.STORAGE,
|
|
1116
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1117
|
+
text: `Failed to load workflow snapshot: ${error instanceof Error ? error.message : String(error)}`,
|
|
1118
|
+
details: { workflowName, runId }
|
|
1119
|
+
},
|
|
1120
|
+
error
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
838
1123
|
}
|
|
839
1124
|
/**
|
|
840
1125
|
* Insert multiple records in a batch operation
|
|
@@ -869,12 +1154,76 @@ var D1Store = class extends MastraStorage {
|
|
|
869
1154
|
}
|
|
870
1155
|
this.logger.debug(`Successfully batch inserted ${records.length} records into ${tableName}`);
|
|
871
1156
|
} catch (error) {
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1157
|
+
throw new MastraError(
|
|
1158
|
+
{
|
|
1159
|
+
id: "CLOUDFLARE_D1_STORAGE_BATCH_INSERT_ERROR",
|
|
1160
|
+
domain: ErrorDomain.STORAGE,
|
|
1161
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1162
|
+
text: `Failed to batch insert into ${tableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1163
|
+
details: { tableName }
|
|
1164
|
+
},
|
|
1165
|
+
error
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Upsert multiple records in a batch operation
|
|
1171
|
+
* @param tableName The table to insert into
|
|
1172
|
+
* @param records The records to insert
|
|
1173
|
+
*/
|
|
1174
|
+
async batchUpsert({
|
|
1175
|
+
tableName,
|
|
1176
|
+
records
|
|
1177
|
+
}) {
|
|
1178
|
+
if (records.length === 0) return;
|
|
1179
|
+
const fullTableName = this.getTableName(tableName);
|
|
1180
|
+
try {
|
|
1181
|
+
const batchSize = 50;
|
|
1182
|
+
for (let i = 0; i < records.length; i += batchSize) {
|
|
1183
|
+
const batch = records.slice(i, i + batchSize);
|
|
1184
|
+
const recordsToInsert = batch;
|
|
1185
|
+
if (recordsToInsert.length > 0) {
|
|
1186
|
+
const firstRecord = recordsToInsert[0];
|
|
1187
|
+
const columns = Object.keys(firstRecord || {});
|
|
1188
|
+
for (const record of recordsToInsert) {
|
|
1189
|
+
const values = columns.map((col) => {
|
|
1190
|
+
if (!record) return null;
|
|
1191
|
+
const value = typeof col === "string" ? record[col] : null;
|
|
1192
|
+
return this.serializeValue(value);
|
|
1193
|
+
});
|
|
1194
|
+
const recordToUpsert = columns.reduce(
|
|
1195
|
+
(acc, col) => {
|
|
1196
|
+
if (col !== "createdAt") acc[col] = `excluded.${col}`;
|
|
1197
|
+
return acc;
|
|
1198
|
+
},
|
|
1199
|
+
{}
|
|
1200
|
+
);
|
|
1201
|
+
const query = createSqlBuilder().insert(fullTableName, columns, values, ["id"], recordToUpsert);
|
|
1202
|
+
const { sql, params } = query.build();
|
|
1203
|
+
await this.executeQuery({ sql, params });
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
this.logger.debug(
|
|
1207
|
+
`Processed batch ${Math.floor(i / batchSize) + 1} of ${Math.ceil(records.length / batchSize)}`
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
this.logger.debug(`Successfully batch upserted ${records.length} records into ${tableName}`);
|
|
1211
|
+
} catch (error) {
|
|
1212
|
+
throw new MastraError(
|
|
1213
|
+
{
|
|
1214
|
+
id: "CLOUDFLARE_D1_STORAGE_BATCH_UPSERT_ERROR",
|
|
1215
|
+
domain: ErrorDomain.STORAGE,
|
|
1216
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1217
|
+
text: `Failed to batch upsert into ${tableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1218
|
+
details: { tableName }
|
|
1219
|
+
},
|
|
1220
|
+
error
|
|
1221
|
+
);
|
|
876
1222
|
}
|
|
877
1223
|
}
|
|
1224
|
+
/**
|
|
1225
|
+
* @deprecated use getTracesPaginated instead
|
|
1226
|
+
*/
|
|
878
1227
|
async getTraces({
|
|
879
1228
|
name,
|
|
880
1229
|
scope,
|
|
@@ -904,22 +1253,108 @@ var D1Store = class extends MastraStorage {
|
|
|
904
1253
|
if (toDate) {
|
|
905
1254
|
query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
906
1255
|
}
|
|
907
|
-
query.orderBy("startTime", "DESC").limit(perPage).offset(
|
|
1256
|
+
query.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
|
|
908
1257
|
const { sql, params } = query.build();
|
|
909
1258
|
const results = await this.executeQuery({ sql, params });
|
|
910
|
-
return isArrayOfRecords(results) ? results.map(
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1259
|
+
return isArrayOfRecords(results) ? results.map(
|
|
1260
|
+
(trace) => ({
|
|
1261
|
+
...trace,
|
|
1262
|
+
attributes: this.deserializeValue(trace.attributes, "jsonb"),
|
|
1263
|
+
status: this.deserializeValue(trace.status, "jsonb"),
|
|
1264
|
+
events: this.deserializeValue(trace.events, "jsonb"),
|
|
1265
|
+
links: this.deserializeValue(trace.links, "jsonb"),
|
|
1266
|
+
other: this.deserializeValue(trace.other, "jsonb")
|
|
1267
|
+
})
|
|
1268
|
+
) : [];
|
|
918
1269
|
} catch (error) {
|
|
919
|
-
|
|
1270
|
+
const mastraError = new MastraError(
|
|
1271
|
+
{
|
|
1272
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_TRACES_ERROR",
|
|
1273
|
+
domain: ErrorDomain.STORAGE,
|
|
1274
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1275
|
+
text: `Failed to retrieve traces: ${error instanceof Error ? error.message : String(error)}`,
|
|
1276
|
+
details: {
|
|
1277
|
+
name: name ?? "",
|
|
1278
|
+
scope: scope ?? ""
|
|
1279
|
+
}
|
|
1280
|
+
},
|
|
1281
|
+
error
|
|
1282
|
+
);
|
|
1283
|
+
this.logger?.error(mastraError.toString());
|
|
1284
|
+
this.logger?.trackException(mastraError);
|
|
920
1285
|
return [];
|
|
921
1286
|
}
|
|
922
1287
|
}
|
|
1288
|
+
async getTracesPaginated(args) {
|
|
1289
|
+
const { name, scope, page, perPage, attributes, fromDate, toDate } = args;
|
|
1290
|
+
const fullTableName = this.getTableName(TABLE_TRACES);
|
|
1291
|
+
try {
|
|
1292
|
+
const dataQuery = createSqlBuilder().select("*").from(fullTableName).where("1=1");
|
|
1293
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("1=1");
|
|
1294
|
+
if (name) {
|
|
1295
|
+
dataQuery.andWhere("name LIKE ?", `%${name}%`);
|
|
1296
|
+
countQuery.andWhere("name LIKE ?", `%${name}%`);
|
|
1297
|
+
}
|
|
1298
|
+
if (scope) {
|
|
1299
|
+
dataQuery.andWhere("scope = ?", scope);
|
|
1300
|
+
countQuery.andWhere("scope = ?", scope);
|
|
1301
|
+
}
|
|
1302
|
+
if (attributes && Object.keys(attributes).length > 0) {
|
|
1303
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1304
|
+
dataQuery.jsonLike("attributes", key, value);
|
|
1305
|
+
countQuery.jsonLike("attributes", key, value);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
if (fromDate) {
|
|
1309
|
+
const fromDateStr = fromDate instanceof Date ? fromDate.toISOString() : fromDate;
|
|
1310
|
+
dataQuery.andWhere("createdAt >= ?", fromDateStr);
|
|
1311
|
+
countQuery.andWhere("createdAt >= ?", fromDateStr);
|
|
1312
|
+
}
|
|
1313
|
+
if (toDate) {
|
|
1314
|
+
const toDateStr = toDate instanceof Date ? toDate.toISOString() : toDate;
|
|
1315
|
+
dataQuery.andWhere("createdAt <= ?", toDateStr);
|
|
1316
|
+
countQuery.andWhere("createdAt <= ?", toDateStr);
|
|
1317
|
+
}
|
|
1318
|
+
const countResult = await this.executeQuery(countQuery.build());
|
|
1319
|
+
const total = Number(countResult?.[0]?.count ?? 0);
|
|
1320
|
+
dataQuery.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
|
|
1321
|
+
const results = await this.executeQuery(dataQuery.build());
|
|
1322
|
+
const traces = isArrayOfRecords(results) ? results.map(
|
|
1323
|
+
(trace) => ({
|
|
1324
|
+
...trace,
|
|
1325
|
+
attributes: this.deserializeValue(trace.attributes, "jsonb"),
|
|
1326
|
+
status: this.deserializeValue(trace.status, "jsonb"),
|
|
1327
|
+
events: this.deserializeValue(trace.events, "jsonb"),
|
|
1328
|
+
links: this.deserializeValue(trace.links, "jsonb"),
|
|
1329
|
+
other: this.deserializeValue(trace.other, "jsonb")
|
|
1330
|
+
})
|
|
1331
|
+
) : [];
|
|
1332
|
+
return {
|
|
1333
|
+
traces,
|
|
1334
|
+
total,
|
|
1335
|
+
page,
|
|
1336
|
+
perPage,
|
|
1337
|
+
hasMore: page * perPage + traces.length < total
|
|
1338
|
+
};
|
|
1339
|
+
} catch (error) {
|
|
1340
|
+
const mastraError = new MastraError(
|
|
1341
|
+
{
|
|
1342
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_TRACES_ERROR",
|
|
1343
|
+
domain: ErrorDomain.STORAGE,
|
|
1344
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1345
|
+
text: `Failed to retrieve traces: ${error instanceof Error ? error.message : String(error)}`,
|
|
1346
|
+
details: { name: name ?? "", scope: scope ?? "" }
|
|
1347
|
+
},
|
|
1348
|
+
error
|
|
1349
|
+
);
|
|
1350
|
+
this.logger?.error(mastraError.toString());
|
|
1351
|
+
this.logger?.trackException(mastraError);
|
|
1352
|
+
return { traces: [], total: 0, page, perPage, hasMore: false };
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* @deprecated use getEvals instead
|
|
1357
|
+
*/
|
|
923
1358
|
async getEvalsByAgentName(agentName, type) {
|
|
924
1359
|
const fullTableName = this.getTableName(TABLE_EVALS);
|
|
925
1360
|
try {
|
|
@@ -949,12 +1384,108 @@ var D1Store = class extends MastraStorage {
|
|
|
949
1384
|
};
|
|
950
1385
|
}) : [];
|
|
951
1386
|
} catch (error) {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1387
|
+
const mastraError = new MastraError(
|
|
1388
|
+
{
|
|
1389
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_EVALS_ERROR",
|
|
1390
|
+
domain: ErrorDomain.STORAGE,
|
|
1391
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1392
|
+
text: `Failed to retrieve evals for agent ${agentName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1393
|
+
details: { agentName }
|
|
1394
|
+
},
|
|
1395
|
+
error
|
|
1396
|
+
);
|
|
1397
|
+
this.logger?.error(mastraError.toString());
|
|
1398
|
+
this.logger?.trackException(mastraError);
|
|
955
1399
|
return [];
|
|
956
1400
|
}
|
|
957
1401
|
}
|
|
1402
|
+
async getEvals(options) {
|
|
1403
|
+
const { agentName, type, page = 0, perPage = 40, fromDate, toDate } = options || {};
|
|
1404
|
+
const fullTableName = this.getTableName(TABLE_EVALS);
|
|
1405
|
+
const conditions = [];
|
|
1406
|
+
const queryParams = [];
|
|
1407
|
+
if (agentName) {
|
|
1408
|
+
conditions.push(`agent_name = ?`);
|
|
1409
|
+
queryParams.push(agentName);
|
|
1410
|
+
}
|
|
1411
|
+
if (type === "test") {
|
|
1412
|
+
conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
|
|
1413
|
+
} else if (type === "live") {
|
|
1414
|
+
conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
|
|
1415
|
+
}
|
|
1416
|
+
if (fromDate) {
|
|
1417
|
+
conditions.push(`createdAt >= ?`);
|
|
1418
|
+
queryParams.push(this.serializeDate(fromDate));
|
|
1419
|
+
}
|
|
1420
|
+
if (toDate) {
|
|
1421
|
+
conditions.push(`createdAt <= ?`);
|
|
1422
|
+
queryParams.push(this.serializeDate(toDate));
|
|
1423
|
+
}
|
|
1424
|
+
const countQueryBuilder = createSqlBuilder().count().from(fullTableName);
|
|
1425
|
+
if (conditions.length > 0) {
|
|
1426
|
+
countQueryBuilder.where(conditions.join(" AND "), ...queryParams);
|
|
1427
|
+
}
|
|
1428
|
+
const { sql: countSql, params: countParams } = countQueryBuilder.build();
|
|
1429
|
+
try {
|
|
1430
|
+
const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
|
|
1431
|
+
const total = Number(countResult?.count || 0);
|
|
1432
|
+
const currentOffset = page * perPage;
|
|
1433
|
+
if (total === 0) {
|
|
1434
|
+
return {
|
|
1435
|
+
evals: [],
|
|
1436
|
+
total: 0,
|
|
1437
|
+
page,
|
|
1438
|
+
perPage,
|
|
1439
|
+
hasMore: false
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
const dataQueryBuilder = createSqlBuilder().select("*").from(fullTableName);
|
|
1443
|
+
if (conditions.length > 0) {
|
|
1444
|
+
dataQueryBuilder.where(conditions.join(" AND "), ...queryParams);
|
|
1445
|
+
}
|
|
1446
|
+
dataQueryBuilder.orderBy("createdAt", "DESC").limit(perPage).offset(currentOffset);
|
|
1447
|
+
const { sql: dataSql, params: dataParams } = dataQueryBuilder.build();
|
|
1448
|
+
const rows = await this.executeQuery({ sql: dataSql, params: dataParams });
|
|
1449
|
+
const evals = (isArrayOfRecords(rows) ? rows : []).map((row) => {
|
|
1450
|
+
const result = this.deserializeValue(row.result);
|
|
1451
|
+
const testInfo = row.test_info ? this.deserializeValue(row.test_info) : void 0;
|
|
1452
|
+
if (!result || typeof result !== "object" || !("score" in result)) {
|
|
1453
|
+
throw new Error(`Invalid MetricResult format: ${JSON.stringify(result)}`);
|
|
1454
|
+
}
|
|
1455
|
+
return {
|
|
1456
|
+
input: row.input,
|
|
1457
|
+
output: row.output,
|
|
1458
|
+
result,
|
|
1459
|
+
agentName: row.agent_name,
|
|
1460
|
+
metricName: row.metric_name,
|
|
1461
|
+
instructions: row.instructions,
|
|
1462
|
+
testInfo,
|
|
1463
|
+
globalRunId: row.global_run_id,
|
|
1464
|
+
runId: row.run_id,
|
|
1465
|
+
createdAt: row.createdAt
|
|
1466
|
+
};
|
|
1467
|
+
});
|
|
1468
|
+
const hasMore = currentOffset + evals.length < total;
|
|
1469
|
+
return {
|
|
1470
|
+
evals,
|
|
1471
|
+
total,
|
|
1472
|
+
page,
|
|
1473
|
+
perPage,
|
|
1474
|
+
hasMore
|
|
1475
|
+
};
|
|
1476
|
+
} catch (error) {
|
|
1477
|
+
throw new MastraError(
|
|
1478
|
+
{
|
|
1479
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_EVALS_ERROR",
|
|
1480
|
+
domain: ErrorDomain.STORAGE,
|
|
1481
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1482
|
+
text: `Failed to retrieve evals for agent ${agentName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1483
|
+
details: { agentName: agentName ?? "", type: type ?? "" }
|
|
1484
|
+
},
|
|
1485
|
+
error
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
958
1489
|
parseWorkflowRun(row) {
|
|
959
1490
|
let parsedSnapshot = row.snapshot;
|
|
960
1491
|
if (typeof parsedSnapshot === "string") {
|
|
@@ -1023,10 +1554,16 @@ var D1Store = class extends MastraStorage {
|
|
|
1023
1554
|
const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
|
|
1024
1555
|
return { runs, total: total || runs.length };
|
|
1025
1556
|
} catch (error) {
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1557
|
+
throw new MastraError(
|
|
1558
|
+
{
|
|
1559
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_WORKFLOW_RUNS_ERROR",
|
|
1560
|
+
domain: ErrorDomain.STORAGE,
|
|
1561
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1562
|
+
text: `Failed to retrieve workflow runs: ${error instanceof Error ? error.message : String(error)}`,
|
|
1563
|
+
details: { workflowName: workflowName ?? "", resourceId: resourceId ?? "" }
|
|
1564
|
+
},
|
|
1565
|
+
error
|
|
1566
|
+
);
|
|
1030
1567
|
}
|
|
1031
1568
|
}
|
|
1032
1569
|
async getWorkflowRunById({
|
|
@@ -1051,10 +1588,16 @@ var D1Store = class extends MastraStorage {
|
|
|
1051
1588
|
if (!result) return null;
|
|
1052
1589
|
return this.parseWorkflowRun(result);
|
|
1053
1590
|
} catch (error) {
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1591
|
+
throw new MastraError(
|
|
1592
|
+
{
|
|
1593
|
+
id: "CLOUDFLARE_D1_STORAGE_GET_WORKFLOW_RUN_BY_ID_ERROR",
|
|
1594
|
+
domain: ErrorDomain.STORAGE,
|
|
1595
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1596
|
+
text: `Failed to retrieve workflow run by ID: ${error instanceof Error ? error.message : String(error)}`,
|
|
1597
|
+
details: { runId, workflowName: workflowName ?? "" }
|
|
1598
|
+
},
|
|
1599
|
+
error
|
|
1600
|
+
);
|
|
1058
1601
|
}
|
|
1059
1602
|
}
|
|
1060
1603
|
/**
|
|
@@ -1064,6 +1607,10 @@ var D1Store = class extends MastraStorage {
|
|
|
1064
1607
|
async close() {
|
|
1065
1608
|
this.logger.debug("Closing D1 connection");
|
|
1066
1609
|
}
|
|
1610
|
+
async updateMessages(_args) {
|
|
1611
|
+
this.logger.error("updateMessages is not yet implemented in CloudflareD1Store");
|
|
1612
|
+
throw new Error("Method not implemented");
|
|
1613
|
+
}
|
|
1067
1614
|
};
|
|
1068
1615
|
|
|
1069
1616
|
export { D1Store };
|