@mastra/cloudflare-d1 0.0.0-share-agent-metadata-with-cloud-20250718123411 → 0.0.0-span-scorring-test-20251124132129

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