@mastra/cloudflare-d1 0.0.0-share-agent-metadata-with-cloud-20250718110128 → 0.0.0-sidebar-window-undefined-fix-20251029233656

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