@mastra/libsql 1.22.5 → 1.23.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-message-history.md +6 -2
- package/dist/docs/references/reference-memory-memory-class.md +2 -1
- package/dist/index.cjs +348 -231
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +348 -231
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/background-tasks/index.d.ts.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +14 -2
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1849,6 +1849,9 @@ MIGRATION REQUIRED: Duplicate spans detected in ${TABLE_SPANS}\n================
|
|
|
1849
1849
|
this.logger.debug(`LibSQLDB: Created unique index on (spanId, traceId) for ${TABLE_SPANS}`);
|
|
1850
1850
|
}
|
|
1851
1851
|
}
|
|
1852
|
+
await this.client.execute(`CREATE INDEX IF NOT EXISTS "mastra_ai_spans_roots_started_at_idx" ON "${TABLE_SPANS}" ("startedAt" DESC) WHERE "parentSpanId" IS NULL`);
|
|
1853
|
+
await this.client.execute(`CREATE INDEX IF NOT EXISTS "mastra_ai_spans_trace_started_at_idx" ON "${TABLE_SPANS}" ("traceId", "startedAt")`);
|
|
1854
|
+
this.logger.debug(`LibSQLDB: Ensured trace read indexes for ${TABLE_SPANS}`);
|
|
1852
1855
|
this.logger.info(`LibSQLDB: Migration completed for ${TABLE_SPANS}`);
|
|
1853
1856
|
} catch (error) {
|
|
1854
1857
|
if (error instanceof MastraError) throw error;
|
|
@@ -3020,8 +3023,15 @@ function resolveTargets({ policies, descriptor, order }) {
|
|
|
3020
3023
|
//#endregion
|
|
3021
3024
|
//#region src/storage/domains/background-tasks/index.ts
|
|
3022
3025
|
function serializeJson(v) {
|
|
3023
|
-
if (
|
|
3024
|
-
|
|
3026
|
+
if (v === void 0) return null;
|
|
3027
|
+
let serialized;
|
|
3028
|
+
try {
|
|
3029
|
+
serialized = JSON.stringify(v);
|
|
3030
|
+
} catch (error) {
|
|
3031
|
+
throw new Error("Failed to serialize background task value as JSON", { cause: error });
|
|
3032
|
+
}
|
|
3033
|
+
if (serialized === void 0) throw new Error("Failed to serialize background task value as JSON");
|
|
3034
|
+
return serialized;
|
|
3025
3035
|
}
|
|
3026
3036
|
function parseJson$4(val) {
|
|
3027
3037
|
if (val == null) return void 0;
|
|
@@ -4140,94 +4150,122 @@ var DatasetsLibSQL = class extends DatasetsStorage {
|
|
|
4140
4150
|
}
|
|
4141
4151
|
async _doUpdateItem(args) {
|
|
4142
4152
|
try {
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4153
|
+
return await withClientWriteLock(this.#client, async () => {
|
|
4154
|
+
const tx = await this.#client.transaction("write");
|
|
4155
|
+
try {
|
|
4156
|
+
const itemResult = await tx.execute({
|
|
4157
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4158
|
+
args: [args.id]
|
|
4159
|
+
});
|
|
4160
|
+
const existing = itemResult.rows[0] ? this.transformItemRow(itemResult.rows[0]) : null;
|
|
4161
|
+
if (!existing) throw new MastraError({
|
|
4162
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_ITEM", "NOT_FOUND"),
|
|
4163
|
+
domain: ErrorDomain.STORAGE,
|
|
4164
|
+
category: ErrorCategory.USER,
|
|
4165
|
+
details: { itemId: args.id }
|
|
4166
|
+
});
|
|
4167
|
+
if (existing.datasetId !== args.datasetId) throw new MastraError({
|
|
4168
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_ITEM", "DATASET_MISMATCH"),
|
|
4169
|
+
domain: ErrorDomain.STORAGE,
|
|
4170
|
+
category: ErrorCategory.USER,
|
|
4171
|
+
details: {
|
|
4172
|
+
itemId: args.id,
|
|
4173
|
+
expectedDatasetId: args.datasetId,
|
|
4174
|
+
actualDatasetId: existing.datasetId
|
|
4175
|
+
}
|
|
4176
|
+
});
|
|
4177
|
+
if (existing.metadata?.__purged === true) throw new MastraError({
|
|
4178
|
+
id: "DATASET_ITEM_PURGED",
|
|
4179
|
+
domain: ErrorDomain.STORAGE,
|
|
4180
|
+
category: ErrorCategory.USER,
|
|
4181
|
+
details: {
|
|
4182
|
+
datasetId: args.datasetId,
|
|
4183
|
+
itemId: args.id
|
|
4184
|
+
},
|
|
4185
|
+
text: `Purged dataset item cannot be updated: ${args.id}`
|
|
4186
|
+
});
|
|
4187
|
+
const dataset = (await tx.execute({
|
|
4188
|
+
sql: `SELECT organizationId, projectId FROM ${TABLE_DATASETS} WHERE id = ?`,
|
|
4189
|
+
args: [args.datasetId]
|
|
4190
|
+
})).rows[0];
|
|
4191
|
+
const organizationId = typeof dataset?.organizationId === "string" ? dataset.organizationId : null;
|
|
4192
|
+
const projectId = typeof dataset?.projectId === "string" ? dataset.projectId : null;
|
|
4193
|
+
const versionId = crypto.randomUUID();
|
|
4194
|
+
const now = /* @__PURE__ */ new Date();
|
|
4195
|
+
const nowIso = now.toISOString();
|
|
4196
|
+
const mergedInput = args.input !== void 0 ? args.input : existing.input;
|
|
4197
|
+
const mergedGroundTruth = args.groundTruth !== void 0 ? args.groundTruth : existing.groundTruth;
|
|
4198
|
+
const mergedExpectedTrajectory = args.expectedTrajectory !== void 0 ? args.expectedTrajectory : existing.expectedTrajectory;
|
|
4199
|
+
const mergedToolMocks = args.toolMocks !== void 0 ? args.toolMocks : existing.toolMocks;
|
|
4200
|
+
const mergedUnmockedToolPolicy = args.unmockedToolPolicy !== void 0 ? args.unmockedToolPolicy : existing.unmockedToolPolicy;
|
|
4201
|
+
const mergedScorerIds = args.scorerIds !== void 0 ? args.scorerIds ?? void 0 : existing.scorerIds;
|
|
4202
|
+
const mergedRequestContext = args.requestContext !== void 0 ? args.requestContext : existing.requestContext;
|
|
4203
|
+
const mergedMetadata = args.metadata !== void 0 ? args.metadata : existing.metadata;
|
|
4204
|
+
const mergedSource = args.source !== void 0 ? args.source : existing.source;
|
|
4205
|
+
const versionResult = await tx.execute({
|
|
4206
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
4207
|
+
args: [args.datasetId]
|
|
4208
|
+
});
|
|
4209
|
+
const newVersion = Number(versionResult.rows[0].version);
|
|
4210
|
+
await tx.execute({
|
|
4211
|
+
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = ? WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4212
|
+
args: [newVersion, args.id]
|
|
4213
|
+
});
|
|
4214
|
+
await tx.execute({
|
|
4215
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id,datasetId,datasetVersion,externalId,organizationId,projectId,validTo,isDeleted,input,groundTruth,expectedTrajectory,toolMocks,unmockedToolPolicy,scorerIds,requestContext,metadata,source,createdAt,updatedAt) VALUES (?,?,?,?,?,?,NULL,0,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,?)`,
|
|
4216
|
+
args: [
|
|
4217
|
+
args.id,
|
|
4218
|
+
args.datasetId,
|
|
4219
|
+
newVersion,
|
|
4220
|
+
existing.externalId ?? null,
|
|
4221
|
+
organizationId,
|
|
4222
|
+
projectId,
|
|
4223
|
+
jsonbArg(mergedInput),
|
|
4224
|
+
jsonbArg(mergedGroundTruth),
|
|
4225
|
+
jsonbArg(mergedExpectedTrajectory),
|
|
4226
|
+
jsonbArg(mergedToolMocks),
|
|
4227
|
+
mergedUnmockedToolPolicy ?? null,
|
|
4228
|
+
jsonbArg(mergedScorerIds),
|
|
4229
|
+
jsonbArg(mergedRequestContext),
|
|
4230
|
+
jsonbArg(mergedMetadata),
|
|
4231
|
+
jsonbArg(mergedSource),
|
|
4232
|
+
existing.createdAt.toISOString(),
|
|
4233
|
+
nowIso
|
|
4234
|
+
]
|
|
4235
|
+
});
|
|
4236
|
+
await tx.execute({
|
|
4237
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, ?, ?)`,
|
|
4238
|
+
args: [
|
|
4239
|
+
versionId,
|
|
4240
|
+
args.datasetId,
|
|
4241
|
+
newVersion,
|
|
4242
|
+
nowIso
|
|
4243
|
+
]
|
|
4244
|
+
});
|
|
4245
|
+
await tx.commit();
|
|
4246
|
+
return {
|
|
4247
|
+
...existing,
|
|
4248
|
+
datasetVersion: newVersion,
|
|
4249
|
+
organizationId,
|
|
4250
|
+
projectId,
|
|
4251
|
+
input: mergedInput,
|
|
4252
|
+
groundTruth: mergedGroundTruth,
|
|
4253
|
+
expectedTrajectory: mergedExpectedTrajectory,
|
|
4254
|
+
toolMocks: mergedToolMocks,
|
|
4255
|
+
unmockedToolPolicy: mergedUnmockedToolPolicy,
|
|
4256
|
+
scorerIds: mergedScorerIds,
|
|
4257
|
+
requestContext: mergedRequestContext,
|
|
4258
|
+
metadata: mergedMetadata,
|
|
4259
|
+
source: mergedSource,
|
|
4260
|
+
updatedAt: now
|
|
4261
|
+
};
|
|
4262
|
+
} catch (error) {
|
|
4263
|
+
if (!tx.closed) await tx.rollback().catch((rollbackError) => {
|
|
4264
|
+
throw new AggregateError([error, rollbackError], "Transaction and rollback both failed");
|
|
4265
|
+
});
|
|
4266
|
+
throw error;
|
|
4158
4267
|
}
|
|
4159
4268
|
});
|
|
4160
|
-
const dataset = await this.getDatasetById({ id: args.datasetId });
|
|
4161
|
-
const versionId = crypto.randomUUID();
|
|
4162
|
-
const now = /* @__PURE__ */ new Date();
|
|
4163
|
-
const nowIso = now.toISOString();
|
|
4164
|
-
const mergedInput = args.input !== void 0 ? args.input : existing.input;
|
|
4165
|
-
const mergedGroundTruth = args.groundTruth !== void 0 ? args.groundTruth : existing.groundTruth;
|
|
4166
|
-
const mergedExpectedTrajectory = args.expectedTrajectory !== void 0 ? args.expectedTrajectory : existing.expectedTrajectory;
|
|
4167
|
-
const mergedToolMocks = args.toolMocks !== void 0 ? args.toolMocks : existing.toolMocks;
|
|
4168
|
-
const mergedUnmockedToolPolicy = args.unmockedToolPolicy !== void 0 ? args.unmockedToolPolicy : existing.unmockedToolPolicy;
|
|
4169
|
-
const mergedScorerIds = args.scorerIds !== void 0 ? args.scorerIds ?? void 0 : existing.scorerIds;
|
|
4170
|
-
const mergedRequestContext = args.requestContext !== void 0 ? args.requestContext : existing.requestContext;
|
|
4171
|
-
const mergedMetadata = args.metadata !== void 0 ? args.metadata : existing.metadata;
|
|
4172
|
-
const mergedSource = args.source !== void 0 ? args.source : existing.source;
|
|
4173
|
-
const results = await this.#client.batch([
|
|
4174
|
-
{
|
|
4175
|
-
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
4176
|
-
args: [args.datasetId]
|
|
4177
|
-
},
|
|
4178
|
-
{
|
|
4179
|
-
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?) WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4180
|
-
args: [args.datasetId, args.id]
|
|
4181
|
-
},
|
|
4182
|
-
{
|
|
4183
|
-
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id,datasetId,datasetVersion,externalId,organizationId,projectId,validTo,isDeleted,input,groundTruth,expectedTrajectory,toolMocks,unmockedToolPolicy,scorerIds,requestContext,metadata,source,createdAt,updatedAt) VALUES (?,?,(SELECT version FROM ${TABLE_DATASETS} WHERE id = ?),?,(SELECT organizationId FROM ${TABLE_DATASETS} WHERE id = ?),(SELECT projectId FROM ${TABLE_DATASETS} WHERE id = ?),NULL,0,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,?)`,
|
|
4184
|
-
args: [
|
|
4185
|
-
args.id,
|
|
4186
|
-
args.datasetId,
|
|
4187
|
-
args.datasetId,
|
|
4188
|
-
existing.externalId ?? null,
|
|
4189
|
-
args.datasetId,
|
|
4190
|
-
args.datasetId,
|
|
4191
|
-
jsonbArg(mergedInput),
|
|
4192
|
-
jsonbArg(mergedGroundTruth),
|
|
4193
|
-
jsonbArg(mergedExpectedTrajectory),
|
|
4194
|
-
jsonbArg(mergedToolMocks),
|
|
4195
|
-
mergedUnmockedToolPolicy ?? null,
|
|
4196
|
-
jsonbArg(mergedScorerIds),
|
|
4197
|
-
jsonbArg(mergedRequestContext),
|
|
4198
|
-
jsonbArg(mergedMetadata),
|
|
4199
|
-
jsonbArg(mergedSource),
|
|
4200
|
-
existing.createdAt.toISOString(),
|
|
4201
|
-
nowIso
|
|
4202
|
-
]
|
|
4203
|
-
},
|
|
4204
|
-
{
|
|
4205
|
-
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
4206
|
-
args: [
|
|
4207
|
-
versionId,
|
|
4208
|
-
args.datasetId,
|
|
4209
|
-
args.datasetId,
|
|
4210
|
-
nowIso
|
|
4211
|
-
]
|
|
4212
|
-
}
|
|
4213
|
-
], "write");
|
|
4214
|
-
const newVersion = Number(results[0].rows[0].version);
|
|
4215
|
-
return {
|
|
4216
|
-
...existing,
|
|
4217
|
-
datasetVersion: newVersion,
|
|
4218
|
-
organizationId: dataset?.organizationId ?? null,
|
|
4219
|
-
projectId: dataset?.projectId ?? null,
|
|
4220
|
-
input: mergedInput,
|
|
4221
|
-
groundTruth: mergedGroundTruth,
|
|
4222
|
-
expectedTrajectory: mergedExpectedTrajectory,
|
|
4223
|
-
toolMocks: mergedToolMocks,
|
|
4224
|
-
unmockedToolPolicy: mergedUnmockedToolPolicy,
|
|
4225
|
-
scorerIds: mergedScorerIds,
|
|
4226
|
-
requestContext: mergedRequestContext,
|
|
4227
|
-
metadata: mergedMetadata,
|
|
4228
|
-
source: mergedSource,
|
|
4229
|
-
updatedAt: now
|
|
4230
|
-
};
|
|
4231
4269
|
} catch (error) {
|
|
4232
4270
|
if (error instanceof MastraError) throw error;
|
|
4233
4271
|
throw new MastraError({
|
|
@@ -4239,61 +4277,78 @@ var DatasetsLibSQL = class extends DatasetsStorage {
|
|
|
4239
4277
|
}
|
|
4240
4278
|
async _doDeleteItem({ id, datasetId }) {
|
|
4241
4279
|
try {
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4280
|
+
await withClientWriteLock(this.#client, async () => {
|
|
4281
|
+
const tx = await this.#client.transaction("write");
|
|
4282
|
+
try {
|
|
4283
|
+
const itemResult = await tx.execute({
|
|
4284
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4285
|
+
args: [id]
|
|
4286
|
+
});
|
|
4287
|
+
const existing = itemResult.rows[0] ? this.transformItemRow(itemResult.rows[0]) : null;
|
|
4288
|
+
if (!existing) {
|
|
4289
|
+
await tx.commit();
|
|
4290
|
+
return;
|
|
4291
|
+
}
|
|
4292
|
+
if (existing.datasetId !== datasetId) throw new MastraError({
|
|
4293
|
+
id: createStorageErrorId("LIBSQL", "DELETE_ITEM", "DATASET_MISMATCH"),
|
|
4294
|
+
domain: ErrorDomain.STORAGE,
|
|
4295
|
+
category: ErrorCategory.USER,
|
|
4296
|
+
details: {
|
|
4297
|
+
itemId: id,
|
|
4298
|
+
expectedDatasetId: datasetId,
|
|
4299
|
+
actualDatasetId: existing.datasetId
|
|
4300
|
+
}
|
|
4301
|
+
});
|
|
4302
|
+
const versionId = crypto.randomUUID();
|
|
4303
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4304
|
+
const dataset = (await tx.execute({
|
|
4305
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version, organizationId, projectId`,
|
|
4306
|
+
args: [datasetId]
|
|
4307
|
+
})).rows[0];
|
|
4308
|
+
const newVersion = Number(dataset.version);
|
|
4309
|
+
await tx.execute({
|
|
4310
|
+
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = ? WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4311
|
+
args: [newVersion, id]
|
|
4312
|
+
});
|
|
4313
|
+
await tx.execute({
|
|
4314
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id,datasetId,datasetVersion,externalId,organizationId,projectId,validTo,isDeleted,input,groundTruth,expectedTrajectory,toolMocks,unmockedToolPolicy,scorerIds,requestContext,metadata,source,createdAt,updatedAt) VALUES (?,?,?,?,?,?,NULL,1,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,?)`,
|
|
4315
|
+
args: [
|
|
4316
|
+
id,
|
|
4317
|
+
datasetId,
|
|
4318
|
+
newVersion,
|
|
4319
|
+
existing.externalId ?? null,
|
|
4320
|
+
dataset.organizationId ?? null,
|
|
4321
|
+
dataset.projectId ?? null,
|
|
4322
|
+
jsonbArg(existing.input),
|
|
4323
|
+
jsonbArg(existing.groundTruth),
|
|
4324
|
+
jsonbArg(existing.expectedTrajectory),
|
|
4325
|
+
jsonbArg(existing.toolMocks),
|
|
4326
|
+
existing.unmockedToolPolicy ?? null,
|
|
4327
|
+
jsonbArg(existing.scorerIds),
|
|
4328
|
+
jsonbArg(existing.requestContext),
|
|
4329
|
+
jsonbArg(existing.metadata),
|
|
4330
|
+
jsonbArg(existing.source),
|
|
4331
|
+
existing.createdAt.toISOString(),
|
|
4332
|
+
nowIso
|
|
4333
|
+
]
|
|
4334
|
+
});
|
|
4335
|
+
await tx.execute({
|
|
4336
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, ?, ?)`,
|
|
4337
|
+
args: [
|
|
4338
|
+
versionId,
|
|
4339
|
+
datasetId,
|
|
4340
|
+
newVersion,
|
|
4341
|
+
nowIso
|
|
4342
|
+
]
|
|
4343
|
+
});
|
|
4344
|
+
await tx.commit();
|
|
4345
|
+
} catch (error) {
|
|
4346
|
+
if (!tx.closed) await tx.rollback().catch((rollbackError) => {
|
|
4347
|
+
throw new AggregateError([error, rollbackError], "Transaction and rollback both failed");
|
|
4348
|
+
});
|
|
4349
|
+
throw error;
|
|
4252
4350
|
}
|
|
4253
4351
|
});
|
|
4254
|
-
const versionId = crypto.randomUUID();
|
|
4255
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4256
|
-
await this.#client.batch([
|
|
4257
|
-
{
|
|
4258
|
-
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
4259
|
-
args: [datasetId]
|
|
4260
|
-
},
|
|
4261
|
-
{
|
|
4262
|
-
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?) WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4263
|
-
args: [datasetId, id]
|
|
4264
|
-
},
|
|
4265
|
-
{
|
|
4266
|
-
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id,datasetId,datasetVersion,externalId,organizationId,projectId,validTo,isDeleted,input,groundTruth,expectedTrajectory,toolMocks,unmockedToolPolicy,scorerIds,requestContext,metadata,source,createdAt,updatedAt) VALUES (?,?,(SELECT version FROM ${TABLE_DATASETS} WHERE id = ?),?,(SELECT organizationId FROM ${TABLE_DATASETS} WHERE id = ?),(SELECT projectId FROM ${TABLE_DATASETS} WHERE id = ?),NULL,1,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,?)`,
|
|
4267
|
-
args: [
|
|
4268
|
-
id,
|
|
4269
|
-
datasetId,
|
|
4270
|
-
datasetId,
|
|
4271
|
-
existing.externalId ?? null,
|
|
4272
|
-
datasetId,
|
|
4273
|
-
datasetId,
|
|
4274
|
-
jsonbArg(existing.input),
|
|
4275
|
-
jsonbArg(existing.groundTruth),
|
|
4276
|
-
jsonbArg(existing.expectedTrajectory),
|
|
4277
|
-
jsonbArg(existing.toolMocks),
|
|
4278
|
-
existing.unmockedToolPolicy ?? null,
|
|
4279
|
-
jsonbArg(existing.scorerIds),
|
|
4280
|
-
jsonbArg(existing.requestContext),
|
|
4281
|
-
jsonbArg(existing.metadata),
|
|
4282
|
-
jsonbArg(existing.source),
|
|
4283
|
-
existing.createdAt.toISOString(),
|
|
4284
|
-
nowIso
|
|
4285
|
-
]
|
|
4286
|
-
},
|
|
4287
|
-
{
|
|
4288
|
-
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
4289
|
-
args: [
|
|
4290
|
-
versionId,
|
|
4291
|
-
datasetId,
|
|
4292
|
-
datasetId,
|
|
4293
|
-
nowIso
|
|
4294
|
-
]
|
|
4295
|
-
}
|
|
4296
|
-
], "write");
|
|
4297
4352
|
} catch (error) {
|
|
4298
4353
|
if (error instanceof MastraError) throw error;
|
|
4299
4354
|
throw new MastraError({
|
|
@@ -4711,63 +4766,84 @@ var DatasetsLibSQL = class extends DatasetsStorage {
|
|
|
4711
4766
|
}
|
|
4712
4767
|
async _doBatchDeleteItems(input) {
|
|
4713
4768
|
try {
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
+
await withClientWriteLock(this.#client, async () => {
|
|
4770
|
+
const tx = await this.#client.transaction("write");
|
|
4771
|
+
try {
|
|
4772
|
+
const dataset = (await tx.execute({
|
|
4773
|
+
sql: `SELECT organizationId, projectId FROM ${TABLE_DATASETS} WHERE id = ?`,
|
|
4774
|
+
args: [input.datasetId]
|
|
4775
|
+
})).rows[0];
|
|
4776
|
+
if (!dataset) throw new MastraError({
|
|
4777
|
+
id: createStorageErrorId("LIBSQL", "BULK_DELETE_ITEMS", "DATASET_NOT_FOUND"),
|
|
4778
|
+
domain: ErrorDomain.STORAGE,
|
|
4779
|
+
category: ErrorCategory.USER,
|
|
4780
|
+
details: { datasetId: input.datasetId }
|
|
4781
|
+
});
|
|
4782
|
+
const currentItems = [];
|
|
4783
|
+
for (const itemId of input.itemIds) {
|
|
4784
|
+
const itemResult = await tx.execute({
|
|
4785
|
+
sql: `SELECT ${buildSelectColumns(TABLE_DATASET_ITEMS)} FROM ${TABLE_DATASET_ITEMS} WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4786
|
+
args: [itemId]
|
|
4787
|
+
});
|
|
4788
|
+
const item = itemResult.rows[0] ? this.transformItemRow(itemResult.rows[0]) : null;
|
|
4789
|
+
if (item && item.datasetId === input.datasetId) currentItems.push(item);
|
|
4790
|
+
}
|
|
4791
|
+
if (currentItems.length === 0) {
|
|
4792
|
+
await tx.commit();
|
|
4793
|
+
return;
|
|
4794
|
+
}
|
|
4795
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4796
|
+
const versionId = crypto.randomUUID();
|
|
4797
|
+
const statements = [{
|
|
4798
|
+
sql: `UPDATE ${TABLE_DATASETS} SET version = version + 1 WHERE id = ? RETURNING version`,
|
|
4799
|
+
args: [input.datasetId]
|
|
4800
|
+
}];
|
|
4801
|
+
for (const item of currentItems) {
|
|
4802
|
+
statements.push({
|
|
4803
|
+
sql: `UPDATE ${TABLE_DATASET_ITEMS} SET validTo = (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?) WHERE id = ? AND validTo IS NULL AND isDeleted = 0`,
|
|
4804
|
+
args: [input.datasetId, item.id]
|
|
4805
|
+
});
|
|
4806
|
+
statements.push({
|
|
4807
|
+
sql: `INSERT INTO ${TABLE_DATASET_ITEMS} (id,datasetId,datasetVersion,externalId,organizationId,projectId,validTo,isDeleted,input,groundTruth,expectedTrajectory,toolMocks,unmockedToolPolicy,scorerIds,requestContext,metadata,source,createdAt,updatedAt) VALUES (?,?,(SELECT version FROM ${TABLE_DATASETS} WHERE id = ?),?,?,?,NULL,1,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,jsonb(?),jsonb(?),jsonb(?),jsonb(?),?,?)`,
|
|
4808
|
+
args: [
|
|
4809
|
+
item.id,
|
|
4810
|
+
input.datasetId,
|
|
4811
|
+
input.datasetId,
|
|
4812
|
+
item.externalId ?? null,
|
|
4813
|
+
dataset.organizationId ?? null,
|
|
4814
|
+
dataset.projectId ?? null,
|
|
4815
|
+
jsonbArg(item.input),
|
|
4816
|
+
jsonbArg(item.groundTruth),
|
|
4817
|
+
jsonbArg(item.expectedTrajectory),
|
|
4818
|
+
jsonbArg(item.toolMocks),
|
|
4819
|
+
item.unmockedToolPolicy ?? null,
|
|
4820
|
+
jsonbArg(item.scorerIds),
|
|
4821
|
+
jsonbArg(item.requestContext),
|
|
4822
|
+
jsonbArg(item.metadata),
|
|
4823
|
+
jsonbArg(item.source),
|
|
4824
|
+
item.createdAt.toISOString(),
|
|
4825
|
+
nowIso
|
|
4826
|
+
]
|
|
4827
|
+
});
|
|
4828
|
+
}
|
|
4829
|
+
statements.push({
|
|
4830
|
+
sql: `INSERT INTO ${TABLE_DATASET_VERSIONS} (id, datasetId, version, createdAt) VALUES (?, ?, (SELECT version FROM ${TABLE_DATASETS} WHERE id = ?), ?)`,
|
|
4831
|
+
args: [
|
|
4832
|
+
versionId,
|
|
4833
|
+
input.datasetId,
|
|
4834
|
+
input.datasetId,
|
|
4835
|
+
nowIso
|
|
4836
|
+
]
|
|
4837
|
+
});
|
|
4838
|
+
for (const statement of statements) await tx.execute(statement);
|
|
4839
|
+
await tx.commit();
|
|
4840
|
+
} catch (error) {
|
|
4841
|
+
if (!tx.closed) await tx.rollback().catch((rollbackError) => {
|
|
4842
|
+
throw new AggregateError([error, rollbackError], "Transaction and rollback both failed");
|
|
4843
|
+
});
|
|
4844
|
+
throw error;
|
|
4845
|
+
}
|
|
4769
4846
|
});
|
|
4770
|
-
await this.#client.batch(statements, "write");
|
|
4771
4847
|
} catch (error) {
|
|
4772
4848
|
if (error instanceof MastraError) throw error;
|
|
4773
4849
|
throw new MastraError({
|
|
@@ -8540,6 +8616,71 @@ var MemoryLibSQL = class MemoryLibSQL extends MemoryStorage {
|
|
|
8540
8616
|
}, error);
|
|
8541
8617
|
}
|
|
8542
8618
|
}
|
|
8619
|
+
/**
|
|
8620
|
+
* Atomically reassign a thread and all of its messages to a different resource.
|
|
8621
|
+
*
|
|
8622
|
+
* Runs inside a single write transaction. SQLite serializes write transactions, so overlapping
|
|
8623
|
+
* transfers of the same thread cannot interleave the thread update with the message update:
|
|
8624
|
+
* either both the thread and every message move to the new resource, or neither does. The
|
|
8625
|
+
* thread's `createdAt` is preserved. Callers are responsible for authorizing the reassignment.
|
|
8626
|
+
*/
|
|
8627
|
+
async updateThreadResourceId({ threadId, resourceId }) {
|
|
8628
|
+
try {
|
|
8629
|
+
const tx = await this.#client.transaction("write");
|
|
8630
|
+
try {
|
|
8631
|
+
const row = (await tx.execute({
|
|
8632
|
+
sql: `SELECT * FROM "${TABLE_THREADS}" WHERE id = ?`,
|
|
8633
|
+
args: [threadId]
|
|
8634
|
+
})).rows?.[0];
|
|
8635
|
+
if (!row) throw new Error(`Thread "${threadId}" not found`);
|
|
8636
|
+
const currentResourceId = row.resourceId;
|
|
8637
|
+
const normalized = {
|
|
8638
|
+
id: row.id,
|
|
8639
|
+
resourceId: currentResourceId,
|
|
8640
|
+
title: row.title,
|
|
8641
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata,
|
|
8642
|
+
createdAt: new Date(row.createdAt),
|
|
8643
|
+
updatedAt: new Date(row.updatedAt)
|
|
8644
|
+
};
|
|
8645
|
+
if (currentResourceId === resourceId) {
|
|
8646
|
+
await tx.commit();
|
|
8647
|
+
return normalized;
|
|
8648
|
+
}
|
|
8649
|
+
const now = /* @__PURE__ */ new Date();
|
|
8650
|
+
await tx.execute({
|
|
8651
|
+
sql: `UPDATE "${TABLE_THREADS}" SET "resourceId" = ?, "updatedAt" = ? WHERE id = ?`,
|
|
8652
|
+
args: [
|
|
8653
|
+
resourceId,
|
|
8654
|
+
now.toISOString(),
|
|
8655
|
+
threadId
|
|
8656
|
+
]
|
|
8657
|
+
});
|
|
8658
|
+
await tx.execute({
|
|
8659
|
+
sql: `UPDATE "${TABLE_MESSAGES}" SET "resourceId" = ? WHERE thread_id = ?`,
|
|
8660
|
+
args: [resourceId, threadId]
|
|
8661
|
+
});
|
|
8662
|
+
await tx.commit();
|
|
8663
|
+
return {
|
|
8664
|
+
...normalized,
|
|
8665
|
+
resourceId,
|
|
8666
|
+
updatedAt: now
|
|
8667
|
+
};
|
|
8668
|
+
} catch (error) {
|
|
8669
|
+
await tx.rollback();
|
|
8670
|
+
throw error;
|
|
8671
|
+
}
|
|
8672
|
+
} catch (error) {
|
|
8673
|
+
throw new MastraError({
|
|
8674
|
+
id: createStorageErrorId("LIBSQL", "UPDATE_THREAD_RESOURCE_ID", "FAILED"),
|
|
8675
|
+
domain: ErrorDomain.STORAGE,
|
|
8676
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
8677
|
+
details: {
|
|
8678
|
+
threadId,
|
|
8679
|
+
resourceId
|
|
8680
|
+
}
|
|
8681
|
+
}, error);
|
|
8682
|
+
}
|
|
8683
|
+
}
|
|
8543
8684
|
async listThreads(args) {
|
|
8544
8685
|
const { page = 0, perPage: perPageInput, orderBy, filter } = args;
|
|
8545
8686
|
try {
|
|
@@ -8728,7 +8869,7 @@ var MemoryLibSQL = class MemoryLibSQL extends MemoryStorage {
|
|
|
8728
8869
|
}, error);
|
|
8729
8870
|
}
|
|
8730
8871
|
}
|
|
8731
|
-
async
|
|
8872
|
+
async copyThread(args) {
|
|
8732
8873
|
const { sourceThreadId, newThreadId: providedThreadId, resourceId, title, metadata, options } = args;
|
|
8733
8874
|
const sourceThread = await this.getThreadById({ threadId: sourceThreadId });
|
|
8734
8875
|
if (!sourceThread) throw new MastraError({
|
|
@@ -8747,7 +8888,7 @@ var MemoryLibSQL = class MemoryLibSQL extends MemoryStorage {
|
|
|
8747
8888
|
details: { newThreadId }
|
|
8748
8889
|
});
|
|
8749
8890
|
try {
|
|
8750
|
-
let messageQuery = `SELECT id,
|
|
8891
|
+
let messageQuery = `SELECT id, "createdAt"
|
|
8751
8892
|
FROM "${TABLE_MESSAGES}" WHERE thread_id = ?`;
|
|
8752
8893
|
const messageParams = [sourceThreadId];
|
|
8753
8894
|
if (options?.messageFilter?.startDate) {
|
|
@@ -8805,52 +8946,28 @@ var MemoryLibSQL = class MemoryLibSQL extends MemoryStorage {
|
|
|
8805
8946
|
nowStr
|
|
8806
8947
|
]
|
|
8807
8948
|
});
|
|
8808
|
-
const clonedMessages = [];
|
|
8809
8949
|
const messageIdMap = {};
|
|
8810
8950
|
const targetResourceId = resourceId || sourceThread.resourceId;
|
|
8811
8951
|
for (const sourceMsg of sourceMessages) {
|
|
8812
8952
|
const newMessageId = crypto.randomUUID();
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
try {
|
|
8817
|
-
parsedContent = JSON.parse(contentStr);
|
|
8818
|
-
} catch {
|
|
8819
|
-
parsedContent = {
|
|
8820
|
-
format: 2,
|
|
8821
|
-
parts: [{
|
|
8822
|
-
type: "text",
|
|
8823
|
-
text: contentStr
|
|
8824
|
-
}]
|
|
8825
|
-
};
|
|
8826
|
-
}
|
|
8827
|
-
await tx.execute({
|
|
8953
|
+
const sourceMsgId = sourceMsg.id;
|
|
8954
|
+
messageIdMap[sourceMsgId] = newMessageId;
|
|
8955
|
+
const insertResult = await tx.execute({
|
|
8828
8956
|
sql: `INSERT INTO "${TABLE_MESSAGES}" (id, thread_id, content, role, type, "createdAt", "resourceId")
|
|
8829
|
-
|
|
8957
|
+
SELECT ?, ?, content, role, type, "createdAt", ?
|
|
8958
|
+
FROM "${TABLE_MESSAGES}" WHERE id = ?`,
|
|
8830
8959
|
args: [
|
|
8831
8960
|
newMessageId,
|
|
8832
8961
|
newThreadId,
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
sourceMsg.type || "v2",
|
|
8836
|
-
sourceMsg.createdAt,
|
|
8837
|
-
targetResourceId
|
|
8962
|
+
targetResourceId,
|
|
8963
|
+
sourceMsgId
|
|
8838
8964
|
]
|
|
8839
8965
|
});
|
|
8840
|
-
|
|
8841
|
-
id: newMessageId,
|
|
8842
|
-
threadId: newThreadId,
|
|
8843
|
-
content: parsedContent,
|
|
8844
|
-
role: sourceMsg.role,
|
|
8845
|
-
type: sourceMsg.type || void 0,
|
|
8846
|
-
createdAt: new Date(sourceMsg.createdAt),
|
|
8847
|
-
resourceId: targetResourceId
|
|
8848
|
-
});
|
|
8966
|
+
if (insertResult.rowsAffected !== 1) throw new Error(`Failed to copy message ${sourceMsgId}: expected 1 row copied but got ${insertResult.rowsAffected}`);
|
|
8849
8967
|
}
|
|
8850
8968
|
await tx.commit();
|
|
8851
8969
|
return {
|
|
8852
8970
|
thread: newThread,
|
|
8853
|
-
clonedMessages,
|
|
8854
8971
|
messageIdMap
|
|
8855
8972
|
};
|
|
8856
8973
|
} catch (error) {
|