@mastra/cloudflare-d1 1.0.0-beta.1 → 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 +478 -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 -1116
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1077 -1117
- 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 +14 -14
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +55 -177
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +9 -9
- 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,1127 +259,1201 @@ 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
|
-
const processedMsg = {};
|
|
685
|
-
for (const [key, value] of Object.entries(message)) {
|
|
686
|
-
if (key === `type` && value === `v2`) continue;
|
|
687
|
-
processedMsg[key] = deserializeValue(value);
|
|
688
|
-
}
|
|
689
|
-
return processedMsg;
|
|
690
|
-
});
|
|
691
|
-
return processedMessages;
|
|
630
|
+
return processed;
|
|
692
631
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
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);
|
|
697
640
|
try {
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
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
|
+
}
|
|
708
665
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
666
|
+
this.logger.debug(
|
|
667
|
+
`Processed batch ${Math.floor(i / batchSize) + 1} of ${Math.ceil(records.length / batchSize)}`
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
this.logger.debug(`Successfully batch upserted ${records.length} records into ${tableName}`);
|
|
714
671
|
} catch (error$1) {
|
|
715
|
-
|
|
672
|
+
throw new error.MastraError(
|
|
716
673
|
{
|
|
717
|
-
id: "
|
|
674
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "BATCH_UPSERT", "FAILED"),
|
|
718
675
|
domain: error.ErrorDomain.STORAGE,
|
|
719
676
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
720
|
-
text: `Failed to
|
|
721
|
-
details: {
|
|
677
|
+
text: `Failed to batch upsert into ${tableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
678
|
+
details: { tableName }
|
|
722
679
|
},
|
|
723
680
|
error$1
|
|
724
681
|
);
|
|
725
|
-
this.logger?.error(mastraError.toString());
|
|
726
|
-
this.logger?.trackException(mastraError);
|
|
727
|
-
throw mastraError;
|
|
728
682
|
}
|
|
729
683
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
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"]
|
|
701
|
+
});
|
|
702
|
+
}
|
|
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;
|
|
714
|
+
try {
|
|
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
|
+
};
|
|
721
|
+
} catch (error$1) {
|
|
722
|
+
const mastraError = new error.MastraError(
|
|
734
723
|
{
|
|
735
|
-
id: "
|
|
724
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "GET_RESOURCE_BY_ID", "FAILED"),
|
|
736
725
|
domain: error.ErrorDomain.STORAGE,
|
|
737
726
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
new Error("threadId must be a non-empty string")
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
if (page < 0) {
|
|
744
|
-
throw new error.MastraError(
|
|
745
|
-
{
|
|
746
|
-
id: "STORAGE_CLOUDFLARE_D1_LIST_MESSAGES_INVALID_PAGE",
|
|
747
|
-
domain: error.ErrorDomain.STORAGE,
|
|
748
|
-
category: error.ErrorCategory.USER,
|
|
749
|
-
details: { page }
|
|
727
|
+
text: `Error processing resource ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
728
|
+
details: { resourceId }
|
|
750
729
|
},
|
|
751
|
-
|
|
730
|
+
error$1
|
|
752
731
|
);
|
|
732
|
+
this.logger?.error(mastraError.toString());
|
|
733
|
+
this.logger?.trackException(mastraError);
|
|
734
|
+
return null;
|
|
753
735
|
}
|
|
754
|
-
|
|
755
|
-
|
|
736
|
+
}
|
|
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();
|
|
756
757
|
try {
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
SELECT id, content, role, type, createdAt, thread_id AS threadId, resourceId
|
|
760
|
-
FROM ${fullTableName}
|
|
761
|
-
WHERE thread_id = ?
|
|
762
|
-
`;
|
|
763
|
-
const queryParams = [threadId];
|
|
764
|
-
if (resourceId) {
|
|
765
|
-
query += ` AND resourceId = ?`;
|
|
766
|
-
queryParams.push(resourceId);
|
|
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;
|
|
853
|
-
return {
|
|
854
|
-
messages: finalMessages,
|
|
855
|
-
total,
|
|
856
|
-
page,
|
|
857
|
-
perPage: perPageForResponse,
|
|
858
|
-
hasMore
|
|
859
|
-
};
|
|
758
|
+
await this.#db.executeQuery({ sql, params });
|
|
759
|
+
return resource;
|
|
860
760
|
} catch (error$1) {
|
|
861
|
-
|
|
761
|
+
throw new error.MastraError(
|
|
862
762
|
{
|
|
863
|
-
id: "
|
|
763
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "SAVE_RESOURCE", "FAILED"),
|
|
864
764
|
domain: error.ErrorDomain.STORAGE,
|
|
865
765
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
866
|
-
text: `Failed to
|
|
867
|
-
details: {
|
|
868
|
-
threadId,
|
|
869
|
-
resourceId: resourceId ?? ""
|
|
870
|
-
}
|
|
766
|
+
text: `Failed to save resource to ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
767
|
+
details: { resourceId: resource.id }
|
|
871
768
|
},
|
|
872
769
|
error$1
|
|
873
770
|
);
|
|
874
|
-
this.logger?.error?.(mastraError.toString());
|
|
875
|
-
this.logger?.trackException?.(mastraError);
|
|
876
|
-
return {
|
|
877
|
-
messages: [],
|
|
878
|
-
total: 0,
|
|
879
|
-
page,
|
|
880
|
-
perPage: perPageForResponse,
|
|
881
|
-
hasMore: false
|
|
882
|
-
};
|
|
883
771
|
}
|
|
884
772
|
}
|
|
885
|
-
async
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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 });
|
|
890
788
|
}
|
|
891
|
-
const
|
|
892
|
-
const
|
|
893
|
-
|
|
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();
|
|
894
804
|
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
|
-
});
|
|
805
|
+
await this.#db.executeQuery({ sql, params });
|
|
806
|
+
return updatedResource;
|
|
973
807
|
} catch (error$1) {
|
|
974
808
|
throw new error.MastraError(
|
|
975
809
|
{
|
|
976
|
-
id: "
|
|
810
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "UPDATE_RESOURCE", "FAILED"),
|
|
977
811
|
domain: error.ErrorDomain.STORAGE,
|
|
978
812
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
979
|
-
|
|
813
|
+
text: `Failed to update resource ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
814
|
+
details: { resourceId }
|
|
980
815
|
},
|
|
981
816
|
error$1
|
|
982
817
|
);
|
|
983
818
|
}
|
|
984
819
|
}
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
super();
|
|
992
|
-
this.client = config.client;
|
|
993
|
-
this.binding = config.binding;
|
|
994
|
-
this.tablePrefix = config.tablePrefix || "";
|
|
995
|
-
}
|
|
996
|
-
async hasColumn(table, column) {
|
|
997
|
-
const fullTableName = table.startsWith(this.tablePrefix) ? table : `${this.tablePrefix}${table}`;
|
|
998
|
-
const sql = `PRAGMA table_info(${fullTableName});`;
|
|
999
|
-
const result = await this.executeQuery({ sql, params: [] });
|
|
1000
|
-
if (!result || !Array.isArray(result)) return false;
|
|
1001
|
-
return result.some((col) => col.name === column || col.name === column.toLowerCase());
|
|
1002
|
-
}
|
|
1003
|
-
getTableName(tableName) {
|
|
1004
|
-
return `${this.tablePrefix}${tableName}`;
|
|
1005
|
-
}
|
|
1006
|
-
formatSqlParams(params) {
|
|
1007
|
-
return params.map((p) => p === void 0 || p === null ? null : p);
|
|
1008
|
-
}
|
|
1009
|
-
async executeWorkersBindingQuery({
|
|
1010
|
-
sql,
|
|
1011
|
-
params = [],
|
|
1012
|
-
first = false
|
|
1013
|
-
}) {
|
|
1014
|
-
if (!this.binding) {
|
|
1015
|
-
throw new Error("Workers binding is not configured");
|
|
1016
|
-
}
|
|
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;
|
|
1017
826
|
try {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (!result) return null;
|
|
1025
|
-
return result;
|
|
1026
|
-
} else {
|
|
1027
|
-
result = await statement.bind(...formattedParams).all();
|
|
1028
|
-
const results = result.results || [];
|
|
1029
|
-
return results;
|
|
1030
|
-
}
|
|
1031
|
-
} else {
|
|
1032
|
-
if (first) {
|
|
1033
|
-
result = await statement.first();
|
|
1034
|
-
if (!result) return null;
|
|
1035
|
-
return result;
|
|
1036
|
-
} else {
|
|
1037
|
-
result = await statement.all();
|
|
1038
|
-
const results = result.results || [];
|
|
1039
|
-
return results;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
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
|
+
};
|
|
1042
833
|
} catch (error$1) {
|
|
1043
|
-
|
|
834
|
+
const mastraError = new error.MastraError(
|
|
1044
835
|
{
|
|
1045
|
-
id: "
|
|
836
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "GET_THREAD_BY_ID", "FAILED"),
|
|
1046
837
|
domain: error.ErrorDomain.STORAGE,
|
|
1047
838
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1048
|
-
|
|
839
|
+
text: `Error processing thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
840
|
+
details: { threadId }
|
|
1049
841
|
},
|
|
1050
842
|
error$1
|
|
1051
843
|
);
|
|
844
|
+
this.logger?.error(mastraError.toString());
|
|
845
|
+
this.logger?.trackException(mastraError);
|
|
846
|
+
return null;
|
|
1052
847
|
}
|
|
1053
848
|
}
|
|
1054
|
-
async
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
849
|
+
async listThreadsByResourceId(args) {
|
|
850
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
851
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
852
|
+
if (page < 0) {
|
|
853
|
+
throw new error.MastraError(
|
|
854
|
+
{
|
|
855
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
856
|
+
domain: error.ErrorDomain.STORAGE,
|
|
857
|
+
category: error.ErrorCategory.USER,
|
|
858
|
+
details: { page }
|
|
859
|
+
},
|
|
860
|
+
new Error("page must be >= 0")
|
|
861
|
+
);
|
|
1061
862
|
}
|
|
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
|
+
});
|
|
1062
872
|
try {
|
|
1063
|
-
const
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
const
|
|
1069
|
-
const
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
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);
|
|
880
|
+
return {
|
|
881
|
+
threads,
|
|
882
|
+
total,
|
|
883
|
+
page,
|
|
884
|
+
perPage: perPageForResponse,
|
|
885
|
+
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
886
|
+
};
|
|
1074
887
|
} catch (error$1) {
|
|
1075
|
-
|
|
888
|
+
const mastraError = new error.MastraError(
|
|
1076
889
|
{
|
|
1077
|
-
id: "
|
|
890
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
|
|
1078
891
|
domain: error.ErrorDomain.STORAGE,
|
|
1079
892
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1080
|
-
|
|
893
|
+
text: `Error getting threads by resourceId ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
894
|
+
details: { resourceId }
|
|
1081
895
|
},
|
|
1082
896
|
error$1
|
|
1083
897
|
);
|
|
898
|
+
this.logger?.error(mastraError.toString());
|
|
899
|
+
this.logger?.trackException(mastraError);
|
|
900
|
+
return {
|
|
901
|
+
threads: [],
|
|
902
|
+
total: 0,
|
|
903
|
+
page,
|
|
904
|
+
perPage: perPageForResponse,
|
|
905
|
+
hasMore: false
|
|
906
|
+
};
|
|
1084
907
|
}
|
|
1085
908
|
}
|
|
1086
|
-
async
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
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();
|
|
1096
931
|
try {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1111
|
-
serializeValue(value) {
|
|
1112
|
-
if (value === null || value === void 0) {
|
|
1113
|
-
return null;
|
|
1114
|
-
}
|
|
1115
|
-
if (value instanceof Date) {
|
|
1116
|
-
return value.toISOString();
|
|
1117
|
-
}
|
|
1118
|
-
if (typeof value === "object") {
|
|
1119
|
-
return JSON.stringify(value);
|
|
1120
|
-
}
|
|
1121
|
-
return value;
|
|
1122
|
-
}
|
|
1123
|
-
getSqlType(type) {
|
|
1124
|
-
switch (type) {
|
|
1125
|
-
case "bigint":
|
|
1126
|
-
return "INTEGER";
|
|
1127
|
-
// SQLite uses INTEGER for all integer sizes
|
|
1128
|
-
case "jsonb":
|
|
1129
|
-
return "TEXT";
|
|
1130
|
-
// Store JSON as TEXT in SQLite
|
|
1131
|
-
default:
|
|
1132
|
-
return super.getSqlType(type);
|
|
932
|
+
await this.#db.executeQuery({ sql, params });
|
|
933
|
+
return thread;
|
|
934
|
+
} catch (error$1) {
|
|
935
|
+
throw new error.MastraError(
|
|
936
|
+
{
|
|
937
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "SAVE_THREAD", "FAILED"),
|
|
938
|
+
domain: error.ErrorDomain.STORAGE,
|
|
939
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
940
|
+
text: `Failed to save thread to ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
941
|
+
details: { threadId: thread.id }
|
|
942
|
+
},
|
|
943
|
+
error$1
|
|
944
|
+
);
|
|
1133
945
|
}
|
|
1134
946
|
}
|
|
1135
|
-
async
|
|
1136
|
-
|
|
1137
|
-
|
|
947
|
+
async updateThread({
|
|
948
|
+
id,
|
|
949
|
+
title,
|
|
950
|
+
metadata
|
|
1138
951
|
}) {
|
|
952
|
+
const thread = await this.getThreadById({ threadId: id });
|
|
1139
953
|
try {
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
const type = this.getSqlType(colDef.type);
|
|
1143
|
-
const nullable = colDef.nullable === false ? "NOT NULL" : "";
|
|
1144
|
-
const primaryKey = colDef.primaryKey ? "PRIMARY KEY" : "";
|
|
1145
|
-
return `${colName} ${type} ${nullable} ${primaryKey}`.trim();
|
|
1146
|
-
});
|
|
1147
|
-
const tableConstraints = [];
|
|
1148
|
-
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
1149
|
-
tableConstraints.push("UNIQUE (workflow_name, run_id)");
|
|
954
|
+
if (!thread) {
|
|
955
|
+
throw new Error(`Thread ${id} not found`);
|
|
1150
956
|
}
|
|
1151
|
-
const
|
|
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);
|
|
1152
966
|
const { sql, params } = query.build();
|
|
1153
|
-
await this.executeQuery({ sql, params });
|
|
1154
|
-
|
|
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
|
+
};
|
|
1155
977
|
} catch (error$1) {
|
|
1156
978
|
throw new error.MastraError(
|
|
1157
979
|
{
|
|
1158
|
-
id: "
|
|
980
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "UPDATE_THREAD", "FAILED"),
|
|
1159
981
|
domain: error.ErrorDomain.STORAGE,
|
|
1160
982
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1161
|
-
|
|
983
|
+
text: `Failed to update thread ${id}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
984
|
+
details: { threadId: id }
|
|
1162
985
|
},
|
|
1163
986
|
error$1
|
|
1164
987
|
);
|
|
1165
988
|
}
|
|
1166
989
|
}
|
|
1167
|
-
async
|
|
990
|
+
async deleteThread({ threadId }) {
|
|
991
|
+
const fullTableName = this.#db.getTableName(storage.TABLE_THREADS);
|
|
1168
992
|
try {
|
|
1169
|
-
const
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
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 });
|
|
1174
1000
|
} catch (error$1) {
|
|
1175
1001
|
throw new error.MastraError(
|
|
1176
1002
|
{
|
|
1177
|
-
id: "
|
|
1003
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "DELETE_THREAD", "FAILED"),
|
|
1178
1004
|
domain: error.ErrorDomain.STORAGE,
|
|
1179
1005
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1180
|
-
|
|
1006
|
+
text: `Failed to delete thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1007
|
+
details: { threadId }
|
|
1181
1008
|
},
|
|
1182
1009
|
error$1
|
|
1183
1010
|
);
|
|
1184
1011
|
}
|
|
1185
1012
|
}
|
|
1186
|
-
async
|
|
1013
|
+
async saveMessages(args) {
|
|
1014
|
+
const { messages } = args;
|
|
1015
|
+
if (messages.length === 0) return { messages: [] };
|
|
1187
1016
|
try {
|
|
1188
|
-
const
|
|
1189
|
-
const
|
|
1190
|
-
|
|
1191
|
-
|
|
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
|
+
}
|
|
1037
|
+
}
|
|
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() };
|
|
1192
1064
|
} catch (error$1) {
|
|
1193
1065
|
throw new error.MastraError(
|
|
1194
1066
|
{
|
|
1195
|
-
id: "
|
|
1067
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "SAVE_MESSAGES", "FAILED"),
|
|
1196
1068
|
domain: error.ErrorDomain.STORAGE,
|
|
1197
1069
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1198
|
-
|
|
1070
|
+
text: `Failed to save messages: ${error$1 instanceof Error ? error$1.message : String(error$1)}`
|
|
1199
1071
|
},
|
|
1200
1072
|
error$1
|
|
1201
1073
|
);
|
|
1202
1074
|
}
|
|
1203
1075
|
}
|
|
1204
|
-
async
|
|
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++;
|
|
1119
|
+
}
|
|
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);
|
|
1130
|
+
}
|
|
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 = [];
|
|
1205
1139
|
try {
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
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");
|
|
1142
|
+
const { sql, params } = query.build();
|
|
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);
|
|
1216
1150
|
}
|
|
1217
|
-
|
|
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() };
|
|
1218
1156
|
} catch (error$1) {
|
|
1219
|
-
|
|
1157
|
+
const mastraError = new error.MastraError(
|
|
1220
1158
|
{
|
|
1221
|
-
id: "
|
|
1159
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
1222
1160
|
domain: error.ErrorDomain.STORAGE,
|
|
1223
1161
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1224
|
-
|
|
1162
|
+
text: `Failed to retrieve messages by ID: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
1163
|
+
details: { messageIds: JSON.stringify(messageIds) }
|
|
1225
1164
|
},
|
|
1226
1165
|
error$1
|
|
1227
1166
|
);
|
|
1167
|
+
this.logger?.error(mastraError.toString());
|
|
1168
|
+
this.logger?.trackException(mastraError);
|
|
1169
|
+
throw mastraError;
|
|
1228
1170
|
}
|
|
1229
1171
|
}
|
|
1230
|
-
async
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
const columns = Object.keys(processedRecord);
|
|
1235
|
-
const values = Object.values(processedRecord);
|
|
1236
|
-
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
1237
|
-
const { sql, params } = query.build();
|
|
1238
|
-
await this.executeQuery({ sql, params });
|
|
1239
|
-
} catch (error$1) {
|
|
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())) {
|
|
1240
1176
|
throw new error.MastraError(
|
|
1241
1177
|
{
|
|
1242
|
-
id: "
|
|
1178
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
1243
1179
|
domain: error.ErrorDomain.STORAGE,
|
|
1244
1180
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1245
|
-
details: {
|
|
1181
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
1246
1182
|
},
|
|
1247
|
-
|
|
1183
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
1248
1184
|
);
|
|
1249
1185
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1186
|
+
if (page < 0) {
|
|
1187
|
+
throw new error.MastraError(
|
|
1188
|
+
{
|
|
1189
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_MESSAGES", "INVALID_PAGE"),
|
|
1190
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1191
|
+
category: error.ErrorCategory.USER,
|
|
1192
|
+
details: { page }
|
|
1193
|
+
},
|
|
1194
|
+
new Error("page must be >= 0")
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1197
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
1198
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1252
1199
|
try {
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
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
|
+
}
|
|
1281
|
+
}
|
|
1262
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
|
+
};
|
|
1263
1307
|
} catch (error$1) {
|
|
1264
|
-
|
|
1308
|
+
const mastraError = new error.MastraError(
|
|
1265
1309
|
{
|
|
1266
|
-
id: "
|
|
1310
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_MESSAGES", "FAILED"),
|
|
1267
1311
|
domain: error.ErrorDomain.STORAGE,
|
|
1268
1312
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1269
|
-
|
|
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
|
+
}
|
|
1270
1318
|
},
|
|
1271
1319
|
error$1
|
|
1272
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
|
+
};
|
|
1273
1330
|
}
|
|
1274
1331
|
}
|
|
1275
|
-
async
|
|
1332
|
+
async updateMessages(args) {
|
|
1333
|
+
const { messages } = args;
|
|
1334
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
1335
|
+
if (!messages.length) {
|
|
1336
|
+
return [];
|
|
1337
|
+
}
|
|
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);
|
|
1276
1341
|
try {
|
|
1277
|
-
const
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
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 [];
|
|
1347
|
+
}
|
|
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 {
|
|
@@ -1807,7 +1912,7 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
|
1807
1912
|
resourceId,
|
|
1808
1913
|
status
|
|
1809
1914
|
} = {}) {
|
|
1810
|
-
const fullTableName = this.
|
|
1915
|
+
const fullTableName = this.#db.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1811
1916
|
try {
|
|
1812
1917
|
const builder = createSqlBuilder().select().from(fullTableName);
|
|
1813
1918
|
const countBuilder = createSqlBuilder().count().from(fullTableName);
|
|
@@ -1817,12 +1922,12 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
|
1817
1922
|
countBuilder.whereAnd("json_extract(snapshot, '$.status') = ?", status);
|
|
1818
1923
|
}
|
|
1819
1924
|
if (resourceId) {
|
|
1820
|
-
const hasResourceId = await this.
|
|
1925
|
+
const hasResourceId = await this.#db.hasColumn(fullTableName, "resourceId");
|
|
1821
1926
|
if (hasResourceId) {
|
|
1822
1927
|
builder.whereAnd("resourceId = ?", resourceId);
|
|
1823
1928
|
countBuilder.whereAnd("resourceId = ?", resourceId);
|
|
1824
1929
|
} else {
|
|
1825
|
-
|
|
1930
|
+
this.logger.warn(`[${fullTableName}] resourceId column not found. Skipping resourceId filter.`);
|
|
1826
1931
|
}
|
|
1827
1932
|
}
|
|
1828
1933
|
if (fromDate) {
|
|
@@ -1843,20 +1948,20 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
|
1843
1948
|
let total = 0;
|
|
1844
1949
|
if (perPage !== void 0 && page !== void 0) {
|
|
1845
1950
|
const { sql: countSql, params: countParams } = countBuilder.build();
|
|
1846
|
-
const countResult = await this.
|
|
1951
|
+
const countResult = await this.#db.executeQuery({
|
|
1847
1952
|
sql: countSql,
|
|
1848
1953
|
params: countParams,
|
|
1849
1954
|
first: true
|
|
1850
1955
|
});
|
|
1851
1956
|
total = Number(countResult?.count ?? 0);
|
|
1852
1957
|
}
|
|
1853
|
-
const results = await this.
|
|
1958
|
+
const results = await this.#db.executeQuery({ sql, params });
|
|
1854
1959
|
const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
|
|
1855
1960
|
return { runs, total: total || runs.length };
|
|
1856
1961
|
} catch (error$1) {
|
|
1857
1962
|
throw new error.MastraError(
|
|
1858
1963
|
{
|
|
1859
|
-
id: "
|
|
1964
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
1860
1965
|
domain: error.ErrorDomain.STORAGE,
|
|
1861
1966
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1862
1967
|
text: `Failed to retrieve workflow runs: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
@@ -1873,7 +1978,7 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
|
1873
1978
|
runId,
|
|
1874
1979
|
workflowName
|
|
1875
1980
|
}) {
|
|
1876
|
-
const fullTableName = this.
|
|
1981
|
+
const fullTableName = this.#db.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1877
1982
|
try {
|
|
1878
1983
|
const conditions = [];
|
|
1879
1984
|
const params = [];
|
|
@@ -1887,13 +1992,13 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
|
1887
1992
|
}
|
|
1888
1993
|
const whereClause = conditions.length > 0 ? "WHERE " + conditions.join(" AND ") : "";
|
|
1889
1994
|
const sql = `SELECT * FROM ${fullTableName} ${whereClause} ORDER BY createdAt DESC LIMIT 1`;
|
|
1890
|
-
const result = await this.
|
|
1995
|
+
const result = await this.#db.executeQuery({ sql, params, first: true });
|
|
1891
1996
|
if (!result) return null;
|
|
1892
1997
|
return this.parseWorkflowRun(result);
|
|
1893
1998
|
} catch (error$1) {
|
|
1894
1999
|
throw new error.MastraError(
|
|
1895
2000
|
{
|
|
1896
|
-
id: "
|
|
2001
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1897
2002
|
domain: error.ErrorDomain.STORAGE,
|
|
1898
2003
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1899
2004
|
text: `Failed to retrieve workflow run by ID: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
|
|
@@ -1903,13 +2008,31 @@ var WorkflowsStorageD1 = class extends storage.WorkflowsStorage {
|
|
|
1903
2008
|
);
|
|
1904
2009
|
}
|
|
1905
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
|
+
}
|
|
1906
2030
|
};
|
|
1907
2031
|
|
|
1908
2032
|
// src/storage/index.ts
|
|
1909
2033
|
var D1Store = class extends storage.MastraStorage {
|
|
1910
2034
|
client;
|
|
1911
2035
|
binding;
|
|
1912
|
-
// D1Database binding
|
|
1913
2036
|
tablePrefix;
|
|
1914
2037
|
stores;
|
|
1915
2038
|
/**
|
|
@@ -1918,7 +2041,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
1918
2041
|
*/
|
|
1919
2042
|
constructor(config) {
|
|
1920
2043
|
try {
|
|
1921
|
-
super({ id: config.id, name: "D1" });
|
|
2044
|
+
super({ id: config.id, name: "D1", disableInit: config.disableInit });
|
|
1922
2045
|
if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
|
|
1923
2046
|
throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
|
|
1924
2047
|
}
|
|
@@ -1956,7 +2079,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
1956
2079
|
} catch (error$1) {
|
|
1957
2080
|
throw new error.MastraError(
|
|
1958
2081
|
{
|
|
1959
|
-
id: "
|
|
2082
|
+
id: storage.createStorageErrorId("CLOUDFLARE_D1", "INITIALIZATION", "FAILED"),
|
|
1960
2083
|
domain: error.ErrorDomain.STORAGE,
|
|
1961
2084
|
category: error.ErrorCategory.SYSTEM,
|
|
1962
2085
|
text: "Error initializing D1Store"
|
|
@@ -1964,189 +2087,26 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
1964
2087
|
error$1
|
|
1965
2088
|
);
|
|
1966
2089
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
}
|
|
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
|
+
}
|
|
1981
2104
|
this.stores = {
|
|
1982
|
-
operations,
|
|
1983
2105
|
scores,
|
|
1984
2106
|
workflows,
|
|
1985
2107
|
memory
|
|
1986
2108
|
};
|
|
1987
2109
|
}
|
|
1988
|
-
get supports() {
|
|
1989
|
-
return {
|
|
1990
|
-
selectByIncludeResourceScope: true,
|
|
1991
|
-
resourceWorkingMemory: true,
|
|
1992
|
-
hasColumn: true,
|
|
1993
|
-
createTable: true,
|
|
1994
|
-
deleteMessages: false,
|
|
1995
|
-
listScoresBySpan: true
|
|
1996
|
-
};
|
|
1997
|
-
}
|
|
1998
|
-
async createTable({
|
|
1999
|
-
tableName,
|
|
2000
|
-
schema
|
|
2001
|
-
}) {
|
|
2002
|
-
return this.stores.operations.createTable({ tableName, schema });
|
|
2003
|
-
}
|
|
2004
|
-
/**
|
|
2005
|
-
* Alters table schema to add columns if they don't exist
|
|
2006
|
-
* @param tableName Name of the table
|
|
2007
|
-
* @param schema Schema of the table
|
|
2008
|
-
* @param ifNotExists Array of column names to add if they don't exist
|
|
2009
|
-
*/
|
|
2010
|
-
async alterTable({
|
|
2011
|
-
tableName,
|
|
2012
|
-
schema,
|
|
2013
|
-
ifNotExists
|
|
2014
|
-
}) {
|
|
2015
|
-
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
2016
|
-
}
|
|
2017
|
-
async clearTable({ tableName }) {
|
|
2018
|
-
return this.stores.operations.clearTable({ tableName });
|
|
2019
|
-
}
|
|
2020
|
-
async dropTable({ tableName }) {
|
|
2021
|
-
return this.stores.operations.dropTable({ tableName });
|
|
2022
|
-
}
|
|
2023
|
-
async hasColumn(table, column) {
|
|
2024
|
-
return this.stores.operations.hasColumn(table, column);
|
|
2025
|
-
}
|
|
2026
|
-
async insert({ tableName, record }) {
|
|
2027
|
-
return this.stores.operations.insert({ tableName, record });
|
|
2028
|
-
}
|
|
2029
|
-
async load({ tableName, keys }) {
|
|
2030
|
-
return this.stores.operations.load({ tableName, keys });
|
|
2031
|
-
}
|
|
2032
|
-
async getThreadById({ threadId }) {
|
|
2033
|
-
return this.stores.memory.getThreadById({ threadId });
|
|
2034
|
-
}
|
|
2035
|
-
async saveThread({ thread }) {
|
|
2036
|
-
return this.stores.memory.saveThread({ thread });
|
|
2037
|
-
}
|
|
2038
|
-
async updateThread({
|
|
2039
|
-
id,
|
|
2040
|
-
title,
|
|
2041
|
-
metadata
|
|
2042
|
-
}) {
|
|
2043
|
-
return this.stores.memory.updateThread({ id, title, metadata });
|
|
2044
|
-
}
|
|
2045
|
-
async deleteThread({ threadId }) {
|
|
2046
|
-
return this.stores.memory.deleteThread({ threadId });
|
|
2047
|
-
}
|
|
2048
|
-
async saveMessages(args) {
|
|
2049
|
-
return this.stores.memory.saveMessages(args);
|
|
2050
|
-
}
|
|
2051
|
-
async updateWorkflowResults({
|
|
2052
|
-
workflowName,
|
|
2053
|
-
runId,
|
|
2054
|
-
stepId,
|
|
2055
|
-
result,
|
|
2056
|
-
requestContext
|
|
2057
|
-
}) {
|
|
2058
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
2059
|
-
}
|
|
2060
|
-
async updateWorkflowState({
|
|
2061
|
-
workflowName,
|
|
2062
|
-
runId,
|
|
2063
|
-
opts
|
|
2064
|
-
}) {
|
|
2065
|
-
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
2066
|
-
}
|
|
2067
|
-
async persistWorkflowSnapshot({
|
|
2068
|
-
workflowName,
|
|
2069
|
-
runId,
|
|
2070
|
-
resourceId,
|
|
2071
|
-
snapshot
|
|
2072
|
-
}) {
|
|
2073
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
2074
|
-
}
|
|
2075
|
-
async loadWorkflowSnapshot(params) {
|
|
2076
|
-
return this.stores.workflows.loadWorkflowSnapshot(params);
|
|
2077
|
-
}
|
|
2078
|
-
async listWorkflowRuns(args = {}) {
|
|
2079
|
-
return this.stores.workflows.listWorkflowRuns(args);
|
|
2080
|
-
}
|
|
2081
|
-
async getWorkflowRunById({
|
|
2082
|
-
runId,
|
|
2083
|
-
workflowName
|
|
2084
|
-
}) {
|
|
2085
|
-
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
2086
|
-
}
|
|
2087
|
-
/**
|
|
2088
|
-
* Insert multiple records in a batch operation
|
|
2089
|
-
* @param tableName The table to insert into
|
|
2090
|
-
* @param records The records to insert
|
|
2091
|
-
*/
|
|
2092
|
-
async batchInsert({ tableName, records }) {
|
|
2093
|
-
return this.stores.operations.batchInsert({ tableName, records });
|
|
2094
|
-
}
|
|
2095
|
-
async updateMessages(_args) {
|
|
2096
|
-
return this.stores.memory.updateMessages(_args);
|
|
2097
|
-
}
|
|
2098
|
-
async getResourceById({ resourceId }) {
|
|
2099
|
-
return this.stores.memory.getResourceById({ resourceId });
|
|
2100
|
-
}
|
|
2101
|
-
async saveResource({ resource }) {
|
|
2102
|
-
return this.stores.memory.saveResource({ resource });
|
|
2103
|
-
}
|
|
2104
|
-
async updateResource({
|
|
2105
|
-
resourceId,
|
|
2106
|
-
workingMemory,
|
|
2107
|
-
metadata
|
|
2108
|
-
}) {
|
|
2109
|
-
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
2110
|
-
}
|
|
2111
|
-
async getScoreById({ id: _id }) {
|
|
2112
|
-
return this.stores.scores.getScoreById({ id: _id });
|
|
2113
|
-
}
|
|
2114
|
-
async saveScore(_score) {
|
|
2115
|
-
return this.stores.scores.saveScore(_score);
|
|
2116
|
-
}
|
|
2117
|
-
async listScoresByRunId({
|
|
2118
|
-
runId: _runId,
|
|
2119
|
-
pagination: _pagination
|
|
2120
|
-
}) {
|
|
2121
|
-
return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
|
|
2122
|
-
}
|
|
2123
|
-
async listScoresByEntityId({
|
|
2124
|
-
entityId: _entityId,
|
|
2125
|
-
entityType: _entityType,
|
|
2126
|
-
pagination: _pagination
|
|
2127
|
-
}) {
|
|
2128
|
-
return this.stores.scores.listScoresByEntityId({
|
|
2129
|
-
entityId: _entityId,
|
|
2130
|
-
entityType: _entityType,
|
|
2131
|
-
pagination: _pagination
|
|
2132
|
-
});
|
|
2133
|
-
}
|
|
2134
|
-
async listScoresByScorerId({
|
|
2135
|
-
scorerId,
|
|
2136
|
-
pagination,
|
|
2137
|
-
entityId,
|
|
2138
|
-
entityType,
|
|
2139
|
-
source
|
|
2140
|
-
}) {
|
|
2141
|
-
return this.stores.scores.listScoresByScorerId({ scorerId, pagination, entityId, entityType, source });
|
|
2142
|
-
}
|
|
2143
|
-
async listScoresBySpan({
|
|
2144
|
-
traceId,
|
|
2145
|
-
spanId,
|
|
2146
|
-
pagination
|
|
2147
|
-
}) {
|
|
2148
|
-
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
|
|
2149
|
-
}
|
|
2150
2110
|
/**
|
|
2151
2111
|
* Close the database connection
|
|
2152
2112
|
* No explicit cleanup needed for D1 in either REST or Workers Binding mode
|
|
@@ -2157,5 +2117,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
2157
2117
|
};
|
|
2158
2118
|
|
|
2159
2119
|
exports.D1Store = D1Store;
|
|
2120
|
+
exports.MemoryStorageD1 = MemoryStorageD1;
|
|
2121
|
+
exports.ScoresStorageD1 = ScoresStorageD1;
|
|
2122
|
+
exports.WorkflowsStorageD1 = WorkflowsStorageD1;
|
|
2160
2123
|
//# sourceMappingURL=index.cjs.map
|
|
2161
2124
|
//# sourceMappingURL=index.cjs.map
|