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