@mastra/lance 0.0.0-new-scorer-api-20250801075530 → 0.0.0-new-button-export-20251219133013
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 +1111 -3
- package/README.md +64 -7
- package/dist/index.cjs +1525 -1403
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1526 -1404
- package/dist/index.js.map +1 -1
- package/dist/storage/{domains/operations → db}/index.d.ts +21 -2
- package/dist/storage/db/index.d.ts.map +1 -0
- package/dist/storage/db/utils.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +23 -39
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +29 -9
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +28 -14
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +88 -109
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/filter.d.ts +5 -5
- package/dist/vector/index.d.ts +8 -5
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +29 -11
- package/dist/storage/domains/legacy-evals/index.d.ts +0 -25
- package/dist/storage/domains/legacy-evals/index.d.ts.map +0 -1
- package/dist/storage/domains/operations/index.d.ts.map +0 -1
- package/dist/storage/domains/traces/index.d.ts +0 -34
- package/dist/storage/domains/traces/index.d.ts.map +0 -1
- package/dist/storage/domains/utils.d.ts.map +0 -1
- package/eslint.config.js +0 -6
- package/src/index.ts +0 -2
- package/src/storage/domains/legacy-evals/index.ts +0 -156
- package/src/storage/domains/memory/index.ts +0 -947
- package/src/storage/domains/operations/index.ts +0 -489
- package/src/storage/domains/scores/index.ts +0 -221
- package/src/storage/domains/traces/index.ts +0 -212
- package/src/storage/domains/utils.ts +0 -158
- package/src/storage/domains/workflows/index.ts +0 -207
- package/src/storage/index.test.ts +0 -10
- package/src/storage/index.ts +0 -442
- package/src/vector/filter.test.ts +0 -295
- package/src/vector/filter.ts +0 -443
- package/src/vector/index.test.ts +0 -1493
- package/src/vector/index.ts +0 -941
- package/src/vector/types.ts +0 -16
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -22
- package/vitest.config.ts +0 -11
- /package/dist/storage/{domains → db}/utils.d.ts +0 -0
package/dist/index.cjs
CHANGED
|
@@ -4,131 +4,17 @@ var lancedb = require('@lancedb/lancedb');
|
|
|
4
4
|
var error = require('@mastra/core/error');
|
|
5
5
|
var storage = require('@mastra/core/storage');
|
|
6
6
|
var agent = require('@mastra/core/agent');
|
|
7
|
+
var base = require('@mastra/core/base');
|
|
7
8
|
var apacheArrow = require('apache-arrow');
|
|
9
|
+
var evals = require('@mastra/core/evals');
|
|
8
10
|
var vector = require('@mastra/core/vector');
|
|
9
11
|
var filter = require('@mastra/core/vector/filter');
|
|
10
12
|
|
|
11
13
|
// src/storage/index.ts
|
|
12
|
-
var StoreLegacyEvalsLance = class extends storage.LegacyEvalsStorage {
|
|
13
|
-
client;
|
|
14
|
-
constructor({ client }) {
|
|
15
|
-
super();
|
|
16
|
-
this.client = client;
|
|
17
|
-
}
|
|
18
|
-
async getEvalsByAgentName(agentName, type) {
|
|
19
|
-
try {
|
|
20
|
-
const table = await this.client.openTable(storage.TABLE_EVALS);
|
|
21
|
-
const query = table.query().where(`agent_name = '${agentName}'`);
|
|
22
|
-
const records = await query.toArray();
|
|
23
|
-
let filteredRecords = records;
|
|
24
|
-
if (type === "live") {
|
|
25
|
-
filteredRecords = records.filter((record) => record.test_info === null);
|
|
26
|
-
} else if (type === "test") {
|
|
27
|
-
filteredRecords = records.filter((record) => record.test_info !== null);
|
|
28
|
-
}
|
|
29
|
-
return filteredRecords.map((record) => {
|
|
30
|
-
return {
|
|
31
|
-
id: record.id,
|
|
32
|
-
input: record.input,
|
|
33
|
-
output: record.output,
|
|
34
|
-
agentName: record.agent_name,
|
|
35
|
-
metricName: record.metric_name,
|
|
36
|
-
result: JSON.parse(record.result),
|
|
37
|
-
instructions: record.instructions,
|
|
38
|
-
testInfo: record.test_info ? JSON.parse(record.test_info) : null,
|
|
39
|
-
globalRunId: record.global_run_id,
|
|
40
|
-
runId: record.run_id,
|
|
41
|
-
createdAt: new Date(record.created_at).toString()
|
|
42
|
-
};
|
|
43
|
-
});
|
|
44
|
-
} catch (error$1) {
|
|
45
|
-
throw new error.MastraError(
|
|
46
|
-
{
|
|
47
|
-
id: "LANCE_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
|
|
48
|
-
domain: error.ErrorDomain.STORAGE,
|
|
49
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
50
|
-
details: { agentName }
|
|
51
|
-
},
|
|
52
|
-
error$1
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
async getEvals(options) {
|
|
57
|
-
try {
|
|
58
|
-
const table = await this.client.openTable(storage.TABLE_EVALS);
|
|
59
|
-
const conditions = [];
|
|
60
|
-
if (options.agentName) {
|
|
61
|
-
conditions.push(`agent_name = '${options.agentName}'`);
|
|
62
|
-
}
|
|
63
|
-
if (options.type === "live") {
|
|
64
|
-
conditions.push("length(test_info) = 0");
|
|
65
|
-
} else if (options.type === "test") {
|
|
66
|
-
conditions.push("length(test_info) > 0");
|
|
67
|
-
}
|
|
68
|
-
const startDate = options.dateRange?.start || options.fromDate;
|
|
69
|
-
const endDate = options.dateRange?.end || options.toDate;
|
|
70
|
-
if (startDate) {
|
|
71
|
-
conditions.push(`\`created_at\` >= ${startDate.getTime()}`);
|
|
72
|
-
}
|
|
73
|
-
if (endDate) {
|
|
74
|
-
conditions.push(`\`created_at\` <= ${endDate.getTime()}`);
|
|
75
|
-
}
|
|
76
|
-
let total = 0;
|
|
77
|
-
if (conditions.length > 0) {
|
|
78
|
-
total = await table.countRows(conditions.join(" AND "));
|
|
79
|
-
} else {
|
|
80
|
-
total = await table.countRows();
|
|
81
|
-
}
|
|
82
|
-
const query = table.query();
|
|
83
|
-
if (conditions.length > 0) {
|
|
84
|
-
const whereClause = conditions.join(" AND ");
|
|
85
|
-
query.where(whereClause);
|
|
86
|
-
}
|
|
87
|
-
const records = await query.toArray();
|
|
88
|
-
const evals = records.sort((a, b) => b.created_at - a.created_at).map((record) => {
|
|
89
|
-
return {
|
|
90
|
-
id: record.id,
|
|
91
|
-
input: record.input,
|
|
92
|
-
output: record.output,
|
|
93
|
-
agentName: record.agent_name,
|
|
94
|
-
metricName: record.metric_name,
|
|
95
|
-
result: JSON.parse(record.result),
|
|
96
|
-
instructions: record.instructions,
|
|
97
|
-
testInfo: record.test_info ? JSON.parse(record.test_info) : null,
|
|
98
|
-
globalRunId: record.global_run_id,
|
|
99
|
-
runId: record.run_id,
|
|
100
|
-
createdAt: new Date(record.created_at).toISOString()
|
|
101
|
-
};
|
|
102
|
-
});
|
|
103
|
-
const page = options.page || 0;
|
|
104
|
-
const perPage = options.perPage || 10;
|
|
105
|
-
const pagedEvals = evals.slice(page * perPage, (page + 1) * perPage);
|
|
106
|
-
return {
|
|
107
|
-
evals: pagedEvals,
|
|
108
|
-
total,
|
|
109
|
-
page,
|
|
110
|
-
perPage,
|
|
111
|
-
hasMore: total > (page + 1) * perPage
|
|
112
|
-
};
|
|
113
|
-
} catch (error$1) {
|
|
114
|
-
throw new error.MastraError(
|
|
115
|
-
{
|
|
116
|
-
id: "LANCE_STORE_GET_EVALS_FAILED",
|
|
117
|
-
domain: error.ErrorDomain.STORAGE,
|
|
118
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
119
|
-
details: { agentName: options.agentName ?? "" }
|
|
120
|
-
},
|
|
121
|
-
error$1
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
14
|
function getPrimaryKeys(tableName) {
|
|
127
15
|
let primaryId = ["id"];
|
|
128
16
|
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
129
17
|
primaryId = ["workflow_name", "run_id"];
|
|
130
|
-
} else if (tableName === storage.TABLE_EVALS) {
|
|
131
|
-
primaryId = ["agent_name", "metric_name", "run_id"];
|
|
132
18
|
}
|
|
133
19
|
return primaryId;
|
|
134
20
|
}
|
|
@@ -189,7 +75,6 @@ function processResultWithTypeConversion(rawResult, tableSchema) {
|
|
|
189
75
|
} else if (fieldTypeStr.includes("float64") && ["createdAt", "updatedAt"].includes(key)) {
|
|
190
76
|
processedResult[key] = new Date(processedResult[key]);
|
|
191
77
|
}
|
|
192
|
-
console.log(key, "processedResult", processedResult);
|
|
193
78
|
}
|
|
194
79
|
return processedResult;
|
|
195
80
|
}
|
|
@@ -207,7 +92,7 @@ async function getTableSchema({
|
|
|
207
92
|
} catch (validationError) {
|
|
208
93
|
throw new error.MastraError(
|
|
209
94
|
{
|
|
210
|
-
id: "
|
|
95
|
+
id: storage.createStorageErrorId("LANCE", "GET_TABLE_SCHEMA", "INVALID_ARGS"),
|
|
211
96
|
domain: error.ErrorDomain.STORAGE,
|
|
212
97
|
category: error.ErrorCategory.USER,
|
|
213
98
|
text: validationError.message,
|
|
@@ -230,7 +115,7 @@ async function getTableSchema({
|
|
|
230
115
|
} catch (error$1) {
|
|
231
116
|
throw new error.MastraError(
|
|
232
117
|
{
|
|
233
|
-
id: "
|
|
118
|
+
id: storage.createStorageErrorId("LANCE", "GET_TABLE_SCHEMA", "FAILED"),
|
|
234
119
|
domain: error.ErrorDomain.STORAGE,
|
|
235
120
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
236
121
|
details: { tableName }
|
|
@@ -240,625 +125,503 @@ async function getTableSchema({
|
|
|
240
125
|
}
|
|
241
126
|
}
|
|
242
127
|
|
|
243
|
-
// src/storage/
|
|
244
|
-
|
|
128
|
+
// src/storage/db/index.ts
|
|
129
|
+
function resolveLanceConfig(config) {
|
|
130
|
+
return config.client;
|
|
131
|
+
}
|
|
132
|
+
var LanceDB = class extends base.MastraBase {
|
|
245
133
|
client;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
super();
|
|
134
|
+
constructor({ client }) {
|
|
135
|
+
super({ name: "lance-db" });
|
|
249
136
|
this.client = client;
|
|
250
|
-
this.operations = operations;
|
|
251
137
|
}
|
|
252
|
-
|
|
138
|
+
getDefaultValue(type) {
|
|
139
|
+
switch (type) {
|
|
140
|
+
case "text":
|
|
141
|
+
return "''";
|
|
142
|
+
case "timestamp":
|
|
143
|
+
return "CURRENT_TIMESTAMP";
|
|
144
|
+
case "integer":
|
|
145
|
+
case "bigint":
|
|
146
|
+
return "0";
|
|
147
|
+
case "jsonb":
|
|
148
|
+
return "'{}'";
|
|
149
|
+
case "uuid":
|
|
150
|
+
return "''";
|
|
151
|
+
default:
|
|
152
|
+
return storage.getDefaultValue(type);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async hasColumn(tableName, columnName) {
|
|
156
|
+
const table = await this.client.openTable(tableName);
|
|
157
|
+
const schema = await table.schema();
|
|
158
|
+
return schema.fields.some((field) => field.name === columnName);
|
|
159
|
+
}
|
|
160
|
+
translateSchema(schema) {
|
|
161
|
+
const fields = Object.entries(schema).map(([name, column]) => {
|
|
162
|
+
let arrowType;
|
|
163
|
+
switch (column.type.toLowerCase()) {
|
|
164
|
+
case "text":
|
|
165
|
+
case "uuid":
|
|
166
|
+
arrowType = new apacheArrow.Utf8();
|
|
167
|
+
break;
|
|
168
|
+
case "int":
|
|
169
|
+
case "integer":
|
|
170
|
+
arrowType = new apacheArrow.Int32();
|
|
171
|
+
break;
|
|
172
|
+
case "bigint":
|
|
173
|
+
arrowType = new apacheArrow.Float64();
|
|
174
|
+
break;
|
|
175
|
+
case "float":
|
|
176
|
+
arrowType = new apacheArrow.Float32();
|
|
177
|
+
break;
|
|
178
|
+
case "jsonb":
|
|
179
|
+
case "json":
|
|
180
|
+
arrowType = new apacheArrow.Utf8();
|
|
181
|
+
break;
|
|
182
|
+
case "binary":
|
|
183
|
+
arrowType = new apacheArrow.Binary();
|
|
184
|
+
break;
|
|
185
|
+
case "timestamp":
|
|
186
|
+
arrowType = new apacheArrow.Float64();
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
arrowType = new apacheArrow.Utf8();
|
|
190
|
+
}
|
|
191
|
+
return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
|
|
192
|
+
});
|
|
193
|
+
return new apacheArrow.Schema(fields);
|
|
194
|
+
}
|
|
195
|
+
async createTable({
|
|
196
|
+
tableName,
|
|
197
|
+
schema
|
|
198
|
+
}) {
|
|
253
199
|
try {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
200
|
+
if (!this.client) {
|
|
201
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
202
|
+
}
|
|
203
|
+
if (!tableName) {
|
|
204
|
+
throw new Error("tableName is required for createTable.");
|
|
205
|
+
}
|
|
206
|
+
if (!schema) {
|
|
207
|
+
throw new Error("schema is required for createTable.");
|
|
257
208
|
}
|
|
258
|
-
return {
|
|
259
|
-
...thread,
|
|
260
|
-
createdAt: new Date(thread.createdAt),
|
|
261
|
-
updatedAt: new Date(thread.updatedAt)
|
|
262
|
-
};
|
|
263
209
|
} catch (error$1) {
|
|
264
210
|
throw new error.MastraError(
|
|
265
211
|
{
|
|
266
|
-
id: "
|
|
212
|
+
id: storage.createStorageErrorId("LANCE", "CREATE_TABLE", "INVALID_ARGS"),
|
|
267
213
|
domain: error.ErrorDomain.STORAGE,
|
|
268
|
-
category: error.ErrorCategory.
|
|
214
|
+
category: error.ErrorCategory.USER,
|
|
215
|
+
details: { tableName }
|
|
269
216
|
},
|
|
270
217
|
error$1
|
|
271
218
|
);
|
|
272
219
|
}
|
|
273
|
-
}
|
|
274
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
275
220
|
try {
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
const records = await query.toArray();
|
|
279
|
-
return processResultWithTypeConversion(
|
|
280
|
-
records,
|
|
281
|
-
await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client })
|
|
282
|
-
);
|
|
221
|
+
const arrowSchema = this.translateSchema(schema);
|
|
222
|
+
await this.client.createEmptyTable(tableName, arrowSchema);
|
|
283
223
|
} catch (error$1) {
|
|
224
|
+
if (error$1.message?.includes("already exists")) {
|
|
225
|
+
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
284
228
|
throw new error.MastraError(
|
|
285
229
|
{
|
|
286
|
-
id: "
|
|
230
|
+
id: storage.createStorageErrorId("LANCE", "CREATE_TABLE", "FAILED"),
|
|
287
231
|
domain: error.ErrorDomain.STORAGE,
|
|
288
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
232
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
233
|
+
details: { tableName }
|
|
289
234
|
},
|
|
290
235
|
error$1
|
|
291
236
|
);
|
|
292
237
|
}
|
|
293
238
|
}
|
|
294
|
-
|
|
295
|
-
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
296
|
-
* @param thread - The thread to save
|
|
297
|
-
* @returns The saved thread
|
|
298
|
-
*/
|
|
299
|
-
async saveThread({ thread }) {
|
|
239
|
+
async dropTable({ tableName }) {
|
|
300
240
|
try {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
241
|
+
if (!this.client) {
|
|
242
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
243
|
+
}
|
|
244
|
+
if (!tableName) {
|
|
245
|
+
throw new Error("tableName is required for dropTable.");
|
|
246
|
+
}
|
|
247
|
+
} catch (validationError) {
|
|
306
248
|
throw new error.MastraError(
|
|
307
249
|
{
|
|
308
|
-
id: "
|
|
250
|
+
id: storage.createStorageErrorId("LANCE", "DROP_TABLE", "INVALID_ARGS"),
|
|
309
251
|
domain: error.ErrorDomain.STORAGE,
|
|
310
|
-
category: error.ErrorCategory.
|
|
252
|
+
category: error.ErrorCategory.USER,
|
|
253
|
+
text: validationError.message,
|
|
254
|
+
details: { tableName }
|
|
311
255
|
},
|
|
312
|
-
|
|
256
|
+
validationError
|
|
313
257
|
);
|
|
314
258
|
}
|
|
315
|
-
}
|
|
316
|
-
async updateThread({
|
|
317
|
-
id,
|
|
318
|
-
title,
|
|
319
|
-
metadata
|
|
320
|
-
}) {
|
|
321
|
-
const maxRetries = 5;
|
|
322
|
-
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
323
|
-
try {
|
|
324
|
-
const current = await this.getThreadById({ threadId: id });
|
|
325
|
-
if (!current) {
|
|
326
|
-
throw new Error(`Thread with id ${id} not found`);
|
|
327
|
-
}
|
|
328
|
-
const mergedMetadata = { ...current.metadata, ...metadata };
|
|
329
|
-
const record = {
|
|
330
|
-
id,
|
|
331
|
-
title,
|
|
332
|
-
metadata: JSON.stringify(mergedMetadata),
|
|
333
|
-
updatedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
334
|
-
};
|
|
335
|
-
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
336
|
-
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
337
|
-
const updatedThread = await this.getThreadById({ threadId: id });
|
|
338
|
-
if (!updatedThread) {
|
|
339
|
-
throw new Error(`Failed to retrieve updated thread ${id}`);
|
|
340
|
-
}
|
|
341
|
-
return updatedThread;
|
|
342
|
-
} catch (error$1) {
|
|
343
|
-
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
344
|
-
const delay = Math.pow(2, attempt) * 10;
|
|
345
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
throw new error.MastraError(
|
|
349
|
-
{
|
|
350
|
-
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
351
|
-
domain: error.ErrorDomain.STORAGE,
|
|
352
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
353
|
-
},
|
|
354
|
-
error$1
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
throw new error.MastraError(
|
|
359
|
-
{
|
|
360
|
-
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
361
|
-
domain: error.ErrorDomain.STORAGE,
|
|
362
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
363
|
-
},
|
|
364
|
-
new Error("All retries exhausted")
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
async deleteThread({ threadId }) {
|
|
368
259
|
try {
|
|
369
|
-
|
|
370
|
-
await table.delete(`id = '${threadId}'`);
|
|
371
|
-
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
372
|
-
await messagesTable.delete(`thread_id = '${threadId}'`);
|
|
260
|
+
await this.client.dropTable(tableName);
|
|
373
261
|
} catch (error$1) {
|
|
262
|
+
if (error$1.toString().includes("was not found") || error$1.message?.includes("Table not found")) {
|
|
263
|
+
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
374
266
|
throw new error.MastraError(
|
|
375
267
|
{
|
|
376
|
-
id: "
|
|
268
|
+
id: storage.createStorageErrorId("LANCE", "DROP_TABLE", "FAILED"),
|
|
377
269
|
domain: error.ErrorDomain.STORAGE,
|
|
378
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
270
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
271
|
+
details: { tableName }
|
|
379
272
|
},
|
|
380
273
|
error$1
|
|
381
274
|
);
|
|
382
275
|
}
|
|
383
276
|
}
|
|
384
|
-
async
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
format,
|
|
389
|
-
threadConfig
|
|
277
|
+
async alterTable({
|
|
278
|
+
tableName,
|
|
279
|
+
schema,
|
|
280
|
+
ifNotExists
|
|
390
281
|
}) {
|
|
391
282
|
try {
|
|
392
|
-
if (
|
|
393
|
-
throw new Error("
|
|
394
|
-
}
|
|
395
|
-
const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
|
|
396
|
-
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
397
|
-
let allRecords = [];
|
|
398
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
399
|
-
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
400
|
-
for (const threadId2 of threadIds) {
|
|
401
|
-
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
402
|
-
let threadRecords = await threadQuery.toArray();
|
|
403
|
-
allRecords.push(...threadRecords);
|
|
404
|
-
}
|
|
405
|
-
} else {
|
|
406
|
-
let query = table.query().where(`\`thread_id\` = '${threadId}'`);
|
|
407
|
-
allRecords = await query.toArray();
|
|
283
|
+
if (!this.client) {
|
|
284
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
408
285
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const dateB = new Date(b.createdAt).getTime();
|
|
412
|
-
return dateA - dateB;
|
|
413
|
-
});
|
|
414
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
415
|
-
allRecords = this.processMessagesWithContext(allRecords, selectBy.include);
|
|
286
|
+
if (!tableName) {
|
|
287
|
+
throw new Error("tableName is required for alterTable.");
|
|
416
288
|
}
|
|
417
|
-
if (
|
|
418
|
-
|
|
289
|
+
if (!schema) {
|
|
290
|
+
throw new Error("schema is required for alterTable.");
|
|
419
291
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
292
|
+
if (!ifNotExists || ifNotExists.length === 0) {
|
|
293
|
+
this.logger.debug("No columns specified to add in alterTable, skipping.");
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
} catch (validationError) {
|
|
297
|
+
throw new error.MastraError(
|
|
298
|
+
{
|
|
299
|
+
id: storage.createStorageErrorId("LANCE", "ALTER_TABLE", "INVALID_ARGS"),
|
|
300
|
+
domain: error.ErrorDomain.STORAGE,
|
|
301
|
+
category: error.ErrorCategory.USER,
|
|
302
|
+
text: validationError.message,
|
|
303
|
+
details: { tableName }
|
|
304
|
+
},
|
|
305
|
+
validationError
|
|
423
306
|
);
|
|
424
|
-
|
|
425
|
-
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
const table = await this.client.openTable(tableName);
|
|
310
|
+
const currentSchema = await table.schema();
|
|
311
|
+
const existingFields = new Set(currentSchema.fields.map((f) => f.name));
|
|
312
|
+
const typeMap = {
|
|
313
|
+
text: "string",
|
|
314
|
+
integer: "int",
|
|
315
|
+
bigint: "bigint",
|
|
316
|
+
timestamp: "timestamp",
|
|
317
|
+
jsonb: "string",
|
|
318
|
+
uuid: "string"
|
|
319
|
+
};
|
|
320
|
+
const columnsToAdd = ifNotExists.filter((col) => schema[col] && !existingFields.has(col)).map((col) => {
|
|
321
|
+
const colDef = schema[col];
|
|
426
322
|
return {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
content: typeof msg.content === "string" ? (() => {
|
|
430
|
-
try {
|
|
431
|
-
return JSON.parse(msg.content);
|
|
432
|
-
} catch {
|
|
433
|
-
return msg.content;
|
|
434
|
-
}
|
|
435
|
-
})() : msg.content
|
|
323
|
+
name: col,
|
|
324
|
+
valueSql: colDef?.nullable ? `cast(NULL as ${typeMap[colDef.type ?? "text"]})` : `cast(${this.getDefaultValue(colDef?.type ?? "text")} as ${typeMap[colDef?.type ?? "text"]})`
|
|
436
325
|
};
|
|
437
326
|
});
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
327
|
+
if (columnsToAdd.length > 0) {
|
|
328
|
+
await table.addColumns(columnsToAdd);
|
|
329
|
+
this.logger?.info?.(`Added columns [${columnsToAdd.map((c) => c.name).join(", ")}] to table ${tableName}`);
|
|
330
|
+
}
|
|
441
331
|
} catch (error$1) {
|
|
442
332
|
throw new error.MastraError(
|
|
443
333
|
{
|
|
444
|
-
id: "
|
|
334
|
+
id: storage.createStorageErrorId("LANCE", "ALTER_TABLE", "FAILED"),
|
|
445
335
|
domain: error.ErrorDomain.STORAGE,
|
|
446
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
336
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
337
|
+
details: { tableName }
|
|
447
338
|
},
|
|
448
339
|
error$1
|
|
449
340
|
);
|
|
450
341
|
}
|
|
451
342
|
}
|
|
452
|
-
async
|
|
343
|
+
async clearTable({ tableName }) {
|
|
453
344
|
try {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
return [];
|
|
457
|
-
}
|
|
458
|
-
const threadId = messages[0]?.threadId;
|
|
459
|
-
if (!threadId) {
|
|
460
|
-
throw new Error("Thread ID is required");
|
|
345
|
+
if (!this.client) {
|
|
346
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
461
347
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
throw new Error("Message ID is required");
|
|
465
|
-
}
|
|
466
|
-
if (!message.threadId) {
|
|
467
|
-
throw new Error("Thread ID is required for all messages");
|
|
468
|
-
}
|
|
469
|
-
if (message.resourceId === null || message.resourceId === void 0) {
|
|
470
|
-
throw new Error("Resource ID cannot be null or undefined");
|
|
471
|
-
}
|
|
472
|
-
if (!message.content) {
|
|
473
|
-
throw new Error("Message content is required");
|
|
474
|
-
}
|
|
348
|
+
if (!tableName) {
|
|
349
|
+
throw new Error("tableName is required for clearTable.");
|
|
475
350
|
}
|
|
476
|
-
|
|
477
|
-
const { threadId: threadId2, type, ...rest } = message;
|
|
478
|
-
return {
|
|
479
|
-
...rest,
|
|
480
|
-
thread_id: threadId2,
|
|
481
|
-
type: type ?? "v2",
|
|
482
|
-
content: JSON.stringify(message.content)
|
|
483
|
-
};
|
|
484
|
-
});
|
|
485
|
-
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
486
|
-
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
487
|
-
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
488
|
-
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
489
|
-
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
490
|
-
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
491
|
-
const list = new agent.MessageList().add(messages, "memory");
|
|
492
|
-
if (format === `v2`) return list.get.all.v2();
|
|
493
|
-
return list.get.all.v1();
|
|
494
|
-
} catch (error$1) {
|
|
351
|
+
} catch (validationError) {
|
|
495
352
|
throw new error.MastraError(
|
|
496
353
|
{
|
|
497
|
-
id: "
|
|
354
|
+
id: storage.createStorageErrorId("LANCE", "CLEAR_TABLE", "INVALID_ARGS"),
|
|
498
355
|
domain: error.ErrorDomain.STORAGE,
|
|
499
|
-
category: error.ErrorCategory.
|
|
356
|
+
category: error.ErrorCategory.USER,
|
|
357
|
+
text: validationError.message,
|
|
358
|
+
details: { tableName }
|
|
500
359
|
},
|
|
501
|
-
|
|
360
|
+
validationError
|
|
502
361
|
);
|
|
503
362
|
}
|
|
504
|
-
}
|
|
505
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
506
363
|
try {
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
const total = await table.countRows(`\`resourceId\` = '${resourceId}'`);
|
|
510
|
-
const query = table.query().where(`\`resourceId\` = '${resourceId}'`);
|
|
511
|
-
const offset = page * perPage;
|
|
512
|
-
query.limit(perPage);
|
|
513
|
-
if (offset > 0) {
|
|
514
|
-
query.offset(offset);
|
|
515
|
-
}
|
|
516
|
-
const records = await query.toArray();
|
|
517
|
-
records.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
518
|
-
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
519
|
-
const threads = records.map((record) => processResultWithTypeConversion(record, schema));
|
|
520
|
-
return {
|
|
521
|
-
threads,
|
|
522
|
-
total,
|
|
523
|
-
page,
|
|
524
|
-
perPage,
|
|
525
|
-
hasMore: total > (page + 1) * perPage
|
|
526
|
-
};
|
|
364
|
+
const table = await this.client.openTable(tableName);
|
|
365
|
+
await table.delete("1=1");
|
|
527
366
|
} catch (error$1) {
|
|
528
367
|
throw new error.MastraError(
|
|
529
368
|
{
|
|
530
|
-
id: "
|
|
369
|
+
id: storage.createStorageErrorId("LANCE", "CLEAR_TABLE", "FAILED"),
|
|
531
370
|
domain: error.ErrorDomain.STORAGE,
|
|
532
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
371
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
372
|
+
details: { tableName }
|
|
533
373
|
},
|
|
534
374
|
error$1
|
|
535
375
|
);
|
|
536
376
|
}
|
|
537
377
|
}
|
|
538
|
-
|
|
539
|
-
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
540
|
-
* @param records - The sorted array of records to process
|
|
541
|
-
* @param include - The array of include specifications with context parameters
|
|
542
|
-
* @returns The processed array with context messages included
|
|
543
|
-
*/
|
|
544
|
-
processMessagesWithContext(records, include) {
|
|
545
|
-
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
546
|
-
if (messagesWithContext.length === 0) {
|
|
547
|
-
return records;
|
|
548
|
-
}
|
|
549
|
-
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
550
|
-
records.forEach((message, index) => {
|
|
551
|
-
messageIndexMap.set(message.id, index);
|
|
552
|
-
});
|
|
553
|
-
const additionalIndices = /* @__PURE__ */ new Set();
|
|
554
|
-
for (const item of messagesWithContext) {
|
|
555
|
-
const messageIndex = messageIndexMap.get(item.id);
|
|
556
|
-
if (messageIndex !== void 0) {
|
|
557
|
-
if (item.withPreviousMessages) {
|
|
558
|
-
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
559
|
-
for (let i = startIdx; i < messageIndex; i++) {
|
|
560
|
-
additionalIndices.add(i);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
if (item.withNextMessages) {
|
|
564
|
-
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
565
|
-
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
566
|
-
additionalIndices.add(i);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
if (additionalIndices.size === 0) {
|
|
572
|
-
return records;
|
|
573
|
-
}
|
|
574
|
-
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
575
|
-
const allIndices = /* @__PURE__ */ new Set();
|
|
576
|
-
records.forEach((record, index) => {
|
|
577
|
-
if (originalMatchIds.has(record.id)) {
|
|
578
|
-
allIndices.add(index);
|
|
579
|
-
}
|
|
580
|
-
});
|
|
581
|
-
additionalIndices.forEach((index) => {
|
|
582
|
-
allIndices.add(index);
|
|
583
|
-
});
|
|
584
|
-
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
585
|
-
}
|
|
586
|
-
async getMessagesPaginated(args) {
|
|
378
|
+
async insert({ tableName, record }) {
|
|
587
379
|
try {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
throw new Error("Thread ID is required for getMessagesPaginated");
|
|
591
|
-
}
|
|
592
|
-
const page = selectBy?.pagination?.page ?? 0;
|
|
593
|
-
const perPage = selectBy?.pagination?.perPage ?? 10;
|
|
594
|
-
const dateRange = selectBy?.pagination?.dateRange;
|
|
595
|
-
const fromDate = dateRange?.start;
|
|
596
|
-
const toDate = dateRange?.end;
|
|
597
|
-
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
598
|
-
const messages = [];
|
|
599
|
-
if (selectBy?.include && Array.isArray(selectBy.include)) {
|
|
600
|
-
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
601
|
-
const allThreadMessages = [];
|
|
602
|
-
for (const threadId2 of threadIds) {
|
|
603
|
-
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
604
|
-
let threadRecords = await threadQuery.toArray();
|
|
605
|
-
if (fromDate) threadRecords = threadRecords.filter((m) => m.createdAt >= fromDate.getTime());
|
|
606
|
-
if (toDate) threadRecords = threadRecords.filter((m) => m.createdAt <= toDate.getTime());
|
|
607
|
-
allThreadMessages.push(...threadRecords);
|
|
608
|
-
}
|
|
609
|
-
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
610
|
-
const contextMessages = this.processMessagesWithContext(allThreadMessages, selectBy.include);
|
|
611
|
-
messages.push(...contextMessages);
|
|
612
|
-
}
|
|
613
|
-
const conditions = [`thread_id = '${threadId}'`];
|
|
614
|
-
if (resourceId) {
|
|
615
|
-
conditions.push(`\`resourceId\` = '${resourceId}'`);
|
|
616
|
-
}
|
|
617
|
-
if (fromDate) {
|
|
618
|
-
conditions.push(`\`createdAt\` >= ${fromDate.getTime()}`);
|
|
619
|
-
}
|
|
620
|
-
if (toDate) {
|
|
621
|
-
conditions.push(`\`createdAt\` <= ${toDate.getTime()}`);
|
|
380
|
+
if (!this.client) {
|
|
381
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
622
382
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
total = await table.countRows(conditions.join(" AND "));
|
|
626
|
-
} else {
|
|
627
|
-
total = await table.countRows();
|
|
383
|
+
if (!tableName) {
|
|
384
|
+
throw new Error("tableName is required for insert.");
|
|
628
385
|
}
|
|
629
|
-
if (
|
|
630
|
-
|
|
631
|
-
messages: [],
|
|
632
|
-
total: 0,
|
|
633
|
-
page,
|
|
634
|
-
perPage,
|
|
635
|
-
hasMore: false
|
|
636
|
-
};
|
|
386
|
+
if (!record || Object.keys(record).length === 0) {
|
|
387
|
+
throw new Error("record is required and cannot be empty for insert.");
|
|
637
388
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
if (excludeIds.length > 0) {
|
|
659
|
-
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
389
|
+
} catch (validationError) {
|
|
390
|
+
throw new error.MastraError(
|
|
391
|
+
{
|
|
392
|
+
id: storage.createStorageErrorId("LANCE", "INSERT", "INVALID_ARGS"),
|
|
393
|
+
domain: error.ErrorDomain.STORAGE,
|
|
394
|
+
category: error.ErrorCategory.USER,
|
|
395
|
+
text: validationError.message,
|
|
396
|
+
details: { tableName }
|
|
397
|
+
},
|
|
398
|
+
validationError
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
const table = await this.client.openTable(tableName);
|
|
403
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
404
|
+
const processedRecord = { ...record };
|
|
405
|
+
for (const key in processedRecord) {
|
|
406
|
+
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
407
|
+
this.logger.debug("Converting object to JSON string: ", processedRecord[key]);
|
|
408
|
+
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
660
409
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
const allMessages = [...messages, ...selectedMessages];
|
|
664
|
-
const seen = /* @__PURE__ */ new Set();
|
|
665
|
-
const dedupedMessages = allMessages.filter((m) => {
|
|
666
|
-
const key = `${m.id}:${m.thread_id}`;
|
|
667
|
-
if (seen.has(key)) return false;
|
|
668
|
-
seen.add(key);
|
|
669
|
-
return true;
|
|
670
|
-
});
|
|
671
|
-
const formattedMessages = dedupedMessages.map((msg) => {
|
|
672
|
-
const { thread_id, ...rest } = msg;
|
|
673
|
-
return {
|
|
674
|
-
...rest,
|
|
675
|
-
threadId: thread_id,
|
|
676
|
-
content: typeof msg.content === "string" ? (() => {
|
|
677
|
-
try {
|
|
678
|
-
return JSON.parse(msg.content);
|
|
679
|
-
} catch {
|
|
680
|
-
return msg.content;
|
|
681
|
-
}
|
|
682
|
-
})() : msg.content
|
|
683
|
-
};
|
|
684
|
-
});
|
|
685
|
-
const list = new agent.MessageList().add(formattedMessages, "memory");
|
|
686
|
-
return {
|
|
687
|
-
messages: format === "v2" ? list.get.all.v2() : list.get.all.v1(),
|
|
688
|
-
total,
|
|
689
|
-
// Total should be the count of messages matching the filters
|
|
690
|
-
page,
|
|
691
|
-
perPage,
|
|
692
|
-
hasMore: total > (page + 1) * perPage
|
|
693
|
-
};
|
|
410
|
+
}
|
|
411
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([processedRecord]);
|
|
694
412
|
} catch (error$1) {
|
|
695
413
|
throw new error.MastraError(
|
|
696
414
|
{
|
|
697
|
-
id: "
|
|
415
|
+
id: storage.createStorageErrorId("LANCE", "INSERT", "FAILED"),
|
|
698
416
|
domain: error.ErrorDomain.STORAGE,
|
|
699
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
417
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
418
|
+
details: { tableName }
|
|
700
419
|
},
|
|
701
420
|
error$1
|
|
702
421
|
);
|
|
703
422
|
}
|
|
704
423
|
}
|
|
705
|
-
|
|
706
|
-
* Parse message data from LanceDB record format to MastraMessageV2 format
|
|
707
|
-
*/
|
|
708
|
-
parseMessageData(data) {
|
|
709
|
-
const { thread_id, ...rest } = data;
|
|
710
|
-
return {
|
|
711
|
-
...rest,
|
|
712
|
-
threadId: thread_id,
|
|
713
|
-
content: typeof data.content === "string" ? (() => {
|
|
714
|
-
try {
|
|
715
|
-
return JSON.parse(data.content);
|
|
716
|
-
} catch {
|
|
717
|
-
return data.content;
|
|
718
|
-
}
|
|
719
|
-
})() : data.content,
|
|
720
|
-
createdAt: new Date(data.createdAt),
|
|
721
|
-
updatedAt: new Date(data.updatedAt)
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
async updateMessages(args) {
|
|
725
|
-
const { messages } = args;
|
|
726
|
-
this.logger.debug("Updating messages", { count: messages.length });
|
|
727
|
-
if (!messages.length) {
|
|
728
|
-
return [];
|
|
729
|
-
}
|
|
730
|
-
const updatedMessages = [];
|
|
731
|
-
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
424
|
+
async batchInsert({ tableName, records }) {
|
|
732
425
|
try {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
const existingMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
736
|
-
if (!existingMessage) {
|
|
737
|
-
this.logger.warn("Message not found for update", { id });
|
|
738
|
-
continue;
|
|
739
|
-
}
|
|
740
|
-
const existingMsg = this.parseMessageData(existingMessage);
|
|
741
|
-
const originalThreadId = existingMsg.threadId;
|
|
742
|
-
affectedThreadIds.add(originalThreadId);
|
|
743
|
-
const updatePayload = {};
|
|
744
|
-
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
745
|
-
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
746
|
-
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
747
|
-
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
748
|
-
updatePayload.thread_id = updates.threadId;
|
|
749
|
-
affectedThreadIds.add(updates.threadId);
|
|
750
|
-
}
|
|
751
|
-
if (updates.content) {
|
|
752
|
-
const existingContent = existingMsg.content;
|
|
753
|
-
let newContent = { ...existingContent };
|
|
754
|
-
if (updates.content.metadata !== void 0) {
|
|
755
|
-
newContent.metadata = {
|
|
756
|
-
...existingContent.metadata || {},
|
|
757
|
-
...updates.content.metadata || {}
|
|
758
|
-
};
|
|
759
|
-
}
|
|
760
|
-
if (updates.content.content !== void 0) {
|
|
761
|
-
newContent.content = updates.content.content;
|
|
762
|
-
}
|
|
763
|
-
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
764
|
-
newContent.parts = updates.content.parts;
|
|
765
|
-
}
|
|
766
|
-
updatePayload.content = JSON.stringify(newContent);
|
|
767
|
-
}
|
|
768
|
-
await this.operations.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
769
|
-
const updatedMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
770
|
-
if (updatedMessage) {
|
|
771
|
-
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
772
|
-
}
|
|
426
|
+
if (!this.client) {
|
|
427
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
773
428
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
tableName: storage.TABLE_THREADS,
|
|
777
|
-
record: { id: threadId, updatedAt: Date.now() }
|
|
778
|
-
});
|
|
429
|
+
if (!tableName) {
|
|
430
|
+
throw new Error("tableName is required for batchInsert.");
|
|
779
431
|
}
|
|
780
|
-
|
|
432
|
+
if (!records || records.length === 0) {
|
|
433
|
+
throw new Error("records array is required and cannot be empty for batchInsert.");
|
|
434
|
+
}
|
|
435
|
+
} catch (validationError) {
|
|
436
|
+
throw new error.MastraError(
|
|
437
|
+
{
|
|
438
|
+
id: storage.createStorageErrorId("LANCE", "BATCH_INSERT", "INVALID_ARGS"),
|
|
439
|
+
domain: error.ErrorDomain.STORAGE,
|
|
440
|
+
category: error.ErrorCategory.USER,
|
|
441
|
+
text: validationError.message,
|
|
442
|
+
details: { tableName }
|
|
443
|
+
},
|
|
444
|
+
validationError
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
try {
|
|
448
|
+
const table = await this.client.openTable(tableName);
|
|
449
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
450
|
+
const processedRecords = records.map((record) => {
|
|
451
|
+
const processedRecord = { ...record };
|
|
452
|
+
for (const key in processedRecord) {
|
|
453
|
+
if (processedRecord[key] == null) continue;
|
|
454
|
+
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
455
|
+
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return processedRecord;
|
|
459
|
+
});
|
|
460
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(processedRecords);
|
|
781
461
|
} catch (error$1) {
|
|
782
462
|
throw new error.MastraError(
|
|
783
463
|
{
|
|
784
|
-
id: "
|
|
464
|
+
id: storage.createStorageErrorId("LANCE", "BATCH_INSERT", "FAILED"),
|
|
785
465
|
domain: error.ErrorDomain.STORAGE,
|
|
786
466
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
787
|
-
details: {
|
|
467
|
+
details: { tableName }
|
|
788
468
|
},
|
|
789
469
|
error$1
|
|
790
470
|
);
|
|
791
471
|
}
|
|
792
472
|
}
|
|
793
|
-
async
|
|
473
|
+
async load({ tableName, keys }) {
|
|
794
474
|
try {
|
|
795
|
-
|
|
796
|
-
|
|
475
|
+
if (!this.client) {
|
|
476
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
477
|
+
}
|
|
478
|
+
if (!tableName) {
|
|
479
|
+
throw new Error("tableName is required for load.");
|
|
480
|
+
}
|
|
481
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
482
|
+
throw new Error("keys are required and cannot be empty for load.");
|
|
483
|
+
}
|
|
484
|
+
} catch (validationError) {
|
|
485
|
+
throw new error.MastraError(
|
|
486
|
+
{
|
|
487
|
+
id: storage.createStorageErrorId("LANCE", "LOAD", "INVALID_ARGS"),
|
|
488
|
+
domain: error.ErrorDomain.STORAGE,
|
|
489
|
+
category: error.ErrorCategory.USER,
|
|
490
|
+
text: validationError.message,
|
|
491
|
+
details: { tableName }
|
|
492
|
+
},
|
|
493
|
+
validationError
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const table = await this.client.openTable(tableName);
|
|
498
|
+
const tableSchema = await getTableSchema({ tableName, client: this.client });
|
|
499
|
+
const query = table.query();
|
|
500
|
+
if (Object.keys(keys).length > 0) {
|
|
501
|
+
validateKeyTypes(keys, tableSchema);
|
|
502
|
+
const filterConditions = Object.entries(keys).map(([key, value]) => {
|
|
503
|
+
const isCamelCase = /^[a-z][a-zA-Z]*$/.test(key) && /[A-Z]/.test(key);
|
|
504
|
+
const quotedKey = isCamelCase ? `\`${key}\`` : key;
|
|
505
|
+
if (typeof value === "string") {
|
|
506
|
+
return `${quotedKey} = '${value}'`;
|
|
507
|
+
} else if (value === null) {
|
|
508
|
+
return `${quotedKey} IS NULL`;
|
|
509
|
+
} else {
|
|
510
|
+
return `${quotedKey} = ${value}`;
|
|
511
|
+
}
|
|
512
|
+
}).join(" AND ");
|
|
513
|
+
this.logger.debug("where clause generated: " + filterConditions);
|
|
514
|
+
query.where(filterConditions);
|
|
515
|
+
}
|
|
516
|
+
const result = await query.limit(1).toArray();
|
|
517
|
+
if (result.length === 0) {
|
|
518
|
+
this.logger.debug("No record found");
|
|
797
519
|
return null;
|
|
798
520
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
521
|
+
return processResultWithTypeConversion(result[0], tableSchema);
|
|
522
|
+
} catch (error$1) {
|
|
523
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
524
|
+
throw new error.MastraError(
|
|
525
|
+
{
|
|
526
|
+
id: storage.createStorageErrorId("LANCE", "LOAD", "FAILED"),
|
|
527
|
+
domain: error.ErrorDomain.STORAGE,
|
|
528
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
529
|
+
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
530
|
+
},
|
|
531
|
+
error$1
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
// src/storage/domains/memory/index.ts
|
|
538
|
+
var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
539
|
+
client;
|
|
540
|
+
#db;
|
|
541
|
+
constructor(config) {
|
|
542
|
+
super();
|
|
543
|
+
const client = resolveLanceConfig(config);
|
|
544
|
+
this.client = client;
|
|
545
|
+
this.#db = new LanceDB({ client });
|
|
546
|
+
}
|
|
547
|
+
async init() {
|
|
548
|
+
await this.#db.createTable({ tableName: storage.TABLE_THREADS, schema: storage.TABLE_SCHEMAS[storage.TABLE_THREADS] });
|
|
549
|
+
await this.#db.createTable({ tableName: storage.TABLE_MESSAGES, schema: storage.TABLE_SCHEMAS[storage.TABLE_MESSAGES] });
|
|
550
|
+
await this.#db.createTable({ tableName: storage.TABLE_RESOURCES, schema: storage.TABLE_SCHEMAS[storage.TABLE_RESOURCES] });
|
|
551
|
+
await this.#db.alterTable({
|
|
552
|
+
tableName: storage.TABLE_MESSAGES,
|
|
553
|
+
schema: storage.TABLE_SCHEMAS[storage.TABLE_MESSAGES],
|
|
554
|
+
ifNotExists: ["resourceId"]
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
async dangerouslyClearAll() {
|
|
558
|
+
await this.#db.clearTable({ tableName: storage.TABLE_THREADS });
|
|
559
|
+
await this.#db.clearTable({ tableName: storage.TABLE_MESSAGES });
|
|
560
|
+
await this.#db.clearTable({ tableName: storage.TABLE_RESOURCES });
|
|
561
|
+
}
|
|
562
|
+
async deleteMessages(messageIds) {
|
|
563
|
+
if (!messageIds || messageIds.length === 0) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
this.logger.debug("Deleting messages", { count: messageIds.length });
|
|
567
|
+
try {
|
|
568
|
+
const threadIds = /* @__PURE__ */ new Set();
|
|
569
|
+
for (const messageId of messageIds) {
|
|
570
|
+
const message = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id: messageId } });
|
|
571
|
+
if (message?.thread_id) {
|
|
572
|
+
threadIds.add(message.thread_id);
|
|
813
573
|
}
|
|
814
|
-
} catch {
|
|
815
|
-
createdAt = /* @__PURE__ */ new Date();
|
|
816
574
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
575
|
+
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
576
|
+
const idConditions = messageIds.map((id) => `id = '${this.escapeSql(id)}'`).join(" OR ");
|
|
577
|
+
await messagesTable.delete(idConditions);
|
|
578
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
579
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
580
|
+
for (const threadId of threadIds) {
|
|
581
|
+
const thread = await this.getThreadById({ threadId });
|
|
582
|
+
if (thread) {
|
|
583
|
+
const record = {
|
|
584
|
+
id: threadId,
|
|
585
|
+
resourceId: thread.resourceId,
|
|
586
|
+
title: thread.title,
|
|
587
|
+
metadata: JSON.stringify(thread.metadata),
|
|
588
|
+
createdAt: new Date(thread.createdAt).getTime(),
|
|
589
|
+
updatedAt: now
|
|
590
|
+
};
|
|
591
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
829
592
|
}
|
|
830
|
-
} catch {
|
|
831
|
-
updatedAt = /* @__PURE__ */ new Date();
|
|
832
|
-
}
|
|
833
|
-
let workingMemory = resource.workingMemory;
|
|
834
|
-
if (workingMemory === null || workingMemory === void 0) {
|
|
835
|
-
workingMemory = void 0;
|
|
836
|
-
} else if (workingMemory === "") {
|
|
837
|
-
workingMemory = "";
|
|
838
|
-
} else if (typeof workingMemory === "object") {
|
|
839
|
-
workingMemory = JSON.stringify(workingMemory);
|
|
840
593
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
594
|
+
} catch (error$1) {
|
|
595
|
+
throw new error.MastraError(
|
|
596
|
+
{
|
|
597
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_MESSAGES", "FAILED"),
|
|
598
|
+
domain: error.ErrorDomain.STORAGE,
|
|
599
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
600
|
+
details: { count: messageIds.length }
|
|
601
|
+
},
|
|
602
|
+
error$1
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
// Utility to escape single quotes in SQL strings
|
|
607
|
+
escapeSql(str) {
|
|
608
|
+
return str.replace(/'/g, "''");
|
|
609
|
+
}
|
|
610
|
+
async getThreadById({ threadId }) {
|
|
611
|
+
try {
|
|
612
|
+
const thread = await this.#db.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
613
|
+
if (!thread) {
|
|
614
|
+
return null;
|
|
850
615
|
}
|
|
851
616
|
return {
|
|
852
|
-
...
|
|
853
|
-
createdAt,
|
|
854
|
-
updatedAt
|
|
855
|
-
workingMemory,
|
|
856
|
-
metadata
|
|
617
|
+
...thread,
|
|
618
|
+
createdAt: new Date(thread.createdAt),
|
|
619
|
+
updatedAt: new Date(thread.updatedAt)
|
|
857
620
|
};
|
|
858
621
|
} catch (error$1) {
|
|
859
622
|
throw new error.MastraError(
|
|
860
623
|
{
|
|
861
|
-
id: "
|
|
624
|
+
id: storage.createStorageErrorId("LANCE", "GET_THREAD_BY_ID", "FAILED"),
|
|
862
625
|
domain: error.ErrorDomain.STORAGE,
|
|
863
626
|
category: error.ErrorCategory.THIRD_PARTY
|
|
864
627
|
},
|
|
@@ -866,23 +629,21 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
866
629
|
);
|
|
867
630
|
}
|
|
868
631
|
}
|
|
869
|
-
|
|
632
|
+
/**
|
|
633
|
+
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
634
|
+
* @param thread - The thread to save
|
|
635
|
+
* @returns The saved thread
|
|
636
|
+
*/
|
|
637
|
+
async saveThread({ thread }) {
|
|
870
638
|
try {
|
|
871
|
-
const record = {
|
|
872
|
-
|
|
873
|
-
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
874
|
-
createdAt: resource.createdAt.getTime(),
|
|
875
|
-
// Store as timestamp (milliseconds)
|
|
876
|
-
updatedAt: resource.updatedAt.getTime()
|
|
877
|
-
// Store as timestamp (milliseconds)
|
|
878
|
-
};
|
|
879
|
-
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
639
|
+
const record = { ...thread, metadata: JSON.stringify(thread.metadata) };
|
|
640
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
880
641
|
await table.add([record], { mode: "append" });
|
|
881
|
-
return
|
|
642
|
+
return thread;
|
|
882
643
|
} catch (error$1) {
|
|
883
644
|
throw new error.MastraError(
|
|
884
645
|
{
|
|
885
|
-
id: "
|
|
646
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_THREAD", "FAILED"),
|
|
886
647
|
domain: error.ErrorDomain.STORAGE,
|
|
887
648
|
category: error.ErrorCategory.THIRD_PARTY
|
|
888
649
|
},
|
|
@@ -890,44 +651,32 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
890
651
|
);
|
|
891
652
|
}
|
|
892
653
|
}
|
|
893
|
-
async
|
|
894
|
-
|
|
895
|
-
|
|
654
|
+
async updateThread({
|
|
655
|
+
id,
|
|
656
|
+
title,
|
|
896
657
|
metadata
|
|
897
658
|
}) {
|
|
898
|
-
const maxRetries =
|
|
659
|
+
const maxRetries = 5;
|
|
899
660
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
900
661
|
try {
|
|
901
|
-
const
|
|
902
|
-
if (!
|
|
903
|
-
|
|
904
|
-
id: resourceId,
|
|
905
|
-
workingMemory,
|
|
906
|
-
metadata: metadata || {},
|
|
907
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
908
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
909
|
-
};
|
|
910
|
-
return this.saveResource({ resource: newResource });
|
|
662
|
+
const current = await this.getThreadById({ threadId: id });
|
|
663
|
+
if (!current) {
|
|
664
|
+
throw new Error(`Thread with id ${id} not found`);
|
|
911
665
|
}
|
|
912
|
-
const
|
|
913
|
-
...existingResource,
|
|
914
|
-
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
915
|
-
metadata: {
|
|
916
|
-
...existingResource.metadata,
|
|
917
|
-
...metadata
|
|
918
|
-
},
|
|
919
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
920
|
-
};
|
|
666
|
+
const mergedMetadata = { ...current.metadata, ...metadata };
|
|
921
667
|
const record = {
|
|
922
|
-
id
|
|
923
|
-
|
|
924
|
-
metadata:
|
|
925
|
-
updatedAt:
|
|
926
|
-
// Store as timestamp (milliseconds)
|
|
668
|
+
id,
|
|
669
|
+
title,
|
|
670
|
+
metadata: JSON.stringify(mergedMetadata),
|
|
671
|
+
updatedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
927
672
|
};
|
|
928
|
-
const table = await this.client.openTable(storage.
|
|
673
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
929
674
|
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
930
|
-
|
|
675
|
+
const updatedThread = await this.getThreadById({ threadId: id });
|
|
676
|
+
if (!updatedThread) {
|
|
677
|
+
throw new Error(`Failed to retrieve updated thread ${id}`);
|
|
678
|
+
}
|
|
679
|
+
return updatedThread;
|
|
931
680
|
} catch (error$1) {
|
|
932
681
|
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
933
682
|
const delay = Math.pow(2, attempt) * 10;
|
|
@@ -936,7 +685,7 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
936
685
|
}
|
|
937
686
|
throw new error.MastraError(
|
|
938
687
|
{
|
|
939
|
-
id: "
|
|
688
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_THREAD", "FAILED"),
|
|
940
689
|
domain: error.ErrorDomain.STORAGE,
|
|
941
690
|
category: error.ErrorCategory.THIRD_PARTY
|
|
942
691
|
},
|
|
@@ -944,444 +693,679 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
944
693
|
);
|
|
945
694
|
}
|
|
946
695
|
}
|
|
947
|
-
throw new
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
}
|
|
956
|
-
getDefaultValue(type) {
|
|
957
|
-
switch (type) {
|
|
958
|
-
case "text":
|
|
959
|
-
return "''";
|
|
960
|
-
case "timestamp":
|
|
961
|
-
return "CURRENT_TIMESTAMP";
|
|
962
|
-
case "integer":
|
|
963
|
-
case "bigint":
|
|
964
|
-
return "0";
|
|
965
|
-
case "jsonb":
|
|
966
|
-
return "'{}'";
|
|
967
|
-
case "uuid":
|
|
968
|
-
return "''";
|
|
969
|
-
default:
|
|
970
|
-
return super.getDefaultValue(type);
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
async hasColumn(tableName, columnName) {
|
|
974
|
-
const table = await this.client.openTable(tableName);
|
|
975
|
-
const schema = await table.schema();
|
|
976
|
-
return schema.fields.some((field) => field.name === columnName);
|
|
977
|
-
}
|
|
978
|
-
translateSchema(schema) {
|
|
979
|
-
const fields = Object.entries(schema).map(([name, column]) => {
|
|
980
|
-
let arrowType;
|
|
981
|
-
switch (column.type.toLowerCase()) {
|
|
982
|
-
case "text":
|
|
983
|
-
case "uuid":
|
|
984
|
-
arrowType = new apacheArrow.Utf8();
|
|
985
|
-
break;
|
|
986
|
-
case "int":
|
|
987
|
-
case "integer":
|
|
988
|
-
arrowType = new apacheArrow.Int32();
|
|
989
|
-
break;
|
|
990
|
-
case "bigint":
|
|
991
|
-
arrowType = new apacheArrow.Float64();
|
|
992
|
-
break;
|
|
993
|
-
case "float":
|
|
994
|
-
arrowType = new apacheArrow.Float32();
|
|
995
|
-
break;
|
|
996
|
-
case "jsonb":
|
|
997
|
-
case "json":
|
|
998
|
-
arrowType = new apacheArrow.Utf8();
|
|
999
|
-
break;
|
|
1000
|
-
case "binary":
|
|
1001
|
-
arrowType = new apacheArrow.Binary();
|
|
1002
|
-
break;
|
|
1003
|
-
case "timestamp":
|
|
1004
|
-
arrowType = new apacheArrow.Float64();
|
|
1005
|
-
break;
|
|
1006
|
-
default:
|
|
1007
|
-
arrowType = new apacheArrow.Utf8();
|
|
1008
|
-
}
|
|
1009
|
-
return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
|
|
1010
|
-
});
|
|
1011
|
-
return new apacheArrow.Schema(fields);
|
|
696
|
+
throw new error.MastraError(
|
|
697
|
+
{
|
|
698
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_THREAD", "FAILED"),
|
|
699
|
+
domain: error.ErrorDomain.STORAGE,
|
|
700
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
701
|
+
},
|
|
702
|
+
new Error("All retries exhausted")
|
|
703
|
+
);
|
|
1012
704
|
}
|
|
1013
|
-
async
|
|
1014
|
-
tableName,
|
|
1015
|
-
schema
|
|
1016
|
-
}) {
|
|
705
|
+
async deleteThread({ threadId }) {
|
|
1017
706
|
try {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
throw new Error("tableName is required for createTable.");
|
|
1023
|
-
}
|
|
1024
|
-
if (!schema) {
|
|
1025
|
-
throw new Error("schema is required for createTable.");
|
|
1026
|
-
}
|
|
707
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
708
|
+
await table.delete(`id = '${threadId}'`);
|
|
709
|
+
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
710
|
+
await messagesTable.delete(`thread_id = '${threadId}'`);
|
|
1027
711
|
} catch (error$1) {
|
|
1028
712
|
throw new error.MastraError(
|
|
1029
713
|
{
|
|
1030
|
-
id: "
|
|
714
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_THREAD", "FAILED"),
|
|
1031
715
|
domain: error.ErrorDomain.STORAGE,
|
|
1032
|
-
category: error.ErrorCategory.
|
|
1033
|
-
details: { tableName }
|
|
716
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1034
717
|
},
|
|
1035
718
|
error$1
|
|
1036
719
|
);
|
|
1037
720
|
}
|
|
721
|
+
}
|
|
722
|
+
normalizeMessage(message) {
|
|
723
|
+
const { thread_id, ...rest } = message;
|
|
724
|
+
return {
|
|
725
|
+
...rest,
|
|
726
|
+
threadId: thread_id,
|
|
727
|
+
content: typeof message.content === "string" ? (() => {
|
|
728
|
+
try {
|
|
729
|
+
return JSON.parse(message.content);
|
|
730
|
+
} catch {
|
|
731
|
+
return message.content;
|
|
732
|
+
}
|
|
733
|
+
})() : message.content
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
async listMessagesById({ messageIds }) {
|
|
737
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
1038
738
|
try {
|
|
1039
|
-
const
|
|
1040
|
-
|
|
739
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
740
|
+
const quotedIds = messageIds.map((id) => `'${id}'`).join(", ");
|
|
741
|
+
const allRecords = await table.query().where(`id IN (${quotedIds})`).toArray();
|
|
742
|
+
const messages = processResultWithTypeConversion(
|
|
743
|
+
allRecords,
|
|
744
|
+
await getTableSchema({ tableName: storage.TABLE_MESSAGES, client: this.client })
|
|
745
|
+
);
|
|
746
|
+
const list = new agent.MessageList().add(
|
|
747
|
+
messages.map(this.normalizeMessage),
|
|
748
|
+
"memory"
|
|
749
|
+
);
|
|
750
|
+
return { messages: list.get.all.db() };
|
|
1041
751
|
} catch (error$1) {
|
|
1042
|
-
if (error$1.message?.includes("already exists")) {
|
|
1043
|
-
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
752
|
throw new error.MastraError(
|
|
1047
753
|
{
|
|
1048
|
-
id: "
|
|
754
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
1049
755
|
domain: error.ErrorDomain.STORAGE,
|
|
1050
756
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1051
|
-
details: {
|
|
757
|
+
details: {
|
|
758
|
+
messageIds: JSON.stringify(messageIds)
|
|
759
|
+
}
|
|
1052
760
|
},
|
|
1053
761
|
error$1
|
|
1054
762
|
);
|
|
1055
763
|
}
|
|
1056
764
|
}
|
|
1057
|
-
async
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1062
|
-
if (!tableName) {
|
|
1063
|
-
throw new Error("tableName is required for dropTable.");
|
|
1064
|
-
}
|
|
1065
|
-
} catch (validationError) {
|
|
1066
|
-
throw new error.MastraError(
|
|
1067
|
-
{
|
|
1068
|
-
id: "STORAGE_LANCE_STORAGE_DROP_TABLE_INVALID_ARGS",
|
|
1069
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1070
|
-
category: error.ErrorCategory.USER,
|
|
1071
|
-
text: validationError.message,
|
|
1072
|
-
details: { tableName }
|
|
1073
|
-
},
|
|
1074
|
-
validationError
|
|
1075
|
-
);
|
|
1076
|
-
}
|
|
1077
|
-
try {
|
|
1078
|
-
await this.client.dropTable(tableName);
|
|
1079
|
-
} catch (error$1) {
|
|
1080
|
-
if (error$1.toString().includes("was not found") || error$1.message?.includes("Table not found")) {
|
|
1081
|
-
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
765
|
+
async listMessages(args) {
|
|
766
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
767
|
+
const threadIds = Array.isArray(threadId) ? threadId : [threadId];
|
|
768
|
+
if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
|
|
1084
769
|
throw new error.MastraError(
|
|
1085
770
|
{
|
|
1086
|
-
id: "
|
|
771
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
1087
772
|
domain: error.ErrorDomain.STORAGE,
|
|
1088
773
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1089
|
-
details: {
|
|
774
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
1090
775
|
},
|
|
1091
|
-
|
|
776
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
1092
777
|
);
|
|
1093
778
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
tableName,
|
|
1097
|
-
schema,
|
|
1098
|
-
ifNotExists
|
|
1099
|
-
}) {
|
|
779
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
780
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1100
781
|
try {
|
|
1101
|
-
if (
|
|
1102
|
-
throw new
|
|
782
|
+
if (page < 0) {
|
|
783
|
+
throw new error.MastraError(
|
|
784
|
+
{
|
|
785
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "INVALID_PAGE"),
|
|
786
|
+
domain: error.ErrorDomain.STORAGE,
|
|
787
|
+
category: error.ErrorCategory.USER,
|
|
788
|
+
details: { page }
|
|
789
|
+
},
|
|
790
|
+
new Error("page must be >= 0")
|
|
791
|
+
);
|
|
1103
792
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
793
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
794
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
795
|
+
const threadCondition = threadIds.length === 1 ? `thread_id = '${this.escapeSql(threadIds[0])}'` : `thread_id IN (${threadIds.map((t) => `'${this.escapeSql(t)}'`).join(", ")})`;
|
|
796
|
+
const conditions = [threadCondition];
|
|
797
|
+
if (resourceId) {
|
|
798
|
+
conditions.push(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
1106
799
|
}
|
|
1107
|
-
if (
|
|
1108
|
-
|
|
800
|
+
if (filter?.dateRange?.start) {
|
|
801
|
+
const startTime = filter.dateRange.start instanceof Date ? filter.dateRange.start.getTime() : new Date(filter.dateRange.start).getTime();
|
|
802
|
+
conditions.push(`\`createdAt\` >= ${startTime}`);
|
|
1109
803
|
}
|
|
1110
|
-
if (
|
|
1111
|
-
|
|
1112
|
-
|
|
804
|
+
if (filter?.dateRange?.end) {
|
|
805
|
+
const endTime = filter.dateRange.end instanceof Date ? filter.dateRange.end.getTime() : new Date(filter.dateRange.end).getTime();
|
|
806
|
+
conditions.push(`\`createdAt\` <= ${endTime}`);
|
|
1113
807
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
const
|
|
1130
|
-
const
|
|
1131
|
-
|
|
1132
|
-
integer: "int",
|
|
1133
|
-
bigint: "bigint",
|
|
1134
|
-
timestamp: "timestamp",
|
|
1135
|
-
jsonb: "string",
|
|
1136
|
-
uuid: "string"
|
|
1137
|
-
};
|
|
1138
|
-
const columnsToAdd = ifNotExists.filter((col) => schema[col] && !existingFields.has(col)).map((col) => {
|
|
1139
|
-
const colDef = schema[col];
|
|
808
|
+
const whereClause = conditions.join(" AND ");
|
|
809
|
+
const total = await table.countRows(whereClause);
|
|
810
|
+
const query = table.query().where(whereClause);
|
|
811
|
+
let allRecords = await query.toArray();
|
|
812
|
+
allRecords.sort((a, b) => {
|
|
813
|
+
const aValue = field === "createdAt" ? a.createdAt : a[field];
|
|
814
|
+
const bValue = field === "createdAt" ? b.createdAt : b[field];
|
|
815
|
+
if (aValue == null && bValue == null) return 0;
|
|
816
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
817
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
818
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
819
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
820
|
+
}
|
|
821
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
822
|
+
});
|
|
823
|
+
const paginatedRecords = allRecords.slice(offset, offset + perPage);
|
|
824
|
+
const messages = paginatedRecords.map((row) => this.normalizeMessage(row));
|
|
825
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
1140
826
|
return {
|
|
1141
|
-
|
|
1142
|
-
|
|
827
|
+
messages: [],
|
|
828
|
+
total: 0,
|
|
829
|
+
page,
|
|
830
|
+
perPage: perPageForResponse,
|
|
831
|
+
hasMore: false
|
|
1143
832
|
};
|
|
1144
|
-
});
|
|
1145
|
-
if (columnsToAdd.length > 0) {
|
|
1146
|
-
await table.addColumns(columnsToAdd);
|
|
1147
|
-
this.logger?.info?.(`Added columns [${columnsToAdd.map((c) => c.name).join(", ")}] to table ${tableName}`);
|
|
1148
833
|
}
|
|
834
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
835
|
+
if (include && include.length > 0) {
|
|
836
|
+
const threadIds2 = [...new Set(include.map((item) => item.threadId || threadId))];
|
|
837
|
+
const allThreadMessages = [];
|
|
838
|
+
for (const tid of threadIds2) {
|
|
839
|
+
const threadQuery = table.query().where(`thread_id = '${tid}'`);
|
|
840
|
+
let threadRecords = await threadQuery.toArray();
|
|
841
|
+
allThreadMessages.push(...threadRecords);
|
|
842
|
+
}
|
|
843
|
+
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
844
|
+
const contextMessages = this.processMessagesWithContext(allThreadMessages, include);
|
|
845
|
+
const includedMessages = contextMessages.map((row) => this.normalizeMessage(row));
|
|
846
|
+
for (const includeMsg of includedMessages) {
|
|
847
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
848
|
+
messages.push(includeMsg);
|
|
849
|
+
messageIds.add(includeMsg.id);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
854
|
+
let finalMessages = list.get.all.db();
|
|
855
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
856
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
857
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
858
|
+
if (aValue == null && bValue == null) return 0;
|
|
859
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
860
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
861
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
862
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
863
|
+
}
|
|
864
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
865
|
+
});
|
|
866
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
867
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
868
|
+
const fetchedAll = perPageInput === false || allThreadMessagesReturned;
|
|
869
|
+
const hasMore = !fetchedAll && offset + perPage < total;
|
|
870
|
+
return {
|
|
871
|
+
messages: finalMessages,
|
|
872
|
+
total,
|
|
873
|
+
page,
|
|
874
|
+
perPage: perPageForResponse,
|
|
875
|
+
hasMore
|
|
876
|
+
};
|
|
1149
877
|
} catch (error$1) {
|
|
1150
|
-
|
|
878
|
+
const mastraError = new error.MastraError(
|
|
1151
879
|
{
|
|
1152
|
-
id: "
|
|
880
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "FAILED"),
|
|
1153
881
|
domain: error.ErrorDomain.STORAGE,
|
|
1154
882
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1155
|
-
details: {
|
|
883
|
+
details: {
|
|
884
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
885
|
+
resourceId: resourceId ?? ""
|
|
886
|
+
}
|
|
1156
887
|
},
|
|
1157
888
|
error$1
|
|
1158
889
|
);
|
|
890
|
+
this.logger?.error?.(mastraError.toString());
|
|
891
|
+
this.logger?.trackException?.(mastraError);
|
|
892
|
+
return {
|
|
893
|
+
messages: [],
|
|
894
|
+
total: 0,
|
|
895
|
+
page,
|
|
896
|
+
perPage: perPageForResponse,
|
|
897
|
+
hasMore: false
|
|
898
|
+
};
|
|
1159
899
|
}
|
|
1160
900
|
}
|
|
1161
|
-
async
|
|
901
|
+
async saveMessages(args) {
|
|
1162
902
|
try {
|
|
1163
|
-
|
|
1164
|
-
|
|
903
|
+
const { messages } = args;
|
|
904
|
+
if (messages.length === 0) {
|
|
905
|
+
return { messages: [] };
|
|
1165
906
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
907
|
+
const threadId = messages[0]?.threadId;
|
|
908
|
+
if (!threadId) {
|
|
909
|
+
throw new Error("Thread ID is required");
|
|
1168
910
|
}
|
|
1169
|
-
|
|
911
|
+
for (const message of messages) {
|
|
912
|
+
if (!message.id) {
|
|
913
|
+
throw new Error("Message ID is required");
|
|
914
|
+
}
|
|
915
|
+
if (!message.threadId) {
|
|
916
|
+
throw new Error("Thread ID is required for all messages");
|
|
917
|
+
}
|
|
918
|
+
if (message.resourceId === null || message.resourceId === void 0) {
|
|
919
|
+
throw new Error("Resource ID cannot be null or undefined");
|
|
920
|
+
}
|
|
921
|
+
if (!message.content) {
|
|
922
|
+
throw new Error("Message content is required");
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
const transformedMessages = messages.map((message) => {
|
|
926
|
+
const { threadId: threadId2, type, ...rest } = message;
|
|
927
|
+
return {
|
|
928
|
+
...rest,
|
|
929
|
+
thread_id: threadId2,
|
|
930
|
+
type: type ?? "v2",
|
|
931
|
+
content: JSON.stringify(message.content)
|
|
932
|
+
};
|
|
933
|
+
});
|
|
934
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
935
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
936
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
937
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
938
|
+
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
939
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
940
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
941
|
+
return { messages: list.get.all.db() };
|
|
942
|
+
} catch (error$1) {
|
|
1170
943
|
throw new error.MastraError(
|
|
1171
944
|
{
|
|
1172
|
-
id: "
|
|
945
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_MESSAGES", "FAILED"),
|
|
1173
946
|
domain: error.ErrorDomain.STORAGE,
|
|
1174
|
-
category: error.ErrorCategory.
|
|
1175
|
-
text: validationError.message,
|
|
1176
|
-
details: { tableName }
|
|
947
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1177
948
|
},
|
|
1178
|
-
|
|
949
|
+
error$1
|
|
1179
950
|
);
|
|
1180
951
|
}
|
|
952
|
+
}
|
|
953
|
+
async listThreadsByResourceId(args) {
|
|
1181
954
|
try {
|
|
1182
|
-
const
|
|
1183
|
-
|
|
955
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
956
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
957
|
+
if (page < 0) {
|
|
958
|
+
throw new error.MastraError(
|
|
959
|
+
{
|
|
960
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
961
|
+
domain: error.ErrorDomain.STORAGE,
|
|
962
|
+
category: error.ErrorCategory.USER,
|
|
963
|
+
details: { page }
|
|
964
|
+
},
|
|
965
|
+
new Error("page must be >= 0")
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
969
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
970
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
971
|
+
const total = await table.countRows(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
972
|
+
const query = table.query().where(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
973
|
+
const records = await query.toArray();
|
|
974
|
+
records.sort((a, b) => {
|
|
975
|
+
const aValue = ["createdAt", "updatedAt"].includes(field) ? new Date(a[field]).getTime() : a[field];
|
|
976
|
+
const bValue = ["createdAt", "updatedAt"].includes(field) ? new Date(b[field]).getTime() : b[field];
|
|
977
|
+
if (aValue == null && bValue == null) return 0;
|
|
978
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
979
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
980
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
981
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
982
|
+
}
|
|
983
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
984
|
+
});
|
|
985
|
+
const paginatedRecords = records.slice(offset, offset + perPage);
|
|
986
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
987
|
+
const threads = paginatedRecords.map(
|
|
988
|
+
(record) => processResultWithTypeConversion(record, schema)
|
|
989
|
+
);
|
|
990
|
+
return {
|
|
991
|
+
threads,
|
|
992
|
+
total,
|
|
993
|
+
page,
|
|
994
|
+
perPage: perPageForResponse,
|
|
995
|
+
hasMore: offset + perPage < total
|
|
996
|
+
};
|
|
1184
997
|
} catch (error$1) {
|
|
1185
998
|
throw new error.MastraError(
|
|
1186
999
|
{
|
|
1187
|
-
id: "
|
|
1000
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
|
|
1188
1001
|
domain: error.ErrorDomain.STORAGE,
|
|
1189
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1190
|
-
details: { tableName }
|
|
1002
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1191
1003
|
},
|
|
1192
1004
|
error$1
|
|
1193
1005
|
);
|
|
1194
1006
|
}
|
|
1195
1007
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1008
|
+
/**
|
|
1009
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
1010
|
+
* @param records - The sorted array of records to process
|
|
1011
|
+
* @param include - The array of include specifications with context parameters
|
|
1012
|
+
* @returns The processed array with context messages included
|
|
1013
|
+
*/
|
|
1014
|
+
processMessagesWithContext(records, include) {
|
|
1015
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
1016
|
+
if (messagesWithContext.length === 0) {
|
|
1017
|
+
return records;
|
|
1018
|
+
}
|
|
1019
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
1020
|
+
records.forEach((message, index) => {
|
|
1021
|
+
messageIndexMap.set(message.id, index);
|
|
1022
|
+
});
|
|
1023
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
1024
|
+
for (const item of messagesWithContext) {
|
|
1025
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
1026
|
+
if (messageIndex !== void 0) {
|
|
1027
|
+
if (item.withPreviousMessages) {
|
|
1028
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
1029
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
1030
|
+
additionalIndices.add(i);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
if (item.withNextMessages) {
|
|
1034
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
1035
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
1036
|
+
additionalIndices.add(i);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1203
1039
|
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1040
|
+
}
|
|
1041
|
+
if (additionalIndices.size === 0) {
|
|
1042
|
+
return records;
|
|
1043
|
+
}
|
|
1044
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
1045
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
1046
|
+
records.forEach((record, index) => {
|
|
1047
|
+
if (originalMatchIds.has(record.id)) {
|
|
1048
|
+
allIndices.add(index);
|
|
1206
1049
|
}
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1050
|
+
});
|
|
1051
|
+
additionalIndices.forEach((index) => {
|
|
1052
|
+
allIndices.add(index);
|
|
1053
|
+
});
|
|
1054
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Parse message data from LanceDB record format to MastraDBMessage format
|
|
1058
|
+
*/
|
|
1059
|
+
parseMessageData(data) {
|
|
1060
|
+
const { thread_id, ...rest } = data;
|
|
1061
|
+
return {
|
|
1062
|
+
...rest,
|
|
1063
|
+
threadId: thread_id,
|
|
1064
|
+
content: typeof data.content === "string" ? (() => {
|
|
1065
|
+
try {
|
|
1066
|
+
return JSON.parse(data.content);
|
|
1067
|
+
} catch {
|
|
1068
|
+
return data.content;
|
|
1069
|
+
}
|
|
1070
|
+
})() : data.content,
|
|
1071
|
+
createdAt: new Date(data.createdAt),
|
|
1072
|
+
updatedAt: new Date(data.updatedAt)
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
async updateMessages(args) {
|
|
1076
|
+
const { messages } = args;
|
|
1077
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
1078
|
+
if (!messages.length) {
|
|
1079
|
+
return [];
|
|
1218
1080
|
}
|
|
1081
|
+
const updatedMessages = [];
|
|
1082
|
+
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
1219
1083
|
try {
|
|
1220
|
-
const
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1084
|
+
for (const updateData of messages) {
|
|
1085
|
+
const { id, ...updates } = updateData;
|
|
1086
|
+
const existingMessage = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
1087
|
+
if (!existingMessage) {
|
|
1088
|
+
this.logger.warn("Message not found for update", { id });
|
|
1089
|
+
continue;
|
|
1090
|
+
}
|
|
1091
|
+
const existingMsg = this.parseMessageData(existingMessage);
|
|
1092
|
+
const originalThreadId = existingMsg.threadId;
|
|
1093
|
+
affectedThreadIds.add(originalThreadId);
|
|
1094
|
+
const updatePayload = {};
|
|
1095
|
+
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
1096
|
+
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
1097
|
+
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
1098
|
+
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
1099
|
+
updatePayload.thread_id = updates.threadId;
|
|
1100
|
+
affectedThreadIds.add(updates.threadId);
|
|
1101
|
+
}
|
|
1102
|
+
if (updates.content) {
|
|
1103
|
+
const existingContent = existingMsg.content;
|
|
1104
|
+
let newContent = { ...existingContent };
|
|
1105
|
+
if (updates.content.metadata !== void 0) {
|
|
1106
|
+
newContent.metadata = {
|
|
1107
|
+
...existingContent.metadata || {},
|
|
1108
|
+
...updates.content.metadata || {}
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
if (updates.content.content !== void 0) {
|
|
1112
|
+
newContent.content = updates.content.content;
|
|
1113
|
+
}
|
|
1114
|
+
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
1115
|
+
newContent.parts = updates.content.parts;
|
|
1116
|
+
}
|
|
1117
|
+
updatePayload.content = JSON.stringify(newContent);
|
|
1118
|
+
}
|
|
1119
|
+
await this.#db.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
1120
|
+
const updatedMessage = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
1121
|
+
if (updatedMessage) {
|
|
1122
|
+
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
1227
1123
|
}
|
|
1228
1124
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1125
|
+
for (const threadId of affectedThreadIds) {
|
|
1126
|
+
await this.#db.insert({
|
|
1127
|
+
tableName: storage.TABLE_THREADS,
|
|
1128
|
+
record: { id: threadId, updatedAt: Date.now() }
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
return updatedMessages;
|
|
1231
1132
|
} catch (error$1) {
|
|
1232
1133
|
throw new error.MastraError(
|
|
1233
1134
|
{
|
|
1234
|
-
id: "
|
|
1135
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_MESSAGES", "FAILED"),
|
|
1235
1136
|
domain: error.ErrorDomain.STORAGE,
|
|
1236
1137
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1237
|
-
details: {
|
|
1138
|
+
details: { count: messages.length }
|
|
1238
1139
|
},
|
|
1239
1140
|
error$1
|
|
1240
1141
|
);
|
|
1241
1142
|
}
|
|
1242
1143
|
}
|
|
1243
|
-
async
|
|
1144
|
+
async getResourceById({ resourceId }) {
|
|
1244
1145
|
try {
|
|
1245
|
-
|
|
1246
|
-
|
|
1146
|
+
const resource = await this.#db.load({ tableName: storage.TABLE_RESOURCES, keys: { id: resourceId } });
|
|
1147
|
+
if (!resource) {
|
|
1148
|
+
return null;
|
|
1247
1149
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1150
|
+
let createdAt;
|
|
1151
|
+
let updatedAt;
|
|
1152
|
+
try {
|
|
1153
|
+
if (resource.createdAt instanceof Date) {
|
|
1154
|
+
createdAt = resource.createdAt;
|
|
1155
|
+
} else if (typeof resource.createdAt === "string") {
|
|
1156
|
+
createdAt = new Date(resource.createdAt);
|
|
1157
|
+
} else if (typeof resource.createdAt === "number") {
|
|
1158
|
+
createdAt = new Date(resource.createdAt);
|
|
1159
|
+
} else {
|
|
1160
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1161
|
+
}
|
|
1162
|
+
if (isNaN(createdAt.getTime())) {
|
|
1163
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1164
|
+
}
|
|
1165
|
+
} catch {
|
|
1166
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1250
1167
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1168
|
+
try {
|
|
1169
|
+
if (resource.updatedAt instanceof Date) {
|
|
1170
|
+
updatedAt = resource.updatedAt;
|
|
1171
|
+
} else if (typeof resource.updatedAt === "string") {
|
|
1172
|
+
updatedAt = new Date(resource.updatedAt);
|
|
1173
|
+
} else if (typeof resource.updatedAt === "number") {
|
|
1174
|
+
updatedAt = new Date(resource.updatedAt);
|
|
1175
|
+
} else {
|
|
1176
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1177
|
+
}
|
|
1178
|
+
if (isNaN(updatedAt.getTime())) {
|
|
1179
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1180
|
+
}
|
|
1181
|
+
} catch {
|
|
1182
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1183
|
+
}
|
|
1184
|
+
let workingMemory = resource.workingMemory;
|
|
1185
|
+
if (workingMemory === null || workingMemory === void 0) {
|
|
1186
|
+
workingMemory = void 0;
|
|
1187
|
+
} else if (workingMemory === "") {
|
|
1188
|
+
workingMemory = "";
|
|
1189
|
+
} else if (typeof workingMemory === "object") {
|
|
1190
|
+
workingMemory = JSON.stringify(workingMemory);
|
|
1191
|
+
}
|
|
1192
|
+
let metadata = resource.metadata;
|
|
1193
|
+
if (metadata === "" || metadata === null || metadata === void 0) {
|
|
1194
|
+
metadata = void 0;
|
|
1195
|
+
} else if (typeof metadata === "string") {
|
|
1196
|
+
try {
|
|
1197
|
+
metadata = JSON.parse(metadata);
|
|
1198
|
+
} catch {
|
|
1199
|
+
metadata = metadata;
|
|
1200
|
+
}
|
|
1253
1201
|
}
|
|
1254
|
-
|
|
1202
|
+
return {
|
|
1203
|
+
...resource,
|
|
1204
|
+
createdAt,
|
|
1205
|
+
updatedAt,
|
|
1206
|
+
workingMemory,
|
|
1207
|
+
metadata
|
|
1208
|
+
};
|
|
1209
|
+
} catch (error$1) {
|
|
1255
1210
|
throw new error.MastraError(
|
|
1256
1211
|
{
|
|
1257
|
-
id: "
|
|
1212
|
+
id: storage.createStorageErrorId("LANCE", "GET_RESOURCE_BY_ID", "FAILED"),
|
|
1258
1213
|
domain: error.ErrorDomain.STORAGE,
|
|
1259
|
-
category: error.ErrorCategory.
|
|
1260
|
-
text: validationError.message,
|
|
1261
|
-
details: { tableName }
|
|
1214
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1262
1215
|
},
|
|
1263
|
-
|
|
1216
|
+
error$1
|
|
1264
1217
|
);
|
|
1265
1218
|
}
|
|
1219
|
+
}
|
|
1220
|
+
async saveResource({ resource }) {
|
|
1266
1221
|
try {
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
});
|
|
1279
|
-
console.log(processedRecords);
|
|
1280
|
-
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(processedRecords);
|
|
1222
|
+
const record = {
|
|
1223
|
+
...resource,
|
|
1224
|
+
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
1225
|
+
createdAt: resource.createdAt.getTime(),
|
|
1226
|
+
// Store as timestamp (milliseconds)
|
|
1227
|
+
updatedAt: resource.updatedAt.getTime()
|
|
1228
|
+
// Store as timestamp (milliseconds)
|
|
1229
|
+
};
|
|
1230
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
1231
|
+
await table.add([record], { mode: "append" });
|
|
1232
|
+
return resource;
|
|
1281
1233
|
} catch (error$1) {
|
|
1282
1234
|
throw new error.MastraError(
|
|
1283
1235
|
{
|
|
1284
|
-
id: "
|
|
1236
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_RESOURCE", "FAILED"),
|
|
1285
1237
|
domain: error.ErrorDomain.STORAGE,
|
|
1286
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1287
|
-
details: { tableName }
|
|
1238
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1288
1239
|
},
|
|
1289
1240
|
error$1
|
|
1290
1241
|
);
|
|
1291
1242
|
}
|
|
1292
1243
|
}
|
|
1293
|
-
async
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1244
|
+
async updateResource({
|
|
1245
|
+
resourceId,
|
|
1246
|
+
workingMemory,
|
|
1247
|
+
metadata
|
|
1248
|
+
}) {
|
|
1249
|
+
const maxRetries = 3;
|
|
1250
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1251
|
+
try {
|
|
1252
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
1253
|
+
if (!existingResource) {
|
|
1254
|
+
const newResource = {
|
|
1255
|
+
id: resourceId,
|
|
1256
|
+
workingMemory,
|
|
1257
|
+
metadata: metadata || {},
|
|
1258
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1259
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1260
|
+
};
|
|
1261
|
+
return this.saveResource({ resource: newResource });
|
|
1262
|
+
}
|
|
1263
|
+
const updatedResource = {
|
|
1264
|
+
...existingResource,
|
|
1265
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
1266
|
+
metadata: {
|
|
1267
|
+
...existingResource.metadata,
|
|
1268
|
+
...metadata
|
|
1269
|
+
},
|
|
1270
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1271
|
+
};
|
|
1272
|
+
const record = {
|
|
1273
|
+
id: resourceId,
|
|
1274
|
+
workingMemory: updatedResource.workingMemory || "",
|
|
1275
|
+
metadata: updatedResource.metadata ? JSON.stringify(updatedResource.metadata) : "",
|
|
1276
|
+
updatedAt: updatedResource.updatedAt.getTime()
|
|
1277
|
+
// Store as timestamp (milliseconds)
|
|
1278
|
+
};
|
|
1279
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
1280
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1281
|
+
return updatedResource;
|
|
1282
|
+
} catch (error$1) {
|
|
1283
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
1284
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
1285
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1286
|
+
continue;
|
|
1287
|
+
}
|
|
1288
|
+
throw new error.MastraError(
|
|
1289
|
+
{
|
|
1290
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_RESOURCE", "FAILED"),
|
|
1291
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1292
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1293
|
+
},
|
|
1294
|
+
error$1
|
|
1295
|
+
);
|
|
1303
1296
|
}
|
|
1304
|
-
} catch (validationError) {
|
|
1305
|
-
throw new error.MastraError(
|
|
1306
|
-
{
|
|
1307
|
-
id: "STORAGE_LANCE_STORAGE_LOAD_INVALID_ARGS",
|
|
1308
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1309
|
-
category: error.ErrorCategory.USER,
|
|
1310
|
-
text: validationError.message,
|
|
1311
|
-
details: { tableName }
|
|
1312
|
-
},
|
|
1313
|
-
validationError
|
|
1314
|
-
);
|
|
1315
1297
|
}
|
|
1298
|
+
throw new Error("Unexpected end of retry loop");
|
|
1299
|
+
}
|
|
1300
|
+
};
|
|
1301
|
+
var StoreScoresLance = class extends storage.ScoresStorage {
|
|
1302
|
+
client;
|
|
1303
|
+
#db;
|
|
1304
|
+
constructor(config) {
|
|
1305
|
+
super();
|
|
1306
|
+
const client = resolveLanceConfig(config);
|
|
1307
|
+
this.client = client;
|
|
1308
|
+
this.#db = new LanceDB({ client });
|
|
1309
|
+
}
|
|
1310
|
+
async init() {
|
|
1311
|
+
await this.#db.createTable({ tableName: storage.TABLE_SCORERS, schema: storage.SCORERS_SCHEMA });
|
|
1312
|
+
await this.#db.alterTable({
|
|
1313
|
+
tableName: storage.TABLE_SCORERS,
|
|
1314
|
+
schema: storage.SCORERS_SCHEMA,
|
|
1315
|
+
ifNotExists: ["spanId", "requestContext"]
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
async dangerouslyClearAll() {
|
|
1319
|
+
await this.#db.clearTable({ tableName: storage.TABLE_SCORERS });
|
|
1320
|
+
}
|
|
1321
|
+
async saveScore(score) {
|
|
1322
|
+
let validatedScore;
|
|
1316
1323
|
try {
|
|
1317
|
-
|
|
1318
|
-
const tableSchema = await getTableSchema({ tableName, client: this.client });
|
|
1319
|
-
const query = table.query();
|
|
1320
|
-
if (Object.keys(keys).length > 0) {
|
|
1321
|
-
validateKeyTypes(keys, tableSchema);
|
|
1322
|
-
const filterConditions = Object.entries(keys).map(([key, value]) => {
|
|
1323
|
-
const isCamelCase = /^[a-z][a-zA-Z]*$/.test(key) && /[A-Z]/.test(key);
|
|
1324
|
-
const quotedKey = isCamelCase ? `\`${key}\`` : key;
|
|
1325
|
-
if (typeof value === "string") {
|
|
1326
|
-
return `${quotedKey} = '${value}'`;
|
|
1327
|
-
} else if (value === null) {
|
|
1328
|
-
return `${quotedKey} IS NULL`;
|
|
1329
|
-
} else {
|
|
1330
|
-
return `${quotedKey} = ${value}`;
|
|
1331
|
-
}
|
|
1332
|
-
}).join(" AND ");
|
|
1333
|
-
this.logger.debug("where clause generated: " + filterConditions);
|
|
1334
|
-
query.where(filterConditions);
|
|
1335
|
-
}
|
|
1336
|
-
const result = await query.limit(1).toArray();
|
|
1337
|
-
if (result.length === 0) {
|
|
1338
|
-
this.logger.debug("No record found");
|
|
1339
|
-
return null;
|
|
1340
|
-
}
|
|
1341
|
-
return processResultWithTypeConversion(result[0], tableSchema);
|
|
1324
|
+
validatedScore = evals.saveScorePayloadSchema.parse(score);
|
|
1342
1325
|
} catch (error$1) {
|
|
1343
|
-
if (error$1 instanceof error.MastraError) throw error$1;
|
|
1344
1326
|
throw new error.MastraError(
|
|
1345
1327
|
{
|
|
1346
|
-
id: "
|
|
1328
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_SCORE", "VALIDATION_FAILED"),
|
|
1329
|
+
text: "Failed to save score in LanceStorage",
|
|
1347
1330
|
domain: error.ErrorDomain.STORAGE,
|
|
1348
|
-
category: error.ErrorCategory.
|
|
1349
|
-
details: {
|
|
1331
|
+
category: error.ErrorCategory.USER,
|
|
1332
|
+
details: {
|
|
1333
|
+
scorer: score.scorer?.id ?? "unknown",
|
|
1334
|
+
entityId: score.entityId ?? "unknown",
|
|
1335
|
+
entityType: score.entityType ?? "unknown",
|
|
1336
|
+
traceId: score.traceId ?? "",
|
|
1337
|
+
spanId: score.spanId ?? ""
|
|
1338
|
+
}
|
|
1350
1339
|
},
|
|
1351
1340
|
error$1
|
|
1352
1341
|
);
|
|
1353
1342
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
var StoreScoresLance = class extends storage.ScoresStorage {
|
|
1357
|
-
client;
|
|
1358
|
-
constructor({ client }) {
|
|
1359
|
-
super();
|
|
1360
|
-
this.client = client;
|
|
1361
|
-
}
|
|
1362
|
-
async saveScore(score) {
|
|
1343
|
+
const id = crypto.randomUUID();
|
|
1344
|
+
const now = /* @__PURE__ */ new Date();
|
|
1363
1345
|
try {
|
|
1364
1346
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1365
1347
|
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1366
1348
|
const allowedFields = new Set(schema.fields.map((f) => f.name));
|
|
1367
1349
|
const filteredScore = {};
|
|
1368
|
-
Object.keys(
|
|
1350
|
+
for (const key of Object.keys(validatedScore)) {
|
|
1369
1351
|
if (allowedFields.has(key)) {
|
|
1370
|
-
filteredScore[key] =
|
|
1352
|
+
filteredScore[key] = validatedScore[key];
|
|
1371
1353
|
}
|
|
1372
|
-
}
|
|
1354
|
+
}
|
|
1373
1355
|
for (const key in filteredScore) {
|
|
1374
1356
|
if (filteredScore[key] !== null && typeof filteredScore[key] === "object" && !(filteredScore[key] instanceof Date)) {
|
|
1375
1357
|
filteredScore[key] = JSON.stringify(filteredScore[key]);
|
|
1376
1358
|
}
|
|
1377
1359
|
}
|
|
1378
|
-
|
|
1360
|
+
filteredScore.id = id;
|
|
1361
|
+
filteredScore.createdAt = now;
|
|
1362
|
+
filteredScore.updatedAt = now;
|
|
1379
1363
|
await table.add([filteredScore], { mode: "append" });
|
|
1380
|
-
return { score };
|
|
1364
|
+
return { score: { ...validatedScore, id, createdAt: now, updatedAt: now } };
|
|
1381
1365
|
} catch (error$1) {
|
|
1382
1366
|
throw new error.MastraError(
|
|
1383
1367
|
{
|
|
1384
|
-
id: "
|
|
1368
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_SCORE", "FAILED"),
|
|
1385
1369
|
text: "Failed to save score in LanceStorage",
|
|
1386
1370
|
domain: error.ErrorDomain.STORAGE,
|
|
1387
1371
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1397,12 +1381,11 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1397
1381
|
const query = table.query().where(`id = '${id}'`).limit(1);
|
|
1398
1382
|
const records = await query.toArray();
|
|
1399
1383
|
if (records.length === 0) return null;
|
|
1400
|
-
|
|
1401
|
-
return processResultWithTypeConversion(records[0], schema);
|
|
1384
|
+
return await this.transformScoreRow(records[0]);
|
|
1402
1385
|
} catch (error$1) {
|
|
1403
1386
|
throw new error.MastraError(
|
|
1404
1387
|
{
|
|
1405
|
-
id: "
|
|
1388
|
+
id: storage.createStorageErrorId("LANCE", "GET_SCORE_BY_ID", "FAILED"),
|
|
1406
1389
|
text: "Failed to get score by id in LanceStorage",
|
|
1407
1390
|
domain: error.ErrorDomain.STORAGE,
|
|
1408
1391
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1412,34 +1395,76 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1412
1395
|
);
|
|
1413
1396
|
}
|
|
1414
1397
|
}
|
|
1415
|
-
|
|
1398
|
+
/**
|
|
1399
|
+
* LanceDB-specific score row transformation.
|
|
1400
|
+
*
|
|
1401
|
+
* Note: This implementation does NOT use coreTransformScoreRow because:
|
|
1402
|
+
* 1. LanceDB stores schema information in the table itself (requires async fetch)
|
|
1403
|
+
* 2. Uses processResultWithTypeConversion utility for LanceDB-specific type handling
|
|
1404
|
+
*/
|
|
1405
|
+
async transformScoreRow(row) {
|
|
1406
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1407
|
+
const transformed = processResultWithTypeConversion(row, schema);
|
|
1408
|
+
return {
|
|
1409
|
+
...transformed,
|
|
1410
|
+
createdAt: row.createdAt,
|
|
1411
|
+
updatedAt: row.updatedAt
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
async listScoresByScorerId({
|
|
1416
1415
|
scorerId,
|
|
1417
|
-
pagination
|
|
1416
|
+
pagination,
|
|
1417
|
+
entityId,
|
|
1418
|
+
entityType,
|
|
1419
|
+
source
|
|
1418
1420
|
}) {
|
|
1419
1421
|
try {
|
|
1422
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1423
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1424
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1420
1425
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1426
|
+
let query = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1427
|
+
if (source) {
|
|
1428
|
+
query = query.where(`\`source\` = '${source}'`);
|
|
1429
|
+
}
|
|
1430
|
+
if (entityId) {
|
|
1431
|
+
query = query.where(`\`entityId\` = '${entityId}'`);
|
|
1432
|
+
}
|
|
1433
|
+
if (entityType) {
|
|
1434
|
+
query = query.where(`\`entityType\` = '${entityType}'`);
|
|
1435
|
+
}
|
|
1436
|
+
let totalQuery = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1437
|
+
if (source) {
|
|
1438
|
+
totalQuery = totalQuery.where(`\`source\` = '${source}'`);
|
|
1439
|
+
}
|
|
1440
|
+
if (entityId) {
|
|
1441
|
+
totalQuery = totalQuery.where(`\`entityId\` = '${entityId}'`);
|
|
1442
|
+
}
|
|
1443
|
+
if (entityType) {
|
|
1444
|
+
totalQuery = totalQuery.where(`\`entityType\` = '${entityType}'`);
|
|
1445
|
+
}
|
|
1446
|
+
const allRecords = await totalQuery.toArray();
|
|
1429
1447
|
const total = allRecords.length;
|
|
1448
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1449
|
+
if (perPageInput !== false) {
|
|
1450
|
+
query = query.limit(perPage);
|
|
1451
|
+
if (start > 0) query = query.offset(start);
|
|
1452
|
+
}
|
|
1453
|
+
const records = await query.toArray();
|
|
1454
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1430
1455
|
return {
|
|
1431
1456
|
pagination: {
|
|
1432
1457
|
page,
|
|
1433
|
-
perPage,
|
|
1458
|
+
perPage: perPageForResponse,
|
|
1434
1459
|
total,
|
|
1435
|
-
hasMore:
|
|
1460
|
+
hasMore: end < total
|
|
1436
1461
|
},
|
|
1437
1462
|
scores
|
|
1438
1463
|
};
|
|
1439
1464
|
} catch (error$1) {
|
|
1440
1465
|
throw new error.MastraError(
|
|
1441
1466
|
{
|
|
1442
|
-
id: "
|
|
1467
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
|
|
1443
1468
|
text: "Failed to get scores by scorerId in LanceStorage",
|
|
1444
1469
|
domain: error.ErrorDomain.STORAGE,
|
|
1445
1470
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1449,274 +1474,135 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1449
1474
|
);
|
|
1450
1475
|
}
|
|
1451
1476
|
}
|
|
1452
|
-
async
|
|
1477
|
+
async listScoresByRunId({
|
|
1453
1478
|
runId,
|
|
1454
1479
|
pagination
|
|
1455
1480
|
}) {
|
|
1456
1481
|
try {
|
|
1482
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1483
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1484
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1457
1485
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1458
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1459
|
-
const offset = page * perPage;
|
|
1460
|
-
const query = table.query().where(`\`runId\` = '${runId}'`).limit(perPage);
|
|
1461
|
-
if (offset > 0) query.offset(offset);
|
|
1462
|
-
const records = await query.toArray();
|
|
1463
|
-
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1464
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1465
1486
|
const allRecords = await table.query().where(`\`runId\` = '${runId}'`).toArray();
|
|
1466
1487
|
const total = allRecords.length;
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
},
|
|
1474
|
-
scores
|
|
1475
|
-
};
|
|
1476
|
-
} catch (error$1) {
|
|
1477
|
-
throw new error.MastraError(
|
|
1478
|
-
{
|
|
1479
|
-
id: "LANCE_STORAGE_GET_SCORES_BY_RUN_ID_FAILED",
|
|
1480
|
-
text: "Failed to get scores by runId in LanceStorage",
|
|
1481
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1482
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1483
|
-
details: { error: error$1?.message }
|
|
1484
|
-
},
|
|
1485
|
-
error$1
|
|
1486
|
-
);
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
async getScoresByEntityId({
|
|
1490
|
-
entityId,
|
|
1491
|
-
entityType,
|
|
1492
|
-
pagination
|
|
1493
|
-
}) {
|
|
1494
|
-
try {
|
|
1495
|
-
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1496
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1497
|
-
const offset = page * perPage;
|
|
1498
|
-
const query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).limit(perPage);
|
|
1499
|
-
if (offset > 0) query.offset(offset);
|
|
1488
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1489
|
+
let query = table.query().where(`\`runId\` = '${runId}'`);
|
|
1490
|
+
if (perPageInput !== false) {
|
|
1491
|
+
query = query.limit(perPage);
|
|
1492
|
+
if (start > 0) query = query.offset(start);
|
|
1493
|
+
}
|
|
1500
1494
|
const records = await query.toArray();
|
|
1501
|
-
const
|
|
1502
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1503
|
-
const allRecords = await table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).toArray();
|
|
1504
|
-
const total = allRecords.length;
|
|
1495
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1505
1496
|
return {
|
|
1506
1497
|
pagination: {
|
|
1507
1498
|
page,
|
|
1508
|
-
perPage,
|
|
1499
|
+
perPage: perPageForResponse,
|
|
1509
1500
|
total,
|
|
1510
|
-
hasMore:
|
|
1501
|
+
hasMore: end < total
|
|
1511
1502
|
},
|
|
1512
1503
|
scores
|
|
1513
|
-
};
|
|
1514
|
-
} catch (error$1) {
|
|
1515
|
-
throw new error.MastraError(
|
|
1516
|
-
{
|
|
1517
|
-
id: "LANCE_STORAGE_GET_SCORES_BY_ENTITY_ID_FAILED",
|
|
1518
|
-
text: "Failed to get scores by entityId and entityType in LanceStorage",
|
|
1519
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1520
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1521
|
-
details: { error: error$1?.message }
|
|
1522
|
-
},
|
|
1523
|
-
error$1
|
|
1524
|
-
);
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
};
|
|
1528
|
-
var StoreTracesLance = class extends storage.TracesStorage {
|
|
1529
|
-
client;
|
|
1530
|
-
operations;
|
|
1531
|
-
constructor({ client, operations }) {
|
|
1532
|
-
super();
|
|
1533
|
-
this.client = client;
|
|
1534
|
-
this.operations = operations;
|
|
1535
|
-
}
|
|
1536
|
-
async saveTrace({ trace }) {
|
|
1537
|
-
try {
|
|
1538
|
-
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
1539
|
-
const record = {
|
|
1540
|
-
...trace,
|
|
1541
|
-
attributes: JSON.stringify(trace.attributes),
|
|
1542
|
-
status: JSON.stringify(trace.status),
|
|
1543
|
-
events: JSON.stringify(trace.events),
|
|
1544
|
-
links: JSON.stringify(trace.links),
|
|
1545
|
-
other: JSON.stringify(trace.other)
|
|
1546
|
-
};
|
|
1547
|
-
await table.add([record], { mode: "append" });
|
|
1548
|
-
return trace;
|
|
1549
|
-
} catch (error$1) {
|
|
1550
|
-
throw new error.MastraError(
|
|
1551
|
-
{
|
|
1552
|
-
id: "LANCE_STORE_SAVE_TRACE_FAILED",
|
|
1553
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1554
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1555
|
-
},
|
|
1556
|
-
error$1
|
|
1557
|
-
);
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
async getTraceById({ traceId }) {
|
|
1561
|
-
try {
|
|
1562
|
-
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
1563
|
-
const query = table.query().where(`id = '${traceId}'`);
|
|
1564
|
-
const records = await query.toArray();
|
|
1565
|
-
return records[0];
|
|
1504
|
+
};
|
|
1566
1505
|
} catch (error$1) {
|
|
1567
1506
|
throw new error.MastraError(
|
|
1568
1507
|
{
|
|
1569
|
-
id: "
|
|
1508
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_RUN_ID", "FAILED"),
|
|
1509
|
+
text: "Failed to get scores by runId in LanceStorage",
|
|
1570
1510
|
domain: error.ErrorDomain.STORAGE,
|
|
1571
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1511
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1512
|
+
details: { error: error$1?.message }
|
|
1572
1513
|
},
|
|
1573
1514
|
error$1
|
|
1574
1515
|
);
|
|
1575
1516
|
}
|
|
1576
1517
|
}
|
|
1577
|
-
async
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
perPage = 10,
|
|
1582
|
-
attributes
|
|
1518
|
+
async listScoresByEntityId({
|
|
1519
|
+
entityId,
|
|
1520
|
+
entityType,
|
|
1521
|
+
pagination
|
|
1583
1522
|
}) {
|
|
1584
1523
|
try {
|
|
1585
|
-
const
|
|
1586
|
-
const
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
}
|
|
1593
|
-
if (
|
|
1594
|
-
query
|
|
1595
|
-
|
|
1596
|
-
const offset = (page - 1) * perPage;
|
|
1597
|
-
query.limit(perPage);
|
|
1598
|
-
if (offset > 0) {
|
|
1599
|
-
query.offset(offset);
|
|
1524
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1525
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1526
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1527
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1528
|
+
const allRecords = await table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).toArray();
|
|
1529
|
+
const total = allRecords.length;
|
|
1530
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1531
|
+
let query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`);
|
|
1532
|
+
if (perPageInput !== false) {
|
|
1533
|
+
query = query.limit(perPage);
|
|
1534
|
+
if (start > 0) query = query.offset(start);
|
|
1600
1535
|
}
|
|
1601
1536
|
const records = await query.toArray();
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
createdAt: new Date(record.createdAt)
|
|
1613
|
-
};
|
|
1614
|
-
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1615
|
-
processed.parentSpanId = "";
|
|
1616
|
-
} else {
|
|
1617
|
-
processed.parentSpanId = String(processed.parentSpanId);
|
|
1618
|
-
}
|
|
1619
|
-
return processed;
|
|
1620
|
-
});
|
|
1537
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1538
|
+
return {
|
|
1539
|
+
pagination: {
|
|
1540
|
+
page,
|
|
1541
|
+
perPage: perPageForResponse,
|
|
1542
|
+
total,
|
|
1543
|
+
hasMore: end < total
|
|
1544
|
+
},
|
|
1545
|
+
scores
|
|
1546
|
+
};
|
|
1621
1547
|
} catch (error$1) {
|
|
1622
1548
|
throw new error.MastraError(
|
|
1623
1549
|
{
|
|
1624
|
-
id: "
|
|
1550
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
|
|
1551
|
+
text: "Failed to get scores by entityId and entityType in LanceStorage",
|
|
1625
1552
|
domain: error.ErrorDomain.STORAGE,
|
|
1626
1553
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1627
|
-
details: {
|
|
1554
|
+
details: { error: error$1?.message }
|
|
1628
1555
|
},
|
|
1629
1556
|
error$1
|
|
1630
1557
|
);
|
|
1631
1558
|
}
|
|
1632
1559
|
}
|
|
1633
|
-
async
|
|
1560
|
+
async listScoresBySpan({
|
|
1561
|
+
traceId,
|
|
1562
|
+
spanId,
|
|
1563
|
+
pagination
|
|
1564
|
+
}) {
|
|
1634
1565
|
try {
|
|
1635
|
-
const
|
|
1636
|
-
const
|
|
1637
|
-
const
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
conditions.push(`attributes LIKE '%${attributesStr.replace(/"/g, '\\"')}%'`);
|
|
1647
|
-
}
|
|
1648
|
-
if (args.dateRange?.start) {
|
|
1649
|
-
conditions.push(`\`createdAt\` >= ${args.dateRange.start.getTime()}`);
|
|
1650
|
-
}
|
|
1651
|
-
if (args.dateRange?.end) {
|
|
1652
|
-
conditions.push(`\`createdAt\` <= ${args.dateRange.end.getTime()}`);
|
|
1653
|
-
}
|
|
1654
|
-
if (conditions.length > 0) {
|
|
1655
|
-
const whereClause = conditions.join(" AND ");
|
|
1656
|
-
query.where(whereClause);
|
|
1657
|
-
}
|
|
1658
|
-
let total = 0;
|
|
1659
|
-
if (conditions.length > 0) {
|
|
1660
|
-
const countQuery = table.query().where(conditions.join(" AND "));
|
|
1661
|
-
const allRecords = await countQuery.toArray();
|
|
1662
|
-
total = allRecords.length;
|
|
1663
|
-
} else {
|
|
1664
|
-
total = await table.countRows();
|
|
1665
|
-
}
|
|
1666
|
-
const page = args.page || 0;
|
|
1667
|
-
const perPage = args.perPage || 10;
|
|
1668
|
-
const offset = page * perPage;
|
|
1669
|
-
query.limit(perPage);
|
|
1670
|
-
if (offset > 0) {
|
|
1671
|
-
query.offset(offset);
|
|
1566
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1567
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1568
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1569
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1570
|
+
const allRecords = await table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`).toArray();
|
|
1571
|
+
const total = allRecords.length;
|
|
1572
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1573
|
+
let query = table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`);
|
|
1574
|
+
if (perPageInput !== false) {
|
|
1575
|
+
query = query.limit(perPage);
|
|
1576
|
+
if (start > 0) query = query.offset(start);
|
|
1672
1577
|
}
|
|
1673
1578
|
const records = await query.toArray();
|
|
1674
|
-
const
|
|
1675
|
-
const processed = {
|
|
1676
|
-
...record,
|
|
1677
|
-
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1678
|
-
status: record.status ? JSON.parse(record.status) : {},
|
|
1679
|
-
events: record.events ? JSON.parse(record.events) : [],
|
|
1680
|
-
links: record.links ? JSON.parse(record.links) : [],
|
|
1681
|
-
other: record.other ? JSON.parse(record.other) : {},
|
|
1682
|
-
startTime: new Date(record.startTime),
|
|
1683
|
-
endTime: new Date(record.endTime),
|
|
1684
|
-
createdAt: new Date(record.createdAt)
|
|
1685
|
-
};
|
|
1686
|
-
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1687
|
-
processed.parentSpanId = "";
|
|
1688
|
-
} else {
|
|
1689
|
-
processed.parentSpanId = String(processed.parentSpanId);
|
|
1690
|
-
}
|
|
1691
|
-
return processed;
|
|
1692
|
-
});
|
|
1579
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1693
1580
|
return {
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1581
|
+
pagination: {
|
|
1582
|
+
page,
|
|
1583
|
+
perPage: perPageForResponse,
|
|
1584
|
+
total,
|
|
1585
|
+
hasMore: end < total
|
|
1586
|
+
},
|
|
1587
|
+
scores
|
|
1699
1588
|
};
|
|
1700
1589
|
} catch (error$1) {
|
|
1701
1590
|
throw new error.MastraError(
|
|
1702
1591
|
{
|
|
1703
|
-
id: "
|
|
1592
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_SPAN", "FAILED"),
|
|
1593
|
+
text: "Failed to get scores by traceId and spanId in LanceStorage",
|
|
1704
1594
|
domain: error.ErrorDomain.STORAGE,
|
|
1705
1595
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1706
|
-
details: {
|
|
1596
|
+
details: { error: error$1?.message }
|
|
1707
1597
|
},
|
|
1708
1598
|
error$1
|
|
1709
1599
|
);
|
|
1710
1600
|
}
|
|
1711
1601
|
}
|
|
1712
|
-
async batchTraceInsert({ records }) {
|
|
1713
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1714
|
-
await this.operations.batchInsert({
|
|
1715
|
-
tableName: storage.TABLE_TRACES,
|
|
1716
|
-
records
|
|
1717
|
-
});
|
|
1718
|
-
}
|
|
1719
1602
|
};
|
|
1603
|
+
function escapeSql(str) {
|
|
1604
|
+
return str.replace(/'/g, "''");
|
|
1605
|
+
}
|
|
1720
1606
|
function parseWorkflowRun(row) {
|
|
1721
1607
|
let parsedSnapshot = row.snapshot;
|
|
1722
1608
|
if (typeof parsedSnapshot === "string") {
|
|
@@ -1737,38 +1623,104 @@ function parseWorkflowRun(row) {
|
|
|
1737
1623
|
}
|
|
1738
1624
|
var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
1739
1625
|
client;
|
|
1740
|
-
|
|
1626
|
+
#db;
|
|
1627
|
+
constructor(config) {
|
|
1741
1628
|
super();
|
|
1629
|
+
const client = resolveLanceConfig(config);
|
|
1742
1630
|
this.client = client;
|
|
1631
|
+
this.#db = new LanceDB({ client });
|
|
1632
|
+
}
|
|
1633
|
+
async init() {
|
|
1634
|
+
const schema = storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT];
|
|
1635
|
+
await this.#db.createTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT, schema });
|
|
1636
|
+
await this.#db.alterTable({
|
|
1637
|
+
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
1638
|
+
schema,
|
|
1639
|
+
ifNotExists: ["resourceId"]
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
async dangerouslyClearAll() {
|
|
1643
|
+
await this.#db.clearTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT });
|
|
1644
|
+
}
|
|
1645
|
+
async updateWorkflowResults({
|
|
1646
|
+
workflowName,
|
|
1647
|
+
runId,
|
|
1648
|
+
stepId,
|
|
1649
|
+
result,
|
|
1650
|
+
requestContext
|
|
1651
|
+
}) {
|
|
1652
|
+
let snapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
|
|
1653
|
+
if (!snapshot) {
|
|
1654
|
+
snapshot = {
|
|
1655
|
+
context: {},
|
|
1656
|
+
activePaths: [],
|
|
1657
|
+
timestamp: Date.now(),
|
|
1658
|
+
suspendedPaths: {},
|
|
1659
|
+
activeStepsPath: {},
|
|
1660
|
+
resumeLabels: {},
|
|
1661
|
+
serializedStepGraph: [],
|
|
1662
|
+
status: "pending",
|
|
1663
|
+
value: {},
|
|
1664
|
+
waitingPaths: {},
|
|
1665
|
+
runId,
|
|
1666
|
+
requestContext: {}
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
snapshot.context[stepId] = result;
|
|
1670
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
1671
|
+
await this.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
1672
|
+
return snapshot.context;
|
|
1673
|
+
}
|
|
1674
|
+
async updateWorkflowState({
|
|
1675
|
+
workflowName,
|
|
1676
|
+
runId,
|
|
1677
|
+
opts
|
|
1678
|
+
}) {
|
|
1679
|
+
const snapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
|
|
1680
|
+
if (!snapshot) {
|
|
1681
|
+
return void 0;
|
|
1682
|
+
}
|
|
1683
|
+
if (!snapshot.context) {
|
|
1684
|
+
throw new Error(`Snapshot not found for runId ${runId}`);
|
|
1685
|
+
}
|
|
1686
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
1687
|
+
await this.persistWorkflowSnapshot({ workflowName, runId, snapshot: updatedSnapshot });
|
|
1688
|
+
return updatedSnapshot;
|
|
1743
1689
|
}
|
|
1744
1690
|
async persistWorkflowSnapshot({
|
|
1745
1691
|
workflowName,
|
|
1746
1692
|
runId,
|
|
1747
|
-
|
|
1693
|
+
resourceId,
|
|
1694
|
+
snapshot,
|
|
1695
|
+
createdAt,
|
|
1696
|
+
updatedAt
|
|
1748
1697
|
}) {
|
|
1749
1698
|
try {
|
|
1750
1699
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1751
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1700
|
+
const query = table.query().where(`workflow_name = '${escapeSql(workflowName)}' AND run_id = '${escapeSql(runId)}'`);
|
|
1752
1701
|
const records = await query.toArray();
|
|
1753
|
-
let
|
|
1754
|
-
const now = Date.now();
|
|
1702
|
+
let createdAtValue;
|
|
1703
|
+
const now = createdAt?.getTime() ?? Date.now();
|
|
1755
1704
|
if (records.length > 0) {
|
|
1756
|
-
|
|
1705
|
+
createdAtValue = records[0].createdAt ?? now;
|
|
1757
1706
|
} else {
|
|
1758
|
-
|
|
1707
|
+
createdAtValue = now;
|
|
1759
1708
|
}
|
|
1709
|
+
const { status, value, ...rest } = snapshot;
|
|
1760
1710
|
const record = {
|
|
1761
1711
|
workflow_name: workflowName,
|
|
1762
1712
|
run_id: runId,
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1713
|
+
resourceId,
|
|
1714
|
+
snapshot: JSON.stringify({ status, value, ...rest }),
|
|
1715
|
+
// this is to ensure status is always just before value, for when querying the db by status
|
|
1716
|
+
createdAt: createdAtValue,
|
|
1717
|
+
updatedAt: updatedAt ?? now
|
|
1766
1718
|
};
|
|
1767
1719
|
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1768
1720
|
} catch (error$1) {
|
|
1769
1721
|
throw new error.MastraError(
|
|
1770
1722
|
{
|
|
1771
|
-
id: "
|
|
1723
|
+
id: storage.createStorageErrorId("LANCE", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1772
1724
|
domain: error.ErrorDomain.STORAGE,
|
|
1773
1725
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1774
1726
|
details: { workflowName, runId }
|
|
@@ -1783,13 +1735,13 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1783
1735
|
}) {
|
|
1784
1736
|
try {
|
|
1785
1737
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1786
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1738
|
+
const query = table.query().where(`workflow_name = '${escapeSql(workflowName)}' AND run_id = '${escapeSql(runId)}'`);
|
|
1787
1739
|
const records = await query.toArray();
|
|
1788
1740
|
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
1789
1741
|
} catch (error$1) {
|
|
1790
1742
|
throw new error.MastraError(
|
|
1791
1743
|
{
|
|
1792
|
-
id: "
|
|
1744
|
+
id: storage.createStorageErrorId("LANCE", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1793
1745
|
domain: error.ErrorDomain.STORAGE,
|
|
1794
1746
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1795
1747
|
details: { workflowName, runId }
|
|
@@ -1801,9 +1753,9 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1801
1753
|
async getWorkflowRunById(args) {
|
|
1802
1754
|
try {
|
|
1803
1755
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1804
|
-
let whereClause = `run_id = '${args.runId}'`;
|
|
1756
|
+
let whereClause = `run_id = '${escapeSql(args.runId)}'`;
|
|
1805
1757
|
if (args.workflowName) {
|
|
1806
|
-
whereClause += ` AND workflow_name = '${args.workflowName}'`;
|
|
1758
|
+
whereClause += ` AND workflow_name = '${escapeSql(args.workflowName)}'`;
|
|
1807
1759
|
}
|
|
1808
1760
|
const query = table.query().where(whereClause);
|
|
1809
1761
|
const records = await query.toArray();
|
|
@@ -1813,7 +1765,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1813
1765
|
} catch (error$1) {
|
|
1814
1766
|
throw new error.MastraError(
|
|
1815
1767
|
{
|
|
1816
|
-
id: "
|
|
1768
|
+
id: storage.createStorageErrorId("LANCE", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1817
1769
|
domain: error.ErrorDomain.STORAGE,
|
|
1818
1770
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1819
1771
|
details: { runId: args.runId, workflowName: args.workflowName ?? "" }
|
|
@@ -1822,16 +1774,37 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1822
1774
|
);
|
|
1823
1775
|
}
|
|
1824
1776
|
}
|
|
1825
|
-
async
|
|
1777
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
1778
|
+
try {
|
|
1779
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1780
|
+
const whereClause = `run_id = '${escapeSql(runId)}' AND workflow_name = '${escapeSql(workflowName)}'`;
|
|
1781
|
+
await table.delete(whereClause);
|
|
1782
|
+
} catch (error$1) {
|
|
1783
|
+
throw new error.MastraError(
|
|
1784
|
+
{
|
|
1785
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1786
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1787
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1788
|
+
details: { runId, workflowName }
|
|
1789
|
+
},
|
|
1790
|
+
error$1
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
async listWorkflowRuns(args) {
|
|
1826
1795
|
try {
|
|
1827
1796
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1828
1797
|
let query = table.query();
|
|
1829
1798
|
const conditions = [];
|
|
1830
1799
|
if (args?.workflowName) {
|
|
1831
|
-
conditions.push(`workflow_name = '${args.workflowName
|
|
1800
|
+
conditions.push(`workflow_name = '${escapeSql(args.workflowName)}'`);
|
|
1801
|
+
}
|
|
1802
|
+
if (args?.status) {
|
|
1803
|
+
const escapedStatus = args.status.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
1804
|
+
conditions.push(`\`snapshot\` LIKE '%"status":"${escapedStatus}","value"%'`);
|
|
1832
1805
|
}
|
|
1833
1806
|
if (args?.resourceId) {
|
|
1834
|
-
conditions.push(`\`resourceId\` = '${args.resourceId}'`);
|
|
1807
|
+
conditions.push(`\`resourceId\` = '${escapeSql(args.resourceId)}'`);
|
|
1835
1808
|
}
|
|
1836
1809
|
if (args?.fromDate instanceof Date) {
|
|
1837
1810
|
conditions.push(`\`createdAt\` >= ${args.fromDate.getTime()}`);
|
|
@@ -1846,11 +1819,22 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1846
1819
|
} else {
|
|
1847
1820
|
total = await table.countRows();
|
|
1848
1821
|
}
|
|
1849
|
-
if (args?.
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1822
|
+
if (args?.perPage !== void 0 && args?.page !== void 0) {
|
|
1823
|
+
const normalizedPerPage = storage.normalizePerPage(args.perPage, Number.MAX_SAFE_INTEGER);
|
|
1824
|
+
if (args.page < 0 || !Number.isInteger(args.page)) {
|
|
1825
|
+
throw new error.MastraError(
|
|
1826
|
+
{
|
|
1827
|
+
id: storage.createStorageErrorId("LANCE", "LIST_WORKFLOW_RUNS", "INVALID_PAGINATION"),
|
|
1828
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1829
|
+
category: error.ErrorCategory.USER,
|
|
1830
|
+
details: { page: args.page, perPage: args.perPage }
|
|
1831
|
+
},
|
|
1832
|
+
new Error(`Invalid pagination parameters: page=${args.page}, perPage=${args.perPage}`)
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
const offset = args.page * normalizedPerPage;
|
|
1836
|
+
query.limit(normalizedPerPage);
|
|
1837
|
+
query.offset(offset);
|
|
1854
1838
|
}
|
|
1855
1839
|
const records = await query.toArray();
|
|
1856
1840
|
return {
|
|
@@ -1860,10 +1844,10 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1860
1844
|
} catch (error$1) {
|
|
1861
1845
|
throw new error.MastraError(
|
|
1862
1846
|
{
|
|
1863
|
-
id: "
|
|
1847
|
+
id: storage.createStorageErrorId("LANCE", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
1864
1848
|
domain: error.ErrorDomain.STORAGE,
|
|
1865
1849
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1866
|
-
details: {
|
|
1850
|
+
details: { resourceId: args?.resourceId ?? "", workflowName: args?.workflowName ?? "" }
|
|
1867
1851
|
},
|
|
1868
1852
|
error$1
|
|
1869
1853
|
);
|
|
@@ -1877,48 +1861,52 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1877
1861
|
lanceClient;
|
|
1878
1862
|
/**
|
|
1879
1863
|
* Creates a new instance of LanceStorage
|
|
1864
|
+
* @param id The unique identifier for this storage instance
|
|
1865
|
+
* @param name The name for this storage instance
|
|
1880
1866
|
* @param uri The URI to connect to LanceDB
|
|
1881
|
-
* @param
|
|
1867
|
+
* @param connectionOptions connection options for LanceDB
|
|
1868
|
+
* @param storageOptions storage options including disableInit
|
|
1882
1869
|
*
|
|
1883
1870
|
* Usage:
|
|
1884
1871
|
*
|
|
1885
1872
|
* Connect to a local database
|
|
1886
1873
|
* ```ts
|
|
1887
|
-
* const store = await LanceStorage.create('/path/to/db');
|
|
1874
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db');
|
|
1888
1875
|
* ```
|
|
1889
1876
|
*
|
|
1890
1877
|
* Connect to a LanceDB cloud database
|
|
1891
1878
|
* ```ts
|
|
1892
|
-
* const store = await LanceStorage.create('db://host:port');
|
|
1879
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 'db://host:port');
|
|
1893
1880
|
* ```
|
|
1894
1881
|
*
|
|
1895
1882
|
* Connect to a cloud database
|
|
1896
1883
|
* ```ts
|
|
1897
|
-
* const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1884
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 's3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1885
|
+
* ```
|
|
1886
|
+
*
|
|
1887
|
+
* Disable auto-init for runtime (after CI/CD has run migrations)
|
|
1888
|
+
* ```ts
|
|
1889
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db', undefined, { disableInit: true });
|
|
1898
1890
|
* ```
|
|
1899
1891
|
*/
|
|
1900
|
-
static async create(name, uri,
|
|
1901
|
-
const instance = new _LanceStorage(name);
|
|
1892
|
+
static async create(id, name, uri, connectionOptions, storageOptions) {
|
|
1893
|
+
const instance = new _LanceStorage(id, name, storageOptions?.disableInit);
|
|
1902
1894
|
try {
|
|
1903
|
-
instance.lanceClient = await lancedb.connect(uri,
|
|
1904
|
-
const operations = new StoreOperationsLance({ client: instance.lanceClient });
|
|
1895
|
+
instance.lanceClient = await lancedb.connect(uri, connectionOptions);
|
|
1905
1896
|
instance.stores = {
|
|
1906
|
-
operations: new StoreOperationsLance({ client: instance.lanceClient }),
|
|
1907
1897
|
workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
|
|
1908
|
-
traces: new StoreTracesLance({ client: instance.lanceClient, operations }),
|
|
1909
1898
|
scores: new StoreScoresLance({ client: instance.lanceClient }),
|
|
1910
|
-
memory: new StoreMemoryLance({ client: instance.lanceClient
|
|
1911
|
-
legacyEvals: new StoreLegacyEvalsLance({ client: instance.lanceClient })
|
|
1899
|
+
memory: new StoreMemoryLance({ client: instance.lanceClient })
|
|
1912
1900
|
};
|
|
1913
1901
|
return instance;
|
|
1914
1902
|
} catch (e) {
|
|
1915
1903
|
throw new error.MastraError(
|
|
1916
1904
|
{
|
|
1917
|
-
id: "
|
|
1905
|
+
id: storage.createStorageErrorId("LANCE", "CONNECT", "FAILED"),
|
|
1918
1906
|
domain: error.ErrorDomain.STORAGE,
|
|
1919
1907
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1920
1908
|
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
1921
|
-
details: { uri, optionsProvided: !!
|
|
1909
|
+
details: { uri, optionsProvided: !!connectionOptions }
|
|
1922
1910
|
},
|
|
1923
1911
|
e
|
|
1924
1912
|
);
|
|
@@ -1926,54 +1914,16 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1926
1914
|
}
|
|
1927
1915
|
/**
|
|
1928
1916
|
* @internal
|
|
1929
|
-
* Private constructor to enforce using the create factory method
|
|
1917
|
+
* Private constructor to enforce using the create factory method.
|
|
1918
|
+
* Note: stores is initialized in create() after the lanceClient is connected.
|
|
1930
1919
|
*/
|
|
1931
|
-
constructor(name) {
|
|
1932
|
-
super({ name });
|
|
1933
|
-
|
|
1934
|
-
this.stores = {
|
|
1935
|
-
operations: new StoreOperationsLance({ client: this.lanceClient }),
|
|
1936
|
-
workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
|
|
1937
|
-
traces: new StoreTracesLance({ client: this.lanceClient, operations }),
|
|
1938
|
-
scores: new StoreScoresLance({ client: this.lanceClient }),
|
|
1939
|
-
legacyEvals: new StoreLegacyEvalsLance({ client: this.lanceClient }),
|
|
1940
|
-
memory: new StoreMemoryLance({ client: this.lanceClient, operations })
|
|
1941
|
-
};
|
|
1942
|
-
}
|
|
1943
|
-
async createTable({
|
|
1944
|
-
tableName,
|
|
1945
|
-
schema
|
|
1946
|
-
}) {
|
|
1947
|
-
return this.stores.operations.createTable({ tableName, schema });
|
|
1948
|
-
}
|
|
1949
|
-
async dropTable({ tableName }) {
|
|
1950
|
-
return this.stores.operations.dropTable({ tableName });
|
|
1951
|
-
}
|
|
1952
|
-
async alterTable({
|
|
1953
|
-
tableName,
|
|
1954
|
-
schema,
|
|
1955
|
-
ifNotExists
|
|
1956
|
-
}) {
|
|
1957
|
-
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
1958
|
-
}
|
|
1959
|
-
async clearTable({ tableName }) {
|
|
1960
|
-
return this.stores.operations.clearTable({ tableName });
|
|
1961
|
-
}
|
|
1962
|
-
async insert({ tableName, record }) {
|
|
1963
|
-
return this.stores.operations.insert({ tableName, record });
|
|
1964
|
-
}
|
|
1965
|
-
async batchInsert({ tableName, records }) {
|
|
1966
|
-
return this.stores.operations.batchInsert({ tableName, records });
|
|
1967
|
-
}
|
|
1968
|
-
async load({ tableName, keys }) {
|
|
1969
|
-
return this.stores.operations.load({ tableName, keys });
|
|
1920
|
+
constructor(id, name, disableInit) {
|
|
1921
|
+
super({ id, name, disableInit });
|
|
1922
|
+
this.stores = {};
|
|
1970
1923
|
}
|
|
1971
1924
|
async getThreadById({ threadId }) {
|
|
1972
1925
|
return this.stores.memory.getThreadById({ threadId });
|
|
1973
1926
|
}
|
|
1974
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
1975
|
-
return this.stores.memory.getThreadsByResourceId({ resourceId });
|
|
1976
|
-
}
|
|
1977
1927
|
/**
|
|
1978
1928
|
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
1979
1929
|
* @param thread - The thread to save
|
|
@@ -1992,13 +1942,17 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1992
1942
|
async deleteThread({ threadId }) {
|
|
1993
1943
|
return this.stores.memory.deleteThread({ threadId });
|
|
1994
1944
|
}
|
|
1945
|
+
async deleteMessages(messageIds) {
|
|
1946
|
+
return this.stores.memory.deleteMessages(messageIds);
|
|
1947
|
+
}
|
|
1995
1948
|
get supports() {
|
|
1996
1949
|
return {
|
|
1997
1950
|
selectByIncludeResourceScope: true,
|
|
1998
1951
|
resourceWorkingMemory: true,
|
|
1999
1952
|
hasColumn: true,
|
|
2000
1953
|
createTable: true,
|
|
2001
|
-
deleteMessages:
|
|
1954
|
+
deleteMessages: true,
|
|
1955
|
+
listScoresBySpan: true
|
|
2002
1956
|
};
|
|
2003
1957
|
}
|
|
2004
1958
|
async getResourceById({ resourceId }) {
|
|
@@ -2062,54 +2016,47 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
2062
2016
|
});
|
|
2063
2017
|
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
2064
2018
|
}
|
|
2065
|
-
async
|
|
2066
|
-
|
|
2067
|
-
resourceId,
|
|
2068
|
-
selectBy,
|
|
2069
|
-
format,
|
|
2070
|
-
threadConfig
|
|
2071
|
-
}) {
|
|
2072
|
-
return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format, threadConfig });
|
|
2019
|
+
async listMessagesById({ messageIds }) {
|
|
2020
|
+
return this.stores.memory.listMessagesById({ messageIds });
|
|
2073
2021
|
}
|
|
2074
2022
|
async saveMessages(args) {
|
|
2075
2023
|
return this.stores.memory.saveMessages(args);
|
|
2076
2024
|
}
|
|
2077
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
2078
|
-
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2079
|
-
}
|
|
2080
|
-
async getMessagesPaginated(args) {
|
|
2081
|
-
return this.stores.memory.getMessagesPaginated(args);
|
|
2082
|
-
}
|
|
2083
2025
|
async updateMessages(_args) {
|
|
2084
2026
|
return this.stores.memory.updateMessages(_args);
|
|
2085
2027
|
}
|
|
2086
|
-
async
|
|
2087
|
-
return this.stores.
|
|
2028
|
+
async listWorkflowRuns(args) {
|
|
2029
|
+
return this.stores.workflows.listWorkflowRuns(args);
|
|
2088
2030
|
}
|
|
2089
|
-
async
|
|
2090
|
-
return this.stores.
|
|
2091
|
-
}
|
|
2092
|
-
async getTracesPaginated(args) {
|
|
2093
|
-
return this.stores.traces.getTracesPaginated(args);
|
|
2094
|
-
}
|
|
2095
|
-
async getEvalsByAgentName(agentName, type) {
|
|
2096
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2031
|
+
async getWorkflowRunById(args) {
|
|
2032
|
+
return this.stores.workflows.getWorkflowRunById(args);
|
|
2097
2033
|
}
|
|
2098
|
-
async
|
|
2099
|
-
return this.stores.
|
|
2034
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
2035
|
+
return this.stores.workflows.deleteWorkflowRunById({ runId, workflowName });
|
|
2100
2036
|
}
|
|
2101
|
-
async
|
|
2102
|
-
|
|
2037
|
+
async updateWorkflowResults({
|
|
2038
|
+
workflowName,
|
|
2039
|
+
runId,
|
|
2040
|
+
stepId,
|
|
2041
|
+
result,
|
|
2042
|
+
requestContext
|
|
2043
|
+
}) {
|
|
2044
|
+
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
2103
2045
|
}
|
|
2104
|
-
async
|
|
2105
|
-
|
|
2046
|
+
async updateWorkflowState({
|
|
2047
|
+
workflowName,
|
|
2048
|
+
runId,
|
|
2049
|
+
opts
|
|
2050
|
+
}) {
|
|
2051
|
+
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
2106
2052
|
}
|
|
2107
2053
|
async persistWorkflowSnapshot({
|
|
2108
2054
|
workflowName,
|
|
2109
2055
|
runId,
|
|
2056
|
+
resourceId,
|
|
2110
2057
|
snapshot
|
|
2111
2058
|
}) {
|
|
2112
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
2059
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
2113
2060
|
}
|
|
2114
2061
|
async loadWorkflowSnapshot({
|
|
2115
2062
|
workflowName,
|
|
@@ -2120,27 +2067,37 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
2120
2067
|
async getScoreById({ id: _id }) {
|
|
2121
2068
|
return this.stores.scores.getScoreById({ id: _id });
|
|
2122
2069
|
}
|
|
2123
|
-
async
|
|
2070
|
+
async listScoresByScorerId({
|
|
2124
2071
|
scorerId,
|
|
2072
|
+
source,
|
|
2073
|
+
entityId,
|
|
2074
|
+
entityType,
|
|
2125
2075
|
pagination
|
|
2126
2076
|
}) {
|
|
2127
|
-
return this.stores.scores.
|
|
2077
|
+
return this.stores.scores.listScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
|
|
2128
2078
|
}
|
|
2129
|
-
async saveScore(
|
|
2130
|
-
return this.stores.scores.saveScore(
|
|
2079
|
+
async saveScore(score) {
|
|
2080
|
+
return this.stores.scores.saveScore(score);
|
|
2131
2081
|
}
|
|
2132
|
-
async
|
|
2082
|
+
async listScoresByRunId({
|
|
2133
2083
|
runId,
|
|
2134
2084
|
pagination
|
|
2135
2085
|
}) {
|
|
2136
|
-
return this.stores.scores.
|
|
2086
|
+
return this.stores.scores.listScoresByRunId({ runId, pagination });
|
|
2137
2087
|
}
|
|
2138
|
-
async
|
|
2088
|
+
async listScoresByEntityId({
|
|
2139
2089
|
entityId,
|
|
2140
2090
|
entityType,
|
|
2141
2091
|
pagination
|
|
2142
2092
|
}) {
|
|
2143
|
-
return this.stores.scores.
|
|
2093
|
+
return this.stores.scores.listScoresByEntityId({ entityId, entityType, pagination });
|
|
2094
|
+
}
|
|
2095
|
+
async listScoresBySpan({
|
|
2096
|
+
traceId,
|
|
2097
|
+
spanId,
|
|
2098
|
+
pagination
|
|
2099
|
+
}) {
|
|
2100
|
+
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
|
|
2144
2101
|
}
|
|
2145
2102
|
};
|
|
2146
2103
|
var LanceFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
@@ -2489,14 +2446,14 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2489
2446
|
* ```
|
|
2490
2447
|
*/
|
|
2491
2448
|
static async create(uri, options) {
|
|
2492
|
-
const instance = new _LanceVectorStore();
|
|
2449
|
+
const instance = new _LanceVectorStore(options?.id || crypto.randomUUID());
|
|
2493
2450
|
try {
|
|
2494
2451
|
instance.lanceClient = await lancedb.connect(uri, options);
|
|
2495
2452
|
return instance;
|
|
2496
2453
|
} catch (e) {
|
|
2497
2454
|
throw new error.MastraError(
|
|
2498
2455
|
{
|
|
2499
|
-
id: "
|
|
2456
|
+
id: storage.createVectorErrorId("LANCE", "CONNECT", "FAILED"),
|
|
2500
2457
|
domain: error.ErrorDomain.STORAGE,
|
|
2501
2458
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2502
2459
|
details: { uri }
|
|
@@ -2509,8 +2466,8 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2509
2466
|
* @internal
|
|
2510
2467
|
* Private constructor to enforce using the create factory method
|
|
2511
2468
|
*/
|
|
2512
|
-
constructor() {
|
|
2513
|
-
super();
|
|
2469
|
+
constructor(id) {
|
|
2470
|
+
super({ id });
|
|
2514
2471
|
}
|
|
2515
2472
|
close() {
|
|
2516
2473
|
if (this.lanceClient) {
|
|
@@ -2539,7 +2496,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2539
2496
|
} catch (error$1) {
|
|
2540
2497
|
throw new error.MastraError(
|
|
2541
2498
|
{
|
|
2542
|
-
id: "
|
|
2499
|
+
id: storage.createVectorErrorId("LANCE", "QUERY", "INVALID_ARGS"),
|
|
2543
2500
|
domain: error.ErrorDomain.STORAGE,
|
|
2544
2501
|
category: error.ErrorCategory.USER,
|
|
2545
2502
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2587,7 +2544,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2587
2544
|
} catch (error$1) {
|
|
2588
2545
|
throw new error.MastraError(
|
|
2589
2546
|
{
|
|
2590
|
-
id: "
|
|
2547
|
+
id: storage.createVectorErrorId("LANCE", "QUERY", "FAILED"),
|
|
2591
2548
|
domain: error.ErrorDomain.STORAGE,
|
|
2592
2549
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2593
2550
|
details: { tableName, includeVector, columnsCount: columns?.length, includeAllColumns }
|
|
@@ -2639,7 +2596,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2639
2596
|
} catch (error$1) {
|
|
2640
2597
|
throw new error.MastraError(
|
|
2641
2598
|
{
|
|
2642
|
-
id: "
|
|
2599
|
+
id: storage.createVectorErrorId("LANCE", "UPSERT", "INVALID_ARGS"),
|
|
2643
2600
|
domain: error.ErrorDomain.STORAGE,
|
|
2644
2601
|
category: error.ErrorCategory.USER,
|
|
2645
2602
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2675,7 +2632,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2675
2632
|
} catch (error$1) {
|
|
2676
2633
|
throw new error.MastraError(
|
|
2677
2634
|
{
|
|
2678
|
-
id: "
|
|
2635
|
+
id: storage.createVectorErrorId("LANCE", "UPSERT", "FAILED"),
|
|
2679
2636
|
domain: error.ErrorDomain.STORAGE,
|
|
2680
2637
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2681
2638
|
details: { tableName, vectorCount: vectors.length, metadataCount: metadata.length, idsCount: ids.length }
|
|
@@ -2702,7 +2659,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2702
2659
|
async createTable(tableName, data, options) {
|
|
2703
2660
|
if (!this.lanceClient) {
|
|
2704
2661
|
throw new error.MastraError({
|
|
2705
|
-
id: "
|
|
2662
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_TABLE", "INVALID_ARGS"),
|
|
2706
2663
|
domain: error.ErrorDomain.STORAGE,
|
|
2707
2664
|
category: error.ErrorCategory.USER,
|
|
2708
2665
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2717,7 +2674,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2717
2674
|
} catch (error$1) {
|
|
2718
2675
|
throw new error.MastraError(
|
|
2719
2676
|
{
|
|
2720
|
-
id: "
|
|
2677
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_TABLE", "FAILED"),
|
|
2721
2678
|
domain: error.ErrorDomain.STORAGE,
|
|
2722
2679
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2723
2680
|
details: { tableName }
|
|
@@ -2729,7 +2686,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2729
2686
|
async listTables() {
|
|
2730
2687
|
if (!this.lanceClient) {
|
|
2731
2688
|
throw new error.MastraError({
|
|
2732
|
-
id: "
|
|
2689
|
+
id: storage.createVectorErrorId("LANCE", "LIST_TABLES", "INVALID_ARGS"),
|
|
2733
2690
|
domain: error.ErrorDomain.STORAGE,
|
|
2734
2691
|
category: error.ErrorCategory.USER,
|
|
2735
2692
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2741,7 +2698,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2741
2698
|
} catch (error$1) {
|
|
2742
2699
|
throw new error.MastraError(
|
|
2743
2700
|
{
|
|
2744
|
-
id: "
|
|
2701
|
+
id: storage.createVectorErrorId("LANCE", "LIST_TABLES", "FAILED"),
|
|
2745
2702
|
domain: error.ErrorDomain.STORAGE,
|
|
2746
2703
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2747
2704
|
},
|
|
@@ -2752,7 +2709,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2752
2709
|
async getTableSchema(tableName) {
|
|
2753
2710
|
if (!this.lanceClient) {
|
|
2754
2711
|
throw new error.MastraError({
|
|
2755
|
-
id: "
|
|
2712
|
+
id: storage.createVectorErrorId("LANCE", "GET_TABLE_SCHEMA", "INVALID_ARGS"),
|
|
2756
2713
|
domain: error.ErrorDomain.STORAGE,
|
|
2757
2714
|
category: error.ErrorCategory.USER,
|
|
2758
2715
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2765,7 +2722,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2765
2722
|
} catch (error$1) {
|
|
2766
2723
|
throw new error.MastraError(
|
|
2767
2724
|
{
|
|
2768
|
-
id: "
|
|
2725
|
+
id: storage.createVectorErrorId("LANCE", "GET_TABLE_SCHEMA", "FAILED"),
|
|
2769
2726
|
domain: error.ErrorDomain.STORAGE,
|
|
2770
2727
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2771
2728
|
details: { tableName }
|
|
@@ -2800,7 +2757,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2800
2757
|
} catch (err) {
|
|
2801
2758
|
throw new error.MastraError(
|
|
2802
2759
|
{
|
|
2803
|
-
id: "
|
|
2760
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "INVALID_ARGS"),
|
|
2804
2761
|
domain: error.ErrorDomain.STORAGE,
|
|
2805
2762
|
category: error.ErrorCategory.USER,
|
|
2806
2763
|
details: { tableName: tableName || "", indexName, dimension, metric }
|
|
@@ -2845,7 +2802,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2845
2802
|
} catch (error$1) {
|
|
2846
2803
|
throw new error.MastraError(
|
|
2847
2804
|
{
|
|
2848
|
-
id: "
|
|
2805
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "FAILED"),
|
|
2849
2806
|
domain: error.ErrorDomain.STORAGE,
|
|
2850
2807
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2851
2808
|
details: { tableName: tableName || "", indexName, dimension }
|
|
@@ -2857,7 +2814,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2857
2814
|
async listIndexes() {
|
|
2858
2815
|
if (!this.lanceClient) {
|
|
2859
2816
|
throw new error.MastraError({
|
|
2860
|
-
id: "
|
|
2817
|
+
id: storage.createVectorErrorId("LANCE", "LIST_INDEXES", "INVALID_ARGS"),
|
|
2861
2818
|
domain: error.ErrorDomain.STORAGE,
|
|
2862
2819
|
category: error.ErrorCategory.USER,
|
|
2863
2820
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2876,7 +2833,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2876
2833
|
} catch (error$1) {
|
|
2877
2834
|
throw new error.MastraError(
|
|
2878
2835
|
{
|
|
2879
|
-
id: "
|
|
2836
|
+
id: storage.createVectorErrorId("LANCE", "LIST_INDEXES", "FAILED"),
|
|
2880
2837
|
domain: error.ErrorDomain.STORAGE,
|
|
2881
2838
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2882
2839
|
},
|
|
@@ -2895,7 +2852,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2895
2852
|
} catch (err) {
|
|
2896
2853
|
throw new error.MastraError(
|
|
2897
2854
|
{
|
|
2898
|
-
id: "
|
|
2855
|
+
id: storage.createVectorErrorId("LANCE", "DESCRIBE_INDEX", "INVALID_ARGS"),
|
|
2899
2856
|
domain: error.ErrorDomain.STORAGE,
|
|
2900
2857
|
category: error.ErrorCategory.USER,
|
|
2901
2858
|
details: { indexName }
|
|
@@ -2930,7 +2887,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2930
2887
|
} catch (error$1) {
|
|
2931
2888
|
throw new error.MastraError(
|
|
2932
2889
|
{
|
|
2933
|
-
id: "
|
|
2890
|
+
id: storage.createVectorErrorId("LANCE", "DESCRIBE_INDEX", "FAILED"),
|
|
2934
2891
|
domain: error.ErrorDomain.STORAGE,
|
|
2935
2892
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2936
2893
|
details: { indexName }
|
|
@@ -2950,7 +2907,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2950
2907
|
} catch (err) {
|
|
2951
2908
|
throw new error.MastraError(
|
|
2952
2909
|
{
|
|
2953
|
-
id: "
|
|
2910
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_INDEX", "INVALID_ARGS"),
|
|
2954
2911
|
domain: error.ErrorDomain.STORAGE,
|
|
2955
2912
|
category: error.ErrorCategory.USER,
|
|
2956
2913
|
details: { indexName }
|
|
@@ -2973,7 +2930,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2973
2930
|
} catch (error$1) {
|
|
2974
2931
|
throw new error.MastraError(
|
|
2975
2932
|
{
|
|
2976
|
-
id: "
|
|
2933
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_INDEX", "FAILED"),
|
|
2977
2934
|
domain: error.ErrorDomain.STORAGE,
|
|
2978
2935
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2979
2936
|
details: { indexName }
|
|
@@ -2988,7 +2945,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2988
2945
|
async deleteAllTables() {
|
|
2989
2946
|
if (!this.lanceClient) {
|
|
2990
2947
|
throw new error.MastraError({
|
|
2991
|
-
id: "
|
|
2948
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_ALL_TABLES", "INVALID_ARGS"),
|
|
2992
2949
|
domain: error.ErrorDomain.STORAGE,
|
|
2993
2950
|
category: error.ErrorCategory.USER,
|
|
2994
2951
|
details: { methodName: "deleteAllTables" },
|
|
@@ -3000,7 +2957,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3000
2957
|
} catch (error$1) {
|
|
3001
2958
|
throw new error.MastraError(
|
|
3002
2959
|
{
|
|
3003
|
-
id: "
|
|
2960
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_ALL_TABLES", "FAILED"),
|
|
3004
2961
|
domain: error.ErrorDomain.STORAGE,
|
|
3005
2962
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3006
2963
|
details: { methodName: "deleteAllTables" }
|
|
@@ -3012,7 +2969,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3012
2969
|
async deleteTable(tableName) {
|
|
3013
2970
|
if (!this.lanceClient) {
|
|
3014
2971
|
throw new error.MastraError({
|
|
3015
|
-
id: "
|
|
2972
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_TABLE", "INVALID_ARGS"),
|
|
3016
2973
|
domain: error.ErrorDomain.STORAGE,
|
|
3017
2974
|
category: error.ErrorCategory.USER,
|
|
3018
2975
|
details: { tableName },
|
|
@@ -3024,7 +2981,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3024
2981
|
} catch (error$1) {
|
|
3025
2982
|
throw new error.MastraError(
|
|
3026
2983
|
{
|
|
3027
|
-
id: "
|
|
2984
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_TABLE", "FAILED"),
|
|
3028
2985
|
domain: error.ErrorDomain.STORAGE,
|
|
3029
2986
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3030
2987
|
details: { tableName }
|
|
@@ -3033,7 +2990,44 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3033
2990
|
);
|
|
3034
2991
|
}
|
|
3035
2992
|
}
|
|
3036
|
-
async updateVector(
|
|
2993
|
+
async updateVector(params) {
|
|
2994
|
+
const { indexName, update } = params;
|
|
2995
|
+
if ("id" in params && "filter" in params && params.id && params.filter) {
|
|
2996
|
+
throw new error.MastraError({
|
|
2997
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "MUTUALLY_EXCLUSIVE"),
|
|
2998
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2999
|
+
category: error.ErrorCategory.USER,
|
|
3000
|
+
text: "id and filter are mutually exclusive",
|
|
3001
|
+
details: { indexName }
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
3004
|
+
if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
|
|
3005
|
+
throw new error.MastraError({
|
|
3006
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "NO_TARGET"),
|
|
3007
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3008
|
+
category: error.ErrorCategory.USER,
|
|
3009
|
+
text: "Either id or filter must be provided",
|
|
3010
|
+
details: { indexName }
|
|
3011
|
+
});
|
|
3012
|
+
}
|
|
3013
|
+
if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
|
|
3014
|
+
throw new error.MastraError({
|
|
3015
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "EMPTY_FILTER"),
|
|
3016
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3017
|
+
category: error.ErrorCategory.USER,
|
|
3018
|
+
text: "Cannot update with empty filter",
|
|
3019
|
+
details: { indexName }
|
|
3020
|
+
});
|
|
3021
|
+
}
|
|
3022
|
+
if (!update.vector && !update.metadata) {
|
|
3023
|
+
throw new error.MastraError({
|
|
3024
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "NO_PAYLOAD"),
|
|
3025
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3026
|
+
category: error.ErrorCategory.USER,
|
|
3027
|
+
text: "No updates provided",
|
|
3028
|
+
details: { indexName }
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3037
3031
|
try {
|
|
3038
3032
|
if (!this.lanceClient) {
|
|
3039
3033
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
@@ -3041,21 +3035,6 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3041
3035
|
if (!indexName) {
|
|
3042
3036
|
throw new Error("indexName is required");
|
|
3043
3037
|
}
|
|
3044
|
-
if (!id) {
|
|
3045
|
-
throw new Error("id is required");
|
|
3046
|
-
}
|
|
3047
|
-
} catch (err) {
|
|
3048
|
-
throw new error.MastraError(
|
|
3049
|
-
{
|
|
3050
|
-
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED_INVALID_ARGS",
|
|
3051
|
-
domain: error.ErrorDomain.STORAGE,
|
|
3052
|
-
category: error.ErrorCategory.USER,
|
|
3053
|
-
details: { indexName, id }
|
|
3054
|
-
},
|
|
3055
|
-
err
|
|
3056
|
-
);
|
|
3057
|
-
}
|
|
3058
|
-
try {
|
|
3059
3038
|
const tables = await this.lanceClient.tableNames();
|
|
3060
3039
|
for (const tableName of tables) {
|
|
3061
3040
|
this.logger.debug("Checking table:" + tableName);
|
|
@@ -3065,39 +3044,66 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3065
3044
|
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3066
3045
|
if (hasColumn) {
|
|
3067
3046
|
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3068
|
-
|
|
3069
|
-
if (
|
|
3070
|
-
|
|
3047
|
+
let whereClause;
|
|
3048
|
+
if ("id" in params && params.id) {
|
|
3049
|
+
whereClause = `id = '${params.id}'`;
|
|
3050
|
+
} else if ("filter" in params && params.filter) {
|
|
3051
|
+
const translator = new LanceFilterTranslator();
|
|
3052
|
+
const processFilterKeys = (filter) => {
|
|
3053
|
+
const processedFilter = {};
|
|
3054
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
3055
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3056
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
3057
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
3058
|
+
});
|
|
3059
|
+
} else {
|
|
3060
|
+
processedFilter[`metadata_${key}`] = value;
|
|
3061
|
+
}
|
|
3062
|
+
});
|
|
3063
|
+
return processedFilter;
|
|
3064
|
+
};
|
|
3065
|
+
const prefixedFilter = processFilterKeys(params.filter);
|
|
3066
|
+
whereClause = translator.translate(prefixedFilter) || "";
|
|
3067
|
+
if (!whereClause) {
|
|
3068
|
+
throw new Error("Failed to translate filter to SQL");
|
|
3069
|
+
}
|
|
3070
|
+
} else {
|
|
3071
|
+
throw new Error("Either id or filter must be provided");
|
|
3071
3072
|
}
|
|
3072
|
-
const
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3073
|
+
const existingRecords = await table.query().where(whereClause).select(schema.fields.map((field) => field.name)).toArray();
|
|
3074
|
+
if (existingRecords.length === 0) {
|
|
3075
|
+
this.logger.info(`No records found matching criteria in table ${tableName}`);
|
|
3076
|
+
return;
|
|
3077
|
+
}
|
|
3078
|
+
const updatedRecords = existingRecords.map((record) => {
|
|
3079
|
+
const rowData = {};
|
|
3080
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
3081
|
+
if (key !== "_distance") {
|
|
3082
|
+
if (key === indexName) {
|
|
3083
|
+
if (update.vector) {
|
|
3084
|
+
rowData[key] = update.vector;
|
|
3083
3085
|
} else {
|
|
3084
|
-
|
|
3086
|
+
if (Array.isArray(value)) {
|
|
3087
|
+
rowData[key] = [...value];
|
|
3088
|
+
} else if (typeof value === "object" && value !== null) {
|
|
3089
|
+
rowData[key] = Array.from(value);
|
|
3090
|
+
} else {
|
|
3091
|
+
rowData[key] = value;
|
|
3092
|
+
}
|
|
3085
3093
|
}
|
|
3094
|
+
} else {
|
|
3095
|
+
rowData[key] = value;
|
|
3086
3096
|
}
|
|
3087
|
-
} else {
|
|
3088
|
-
rowData[key] = value;
|
|
3089
3097
|
}
|
|
3098
|
+
});
|
|
3099
|
+
if (update.metadata) {
|
|
3100
|
+
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
3101
|
+
rowData[`metadata_${key}`] = value;
|
|
3102
|
+
});
|
|
3090
3103
|
}
|
|
3104
|
+
return rowData;
|
|
3091
3105
|
});
|
|
3092
|
-
|
|
3093
|
-
rowData[indexName] = update.vector;
|
|
3094
|
-
}
|
|
3095
|
-
if (update.metadata) {
|
|
3096
|
-
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
3097
|
-
rowData[`metadata_${key}`] = value;
|
|
3098
|
-
});
|
|
3099
|
-
}
|
|
3100
|
-
await table.add([rowData], { mode: "overwrite" });
|
|
3106
|
+
await table.add(updatedRecords, { mode: "overwrite" });
|
|
3101
3107
|
return;
|
|
3102
3108
|
}
|
|
3103
3109
|
} catch (err) {
|
|
@@ -3107,12 +3113,19 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3107
3113
|
}
|
|
3108
3114
|
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3109
3115
|
} catch (error$1) {
|
|
3116
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
3110
3117
|
throw new error.MastraError(
|
|
3111
3118
|
{
|
|
3112
|
-
id: "
|
|
3119
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "FAILED"),
|
|
3113
3120
|
domain: error.ErrorDomain.STORAGE,
|
|
3114
3121
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3115
|
-
details: {
|
|
3122
|
+
details: {
|
|
3123
|
+
indexName,
|
|
3124
|
+
..."id" in params && params.id && { id: params.id },
|
|
3125
|
+
..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) },
|
|
3126
|
+
hasVector: !!update.vector,
|
|
3127
|
+
hasMetadata: !!update.metadata
|
|
3128
|
+
}
|
|
3116
3129
|
},
|
|
3117
3130
|
error$1
|
|
3118
3131
|
);
|
|
@@ -3132,10 +3145,13 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3132
3145
|
} catch (err) {
|
|
3133
3146
|
throw new error.MastraError(
|
|
3134
3147
|
{
|
|
3135
|
-
id: "
|
|
3148
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTOR", "INVALID_ARGS"),
|
|
3136
3149
|
domain: error.ErrorDomain.STORAGE,
|
|
3137
3150
|
category: error.ErrorCategory.USER,
|
|
3138
|
-
details: {
|
|
3151
|
+
details: {
|
|
3152
|
+
indexName,
|
|
3153
|
+
...id && { id }
|
|
3154
|
+
}
|
|
3139
3155
|
},
|
|
3140
3156
|
err
|
|
3141
3157
|
);
|
|
@@ -3162,10 +3178,13 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3162
3178
|
} catch (error$1) {
|
|
3163
3179
|
throw new error.MastraError(
|
|
3164
3180
|
{
|
|
3165
|
-
id: "
|
|
3181
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTOR", "FAILED"),
|
|
3166
3182
|
domain: error.ErrorDomain.STORAGE,
|
|
3167
3183
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3168
|
-
details: {
|
|
3184
|
+
details: {
|
|
3185
|
+
indexName,
|
|
3186
|
+
...id && { id }
|
|
3187
|
+
}
|
|
3169
3188
|
},
|
|
3170
3189
|
error$1
|
|
3171
3190
|
);
|
|
@@ -3196,6 +3215,109 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3196
3215
|
});
|
|
3197
3216
|
return result;
|
|
3198
3217
|
}
|
|
3218
|
+
async deleteVectors({ indexName, filter, ids }) {
|
|
3219
|
+
if (ids && filter) {
|
|
3220
|
+
throw new error.MastraError({
|
|
3221
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "MUTUALLY_EXCLUSIVE"),
|
|
3222
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3223
|
+
category: error.ErrorCategory.USER,
|
|
3224
|
+
text: "ids and filter are mutually exclusive",
|
|
3225
|
+
details: { indexName }
|
|
3226
|
+
});
|
|
3227
|
+
}
|
|
3228
|
+
if (!ids && !filter) {
|
|
3229
|
+
throw new error.MastraError({
|
|
3230
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "NO_TARGET"),
|
|
3231
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3232
|
+
category: error.ErrorCategory.USER,
|
|
3233
|
+
text: "Either filter or ids must be provided",
|
|
3234
|
+
details: { indexName }
|
|
3235
|
+
});
|
|
3236
|
+
}
|
|
3237
|
+
if (ids && ids.length === 0) {
|
|
3238
|
+
throw new error.MastraError({
|
|
3239
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "EMPTY_IDS"),
|
|
3240
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3241
|
+
category: error.ErrorCategory.USER,
|
|
3242
|
+
text: "Cannot delete with empty ids array",
|
|
3243
|
+
details: { indexName }
|
|
3244
|
+
});
|
|
3245
|
+
}
|
|
3246
|
+
if (filter && Object.keys(filter).length === 0) {
|
|
3247
|
+
throw new error.MastraError({
|
|
3248
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "EMPTY_FILTER"),
|
|
3249
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3250
|
+
category: error.ErrorCategory.USER,
|
|
3251
|
+
text: "Cannot delete with empty filter",
|
|
3252
|
+
details: { indexName }
|
|
3253
|
+
});
|
|
3254
|
+
}
|
|
3255
|
+
try {
|
|
3256
|
+
if (!this.lanceClient) {
|
|
3257
|
+
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
3258
|
+
}
|
|
3259
|
+
if (!indexName) {
|
|
3260
|
+
throw new Error("indexName is required");
|
|
3261
|
+
}
|
|
3262
|
+
const tables = await this.lanceClient.tableNames();
|
|
3263
|
+
for (const tableName of tables) {
|
|
3264
|
+
this.logger.debug("Checking table:" + tableName);
|
|
3265
|
+
const table = await this.lanceClient.openTable(tableName);
|
|
3266
|
+
try {
|
|
3267
|
+
const schema = await table.schema();
|
|
3268
|
+
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3269
|
+
if (hasColumn) {
|
|
3270
|
+
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3271
|
+
if (ids) {
|
|
3272
|
+
const idsConditions = ids.map((id) => `id = '${id}'`).join(" OR ");
|
|
3273
|
+
await table.delete(idsConditions);
|
|
3274
|
+
} else if (filter) {
|
|
3275
|
+
const translator = new LanceFilterTranslator();
|
|
3276
|
+
const processFilterKeys = (filter2) => {
|
|
3277
|
+
const processedFilter = {};
|
|
3278
|
+
Object.entries(filter2).forEach(([key, value]) => {
|
|
3279
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3280
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
3281
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
3282
|
+
});
|
|
3283
|
+
} else {
|
|
3284
|
+
processedFilter[`metadata_${key}`] = value;
|
|
3285
|
+
}
|
|
3286
|
+
});
|
|
3287
|
+
return processedFilter;
|
|
3288
|
+
};
|
|
3289
|
+
const prefixedFilter = processFilterKeys(filter);
|
|
3290
|
+
const whereClause = translator.translate(prefixedFilter);
|
|
3291
|
+
if (!whereClause) {
|
|
3292
|
+
throw new Error("Failed to translate filter to SQL");
|
|
3293
|
+
}
|
|
3294
|
+
await table.delete(whereClause);
|
|
3295
|
+
}
|
|
3296
|
+
return;
|
|
3297
|
+
}
|
|
3298
|
+
} catch (err) {
|
|
3299
|
+
this.logger.error(`Error checking schema for table ${tableName}:` + err);
|
|
3300
|
+
continue;
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3304
|
+
} catch (error$1) {
|
|
3305
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
3306
|
+
throw new error.MastraError(
|
|
3307
|
+
{
|
|
3308
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "FAILED"),
|
|
3309
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3310
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
3311
|
+
details: {
|
|
3312
|
+
indexName,
|
|
3313
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
3314
|
+
...ids && { idsCount: ids.length }
|
|
3315
|
+
}
|
|
3316
|
+
},
|
|
3317
|
+
error$1
|
|
3318
|
+
);
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3199
3321
|
};
|
|
3200
3322
|
|
|
3201
3323
|
exports.LanceStorage = LanceStorage;
|