@mastra/lance 0.0.0-issue-7087-20250910004053 → 0.0.0-jail-fs-20260105160110
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 +1285 -3
- package/README.md +61 -4
- package/dist/docs/README.md +33 -0
- package/dist/docs/SKILL.md +34 -0
- package/dist/docs/SOURCE_MAP.json +6 -0
- package/dist/docs/rag/01-vector-databases.md +638 -0
- package/dist/docs/storage/01-reference.md +113 -0
- package/dist/docs/vectors/01-reference.md +149 -0
- package/dist/index.cjs +1466 -1586
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1465 -1588
- 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 +21 -46
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +27 -22
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +20 -24
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +101 -234
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/filter.d.ts +5 -5
- package/dist/vector/index.d.ts +6 -3
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +16 -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/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,665 +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
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
content: typeof message.content === "string" ? (() => {
|
|
390
|
-
try {
|
|
391
|
-
return JSON.parse(message.content);
|
|
392
|
-
} catch {
|
|
393
|
-
return message.content;
|
|
394
|
-
}
|
|
395
|
-
})() : message.content
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
async getMessages({
|
|
399
|
-
threadId,
|
|
400
|
-
resourceId,
|
|
401
|
-
selectBy,
|
|
402
|
-
format,
|
|
403
|
-
threadConfig
|
|
404
|
-
}) {
|
|
277
|
+
async alterTable({
|
|
278
|
+
tableName,
|
|
279
|
+
schema,
|
|
280
|
+
ifNotExists
|
|
281
|
+
}) {
|
|
405
282
|
try {
|
|
406
|
-
if (!
|
|
407
|
-
|
|
408
|
-
throw new Error("ThreadConfig is not supported by LanceDB storage");
|
|
283
|
+
if (!this.client) {
|
|
284
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
409
285
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
let allRecords = [];
|
|
413
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
414
|
-
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
415
|
-
for (const threadId2 of threadIds) {
|
|
416
|
-
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
417
|
-
let threadRecords = await threadQuery.toArray();
|
|
418
|
-
allRecords.push(...threadRecords);
|
|
419
|
-
}
|
|
420
|
-
} else {
|
|
421
|
-
let query = table.query().where(`\`thread_id\` = '${threadId}'`);
|
|
422
|
-
allRecords = await query.toArray();
|
|
286
|
+
if (!tableName) {
|
|
287
|
+
throw new Error("tableName is required for alterTable.");
|
|
423
288
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const dateB = new Date(b.createdAt).getTime();
|
|
427
|
-
return dateA - dateB;
|
|
428
|
-
});
|
|
429
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
430
|
-
allRecords = this.processMessagesWithContext(allRecords, selectBy.include);
|
|
289
|
+
if (!schema) {
|
|
290
|
+
throw new Error("schema is required for alterTable.");
|
|
431
291
|
}
|
|
432
|
-
if (
|
|
433
|
-
|
|
292
|
+
if (!ifNotExists || ifNotExists.length === 0) {
|
|
293
|
+
this.logger.debug("No columns specified to add in alterTable, skipping.");
|
|
294
|
+
return;
|
|
434
295
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
|
438
306
|
);
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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];
|
|
322
|
+
return {
|
|
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"]})`
|
|
325
|
+
};
|
|
326
|
+
});
|
|
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
|
+
}
|
|
442
331
|
} catch (error$1) {
|
|
443
332
|
throw new error.MastraError(
|
|
444
333
|
{
|
|
445
|
-
id: "
|
|
334
|
+
id: storage.createStorageErrorId("LANCE", "ALTER_TABLE", "FAILED"),
|
|
446
335
|
domain: error.ErrorDomain.STORAGE,
|
|
447
336
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
448
|
-
details: {
|
|
449
|
-
threadId,
|
|
450
|
-
resourceId: resourceId ?? ""
|
|
451
|
-
}
|
|
337
|
+
details: { tableName }
|
|
452
338
|
},
|
|
453
339
|
error$1
|
|
454
340
|
);
|
|
455
341
|
}
|
|
456
342
|
}
|
|
457
|
-
async
|
|
458
|
-
messageIds,
|
|
459
|
-
format
|
|
460
|
-
}) {
|
|
461
|
-
if (messageIds.length === 0) return [];
|
|
343
|
+
async clearTable({ tableName }) {
|
|
462
344
|
try {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
345
|
+
if (!this.client) {
|
|
346
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
347
|
+
}
|
|
348
|
+
if (!tableName) {
|
|
349
|
+
throw new Error("tableName is required for clearTable.");
|
|
350
|
+
}
|
|
351
|
+
} catch (validationError) {
|
|
352
|
+
throw new error.MastraError(
|
|
353
|
+
{
|
|
354
|
+
id: storage.createStorageErrorId("LANCE", "CLEAR_TABLE", "INVALID_ARGS"),
|
|
355
|
+
domain: error.ErrorDomain.STORAGE,
|
|
356
|
+
category: error.ErrorCategory.USER,
|
|
357
|
+
text: validationError.message,
|
|
358
|
+
details: { tableName }
|
|
359
|
+
},
|
|
360
|
+
validationError
|
|
469
361
|
);
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
362
|
+
}
|
|
363
|
+
try {
|
|
364
|
+
const table = await this.client.openTable(tableName);
|
|
365
|
+
await table.delete("1=1");
|
|
473
366
|
} catch (error$1) {
|
|
474
367
|
throw new error.MastraError(
|
|
475
368
|
{
|
|
476
|
-
id: "
|
|
369
|
+
id: storage.createStorageErrorId("LANCE", "CLEAR_TABLE", "FAILED"),
|
|
477
370
|
domain: error.ErrorDomain.STORAGE,
|
|
478
371
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
479
|
-
details: {
|
|
480
|
-
messageIds: JSON.stringify(messageIds)
|
|
481
|
-
}
|
|
372
|
+
details: { tableName }
|
|
482
373
|
},
|
|
483
374
|
error$1
|
|
484
375
|
);
|
|
485
376
|
}
|
|
486
377
|
}
|
|
487
|
-
async
|
|
378
|
+
async insert({ tableName, record }) {
|
|
488
379
|
try {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
return [];
|
|
380
|
+
if (!this.client) {
|
|
381
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
492
382
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
throw new Error("Thread ID is required");
|
|
383
|
+
if (!tableName) {
|
|
384
|
+
throw new Error("tableName is required for insert.");
|
|
496
385
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
throw new Error("Message ID is required");
|
|
500
|
-
}
|
|
501
|
-
if (!message.threadId) {
|
|
502
|
-
throw new Error("Thread ID is required for all messages");
|
|
503
|
-
}
|
|
504
|
-
if (message.resourceId === null || message.resourceId === void 0) {
|
|
505
|
-
throw new Error("Resource ID cannot be null or undefined");
|
|
506
|
-
}
|
|
507
|
-
if (!message.content) {
|
|
508
|
-
throw new Error("Message content is required");
|
|
509
|
-
}
|
|
386
|
+
if (!record || Object.keys(record).length === 0) {
|
|
387
|
+
throw new Error("record is required and cannot be empty for insert.");
|
|
510
388
|
}
|
|
511
|
-
|
|
512
|
-
const { threadId: threadId2, type, ...rest } = message;
|
|
513
|
-
return {
|
|
514
|
-
...rest,
|
|
515
|
-
thread_id: threadId2,
|
|
516
|
-
type: type ?? "v2",
|
|
517
|
-
content: JSON.stringify(message.content)
|
|
518
|
-
};
|
|
519
|
-
});
|
|
520
|
-
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
521
|
-
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
522
|
-
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
523
|
-
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
524
|
-
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
525
|
-
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
526
|
-
const list = new agent.MessageList().add(messages, "memory");
|
|
527
|
-
if (format === `v2`) return list.get.all.v2();
|
|
528
|
-
return list.get.all.v1();
|
|
529
|
-
} catch (error$1) {
|
|
389
|
+
} catch (validationError) {
|
|
530
390
|
throw new error.MastraError(
|
|
531
391
|
{
|
|
532
|
-
id: "
|
|
392
|
+
id: storage.createStorageErrorId("LANCE", "INSERT", "INVALID_ARGS"),
|
|
533
393
|
domain: error.ErrorDomain.STORAGE,
|
|
534
|
-
category: error.ErrorCategory.
|
|
394
|
+
category: error.ErrorCategory.USER,
|
|
395
|
+
text: validationError.message,
|
|
396
|
+
details: { tableName }
|
|
535
397
|
},
|
|
536
|
-
|
|
398
|
+
validationError
|
|
537
399
|
);
|
|
538
400
|
}
|
|
539
|
-
}
|
|
540
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
541
401
|
try {
|
|
542
|
-
const
|
|
543
|
-
const
|
|
544
|
-
const
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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]);
|
|
409
|
+
}
|
|
550
410
|
}
|
|
551
|
-
|
|
552
|
-
records.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
553
|
-
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
554
|
-
const threads = records.map((record) => processResultWithTypeConversion(record, schema));
|
|
555
|
-
return {
|
|
556
|
-
threads,
|
|
557
|
-
total,
|
|
558
|
-
page,
|
|
559
|
-
perPage,
|
|
560
|
-
hasMore: total > (page + 1) * perPage
|
|
561
|
-
};
|
|
411
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([processedRecord]);
|
|
562
412
|
} catch (error$1) {
|
|
563
413
|
throw new error.MastraError(
|
|
564
414
|
{
|
|
565
|
-
id: "
|
|
415
|
+
id: storage.createStorageErrorId("LANCE", "INSERT", "FAILED"),
|
|
566
416
|
domain: error.ErrorDomain.STORAGE,
|
|
567
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
417
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
418
|
+
details: { tableName }
|
|
568
419
|
},
|
|
569
420
|
error$1
|
|
570
421
|
);
|
|
571
422
|
}
|
|
572
423
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
424
|
+
async batchInsert({ tableName, records }) {
|
|
425
|
+
try {
|
|
426
|
+
if (!this.client) {
|
|
427
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
428
|
+
}
|
|
429
|
+
if (!tableName) {
|
|
430
|
+
throw new Error("tableName is required for batchInsert.");
|
|
431
|
+
}
|
|
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
|
+
);
|
|
583
446
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
594
|
-
for (let i = startIdx; i < messageIndex; i++) {
|
|
595
|
-
additionalIndices.add(i);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
if (item.withNextMessages) {
|
|
599
|
-
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
600
|
-
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
601
|
-
additionalIndices.add(i);
|
|
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]);
|
|
602
456
|
}
|
|
603
457
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
458
|
+
return processedRecord;
|
|
459
|
+
});
|
|
460
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(processedRecords);
|
|
461
|
+
} catch (error$1) {
|
|
462
|
+
throw new error.MastraError(
|
|
463
|
+
{
|
|
464
|
+
id: storage.createStorageErrorId("LANCE", "BATCH_INSERT", "FAILED"),
|
|
465
|
+
domain: error.ErrorDomain.STORAGE,
|
|
466
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
467
|
+
details: { tableName }
|
|
468
|
+
},
|
|
469
|
+
error$1
|
|
470
|
+
);
|
|
608
471
|
}
|
|
609
|
-
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
610
|
-
const allIndices = /* @__PURE__ */ new Set();
|
|
611
|
-
records.forEach((record, index) => {
|
|
612
|
-
if (originalMatchIds.has(record.id)) {
|
|
613
|
-
allIndices.add(index);
|
|
614
|
-
}
|
|
615
|
-
});
|
|
616
|
-
additionalIndices.forEach((index) => {
|
|
617
|
-
allIndices.add(index);
|
|
618
|
-
});
|
|
619
|
-
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
620
472
|
}
|
|
621
|
-
async
|
|
622
|
-
const { threadId, resourceId, selectBy, format = "v1" } = args;
|
|
623
|
-
const page = selectBy?.pagination?.page ?? 0;
|
|
624
|
-
const perPage = selectBy?.pagination?.perPage ?? 10;
|
|
473
|
+
async load({ tableName, keys }) {
|
|
625
474
|
try {
|
|
626
|
-
if (!
|
|
627
|
-
|
|
628
|
-
const fromDate = dateRange?.start;
|
|
629
|
-
const toDate = dateRange?.end;
|
|
630
|
-
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
631
|
-
const messages = [];
|
|
632
|
-
if (selectBy?.include && Array.isArray(selectBy.include)) {
|
|
633
|
-
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
634
|
-
const allThreadMessages = [];
|
|
635
|
-
for (const threadId2 of threadIds) {
|
|
636
|
-
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
637
|
-
let threadRecords = await threadQuery.toArray();
|
|
638
|
-
if (fromDate) threadRecords = threadRecords.filter((m) => m.createdAt >= fromDate.getTime());
|
|
639
|
-
if (toDate) threadRecords = threadRecords.filter((m) => m.createdAt <= toDate.getTime());
|
|
640
|
-
allThreadMessages.push(...threadRecords);
|
|
641
|
-
}
|
|
642
|
-
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
643
|
-
const contextMessages = this.processMessagesWithContext(allThreadMessages, selectBy.include);
|
|
644
|
-
messages.push(...contextMessages);
|
|
475
|
+
if (!this.client) {
|
|
476
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
645
477
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
conditions.push(`\`resourceId\` = '${resourceId}'`);
|
|
649
|
-
}
|
|
650
|
-
if (fromDate) {
|
|
651
|
-
conditions.push(`\`createdAt\` >= ${fromDate.getTime()}`);
|
|
478
|
+
if (!tableName) {
|
|
479
|
+
throw new Error("tableName is required for load.");
|
|
652
480
|
}
|
|
653
|
-
if (
|
|
654
|
-
|
|
481
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
482
|
+
throw new Error("keys are required and cannot be empty for load.");
|
|
655
483
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
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);
|
|
661
515
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
page,
|
|
667
|
-
perPage,
|
|
668
|
-
hasMore: false
|
|
669
|
-
};
|
|
516
|
+
const result = await query.limit(1).toArray();
|
|
517
|
+
if (result.length === 0) {
|
|
518
|
+
this.logger.debug("No record found");
|
|
519
|
+
return null;
|
|
670
520
|
}
|
|
671
|
-
|
|
672
|
-
let selectedMessages = [];
|
|
673
|
-
if (selectBy?.last && selectBy.last > 0) {
|
|
674
|
-
const query = table.query();
|
|
675
|
-
if (conditions.length > 0) {
|
|
676
|
-
query.where(conditions.join(" AND "));
|
|
677
|
-
}
|
|
678
|
-
let records = await query.toArray();
|
|
679
|
-
records = records.sort((a, b) => a.createdAt - b.createdAt);
|
|
680
|
-
if (excludeIds.length > 0) {
|
|
681
|
-
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
682
|
-
}
|
|
683
|
-
selectedMessages = records.slice(-selectBy.last);
|
|
684
|
-
} else {
|
|
685
|
-
const query = table.query();
|
|
686
|
-
if (conditions.length > 0) {
|
|
687
|
-
query.where(conditions.join(" AND "));
|
|
688
|
-
}
|
|
689
|
-
let records = await query.toArray();
|
|
690
|
-
records = records.sort((a, b) => a.createdAt - b.createdAt);
|
|
691
|
-
if (excludeIds.length > 0) {
|
|
692
|
-
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
693
|
-
}
|
|
694
|
-
selectedMessages = records.slice(page * perPage, (page + 1) * perPage);
|
|
695
|
-
}
|
|
696
|
-
const allMessages = [...messages, ...selectedMessages];
|
|
697
|
-
const seen = /* @__PURE__ */ new Set();
|
|
698
|
-
const dedupedMessages = allMessages.filter((m) => {
|
|
699
|
-
const key = `${m.id}:${m.thread_id}`;
|
|
700
|
-
if (seen.has(key)) return false;
|
|
701
|
-
seen.add(key);
|
|
702
|
-
return true;
|
|
703
|
-
});
|
|
704
|
-
const formattedMessages = dedupedMessages.map((msg) => {
|
|
705
|
-
const { thread_id, ...rest } = msg;
|
|
706
|
-
return {
|
|
707
|
-
...rest,
|
|
708
|
-
threadId: thread_id,
|
|
709
|
-
content: typeof msg.content === "string" ? (() => {
|
|
710
|
-
try {
|
|
711
|
-
return JSON.parse(msg.content);
|
|
712
|
-
} catch {
|
|
713
|
-
return msg.content;
|
|
714
|
-
}
|
|
715
|
-
})() : msg.content
|
|
716
|
-
};
|
|
717
|
-
});
|
|
718
|
-
const list = new agent.MessageList().add(formattedMessages, "memory");
|
|
719
|
-
return {
|
|
720
|
-
messages: format === "v2" ? list.get.all.v2() : list.get.all.v1(),
|
|
721
|
-
total,
|
|
722
|
-
// Total should be the count of messages matching the filters
|
|
723
|
-
page,
|
|
724
|
-
perPage,
|
|
725
|
-
hasMore: total > (page + 1) * perPage
|
|
726
|
-
};
|
|
521
|
+
return processResultWithTypeConversion(result[0], tableSchema);
|
|
727
522
|
} catch (error$1) {
|
|
728
|
-
|
|
523
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
524
|
+
throw new error.MastraError(
|
|
729
525
|
{
|
|
730
|
-
id: "
|
|
526
|
+
id: storage.createStorageErrorId("LANCE", "LOAD", "FAILED"),
|
|
731
527
|
domain: error.ErrorDomain.STORAGE,
|
|
732
528
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
733
|
-
details: {
|
|
734
|
-
threadId,
|
|
735
|
-
resourceId: resourceId ?? ""
|
|
736
|
-
}
|
|
529
|
+
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
737
530
|
},
|
|
738
531
|
error$1
|
|
739
532
|
);
|
|
740
|
-
this.logger?.trackException?.(mastraError);
|
|
741
|
-
this.logger?.error?.(mastraError.toString());
|
|
742
|
-
return { messages: [], total: 0, page, perPage, hasMore: false };
|
|
743
533
|
}
|
|
744
534
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
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
|
+
});
|
|
763
556
|
}
|
|
764
|
-
async
|
|
765
|
-
|
|
766
|
-
this.
|
|
767
|
-
|
|
768
|
-
|
|
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;
|
|
769
565
|
}
|
|
770
|
-
|
|
771
|
-
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
566
|
+
this.logger.debug("Deleting messages", { count: messageIds.length });
|
|
772
567
|
try {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
const
|
|
776
|
-
if (
|
|
777
|
-
|
|
778
|
-
continue;
|
|
779
|
-
}
|
|
780
|
-
const existingMsg = this.parseMessageData(existingMessage);
|
|
781
|
-
const originalThreadId = existingMsg.threadId;
|
|
782
|
-
affectedThreadIds.add(originalThreadId);
|
|
783
|
-
const updatePayload = {};
|
|
784
|
-
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
785
|
-
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
786
|
-
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
787
|
-
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
788
|
-
updatePayload.thread_id = updates.threadId;
|
|
789
|
-
affectedThreadIds.add(updates.threadId);
|
|
790
|
-
}
|
|
791
|
-
if (updates.content) {
|
|
792
|
-
const existingContent = existingMsg.content;
|
|
793
|
-
let newContent = { ...existingContent };
|
|
794
|
-
if (updates.content.metadata !== void 0) {
|
|
795
|
-
newContent.metadata = {
|
|
796
|
-
...existingContent.metadata || {},
|
|
797
|
-
...updates.content.metadata || {}
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
if (updates.content.content !== void 0) {
|
|
801
|
-
newContent.content = updates.content.content;
|
|
802
|
-
}
|
|
803
|
-
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
804
|
-
newContent.parts = updates.content.parts;
|
|
805
|
-
}
|
|
806
|
-
updatePayload.content = JSON.stringify(newContent);
|
|
807
|
-
}
|
|
808
|
-
await this.operations.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
809
|
-
const updatedMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
810
|
-
if (updatedMessage) {
|
|
811
|
-
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
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);
|
|
812
573
|
}
|
|
813
574
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
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]);
|
|
592
|
+
}
|
|
819
593
|
}
|
|
820
|
-
return updatedMessages;
|
|
821
594
|
} catch (error$1) {
|
|
822
595
|
throw new error.MastraError(
|
|
823
596
|
{
|
|
824
|
-
id: "
|
|
597
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_MESSAGES", "FAILED"),
|
|
825
598
|
domain: error.ErrorDomain.STORAGE,
|
|
826
599
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
827
|
-
details: { count:
|
|
600
|
+
details: { count: messageIds.length }
|
|
828
601
|
},
|
|
829
602
|
error$1
|
|
830
603
|
);
|
|
831
604
|
}
|
|
832
605
|
}
|
|
833
|
-
|
|
606
|
+
// Utility to escape single quotes in SQL strings
|
|
607
|
+
escapeSql(str) {
|
|
608
|
+
return str.replace(/'/g, "''");
|
|
609
|
+
}
|
|
610
|
+
async getThreadById({ threadId }) {
|
|
834
611
|
try {
|
|
835
|
-
const
|
|
836
|
-
if (!
|
|
612
|
+
const thread = await this.#db.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
613
|
+
if (!thread) {
|
|
837
614
|
return null;
|
|
838
615
|
}
|
|
839
|
-
let createdAt;
|
|
840
|
-
let updatedAt;
|
|
841
|
-
try {
|
|
842
|
-
if (resource.createdAt instanceof Date) {
|
|
843
|
-
createdAt = resource.createdAt;
|
|
844
|
-
} else if (typeof resource.createdAt === "string") {
|
|
845
|
-
createdAt = new Date(resource.createdAt);
|
|
846
|
-
} else if (typeof resource.createdAt === "number") {
|
|
847
|
-
createdAt = new Date(resource.createdAt);
|
|
848
|
-
} else {
|
|
849
|
-
createdAt = /* @__PURE__ */ new Date();
|
|
850
|
-
}
|
|
851
|
-
if (isNaN(createdAt.getTime())) {
|
|
852
|
-
createdAt = /* @__PURE__ */ new Date();
|
|
853
|
-
}
|
|
854
|
-
} catch {
|
|
855
|
-
createdAt = /* @__PURE__ */ new Date();
|
|
856
|
-
}
|
|
857
|
-
try {
|
|
858
|
-
if (resource.updatedAt instanceof Date) {
|
|
859
|
-
updatedAt = resource.updatedAt;
|
|
860
|
-
} else if (typeof resource.updatedAt === "string") {
|
|
861
|
-
updatedAt = new Date(resource.updatedAt);
|
|
862
|
-
} else if (typeof resource.updatedAt === "number") {
|
|
863
|
-
updatedAt = new Date(resource.updatedAt);
|
|
864
|
-
} else {
|
|
865
|
-
updatedAt = /* @__PURE__ */ new Date();
|
|
866
|
-
}
|
|
867
|
-
if (isNaN(updatedAt.getTime())) {
|
|
868
|
-
updatedAt = /* @__PURE__ */ new Date();
|
|
869
|
-
}
|
|
870
|
-
} catch {
|
|
871
|
-
updatedAt = /* @__PURE__ */ new Date();
|
|
872
|
-
}
|
|
873
|
-
let workingMemory = resource.workingMemory;
|
|
874
|
-
if (workingMemory === null || workingMemory === void 0) {
|
|
875
|
-
workingMemory = void 0;
|
|
876
|
-
} else if (workingMemory === "") {
|
|
877
|
-
workingMemory = "";
|
|
878
|
-
} else if (typeof workingMemory === "object") {
|
|
879
|
-
workingMemory = JSON.stringify(workingMemory);
|
|
880
|
-
}
|
|
881
|
-
let metadata = resource.metadata;
|
|
882
|
-
if (metadata === "" || metadata === null || metadata === void 0) {
|
|
883
|
-
metadata = void 0;
|
|
884
|
-
} else if (typeof metadata === "string") {
|
|
885
|
-
try {
|
|
886
|
-
metadata = JSON.parse(metadata);
|
|
887
|
-
} catch {
|
|
888
|
-
metadata = metadata;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
616
|
return {
|
|
892
|
-
...
|
|
893
|
-
createdAt,
|
|
894
|
-
updatedAt
|
|
895
|
-
workingMemory,
|
|
896
|
-
metadata
|
|
617
|
+
...thread,
|
|
618
|
+
createdAt: new Date(thread.createdAt),
|
|
619
|
+
updatedAt: new Date(thread.updatedAt)
|
|
897
620
|
};
|
|
898
621
|
} catch (error$1) {
|
|
899
622
|
throw new error.MastraError(
|
|
900
623
|
{
|
|
901
|
-
id: "
|
|
624
|
+
id: storage.createStorageErrorId("LANCE", "GET_THREAD_BY_ID", "FAILED"),
|
|
902
625
|
domain: error.ErrorDomain.STORAGE,
|
|
903
626
|
category: error.ErrorCategory.THIRD_PARTY
|
|
904
627
|
},
|
|
@@ -906,23 +629,21 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
906
629
|
);
|
|
907
630
|
}
|
|
908
631
|
}
|
|
909
|
-
|
|
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 }) {
|
|
910
638
|
try {
|
|
911
|
-
const record = {
|
|
912
|
-
|
|
913
|
-
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
914
|
-
createdAt: resource.createdAt.getTime(),
|
|
915
|
-
// Store as timestamp (milliseconds)
|
|
916
|
-
updatedAt: resource.updatedAt.getTime()
|
|
917
|
-
// Store as timestamp (milliseconds)
|
|
918
|
-
};
|
|
919
|
-
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);
|
|
920
641
|
await table.add([record], { mode: "append" });
|
|
921
|
-
return
|
|
642
|
+
return thread;
|
|
922
643
|
} catch (error$1) {
|
|
923
644
|
throw new error.MastraError(
|
|
924
645
|
{
|
|
925
|
-
id: "
|
|
646
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_THREAD", "FAILED"),
|
|
926
647
|
domain: error.ErrorDomain.STORAGE,
|
|
927
648
|
category: error.ErrorCategory.THIRD_PARTY
|
|
928
649
|
},
|
|
@@ -930,44 +651,32 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
930
651
|
);
|
|
931
652
|
}
|
|
932
653
|
}
|
|
933
|
-
async
|
|
934
|
-
|
|
935
|
-
|
|
654
|
+
async updateThread({
|
|
655
|
+
id,
|
|
656
|
+
title,
|
|
936
657
|
metadata
|
|
937
658
|
}) {
|
|
938
|
-
const maxRetries =
|
|
659
|
+
const maxRetries = 5;
|
|
939
660
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
940
661
|
try {
|
|
941
|
-
const
|
|
942
|
-
if (!
|
|
943
|
-
|
|
944
|
-
id: resourceId,
|
|
945
|
-
workingMemory,
|
|
946
|
-
metadata: metadata || {},
|
|
947
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
948
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
949
|
-
};
|
|
950
|
-
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`);
|
|
951
665
|
}
|
|
952
|
-
const
|
|
953
|
-
...existingResource,
|
|
954
|
-
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
955
|
-
metadata: {
|
|
956
|
-
...existingResource.metadata,
|
|
957
|
-
...metadata
|
|
958
|
-
},
|
|
959
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
960
|
-
};
|
|
666
|
+
const mergedMetadata = { ...current.metadata, ...metadata };
|
|
961
667
|
const record = {
|
|
962
|
-
id
|
|
963
|
-
|
|
964
|
-
metadata:
|
|
965
|
-
updatedAt:
|
|
966
|
-
// Store as timestamp (milliseconds)
|
|
668
|
+
id,
|
|
669
|
+
title,
|
|
670
|
+
metadata: JSON.stringify(mergedMetadata),
|
|
671
|
+
updatedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
967
672
|
};
|
|
968
|
-
const table = await this.client.openTable(storage.
|
|
673
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
969
674
|
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
970
|
-
|
|
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;
|
|
971
680
|
} catch (error$1) {
|
|
972
681
|
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
973
682
|
const delay = Math.pow(2, attempt) * 10;
|
|
@@ -976,7 +685,7 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
976
685
|
}
|
|
977
686
|
throw new error.MastraError(
|
|
978
687
|
{
|
|
979
|
-
id: "
|
|
688
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_THREAD", "FAILED"),
|
|
980
689
|
domain: error.ErrorDomain.STORAGE,
|
|
981
690
|
category: error.ErrorCategory.THIRD_PARTY
|
|
982
691
|
},
|
|
@@ -984,445 +693,681 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
984
693
|
);
|
|
985
694
|
}
|
|
986
695
|
}
|
|
987
|
-
throw new
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
}
|
|
996
|
-
getDefaultValue(type) {
|
|
997
|
-
switch (type) {
|
|
998
|
-
case "text":
|
|
999
|
-
return "''";
|
|
1000
|
-
case "timestamp":
|
|
1001
|
-
return "CURRENT_TIMESTAMP";
|
|
1002
|
-
case "integer":
|
|
1003
|
-
case "bigint":
|
|
1004
|
-
return "0";
|
|
1005
|
-
case "jsonb":
|
|
1006
|
-
return "'{}'";
|
|
1007
|
-
case "uuid":
|
|
1008
|
-
return "''";
|
|
1009
|
-
default:
|
|
1010
|
-
return super.getDefaultValue(type);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
async hasColumn(tableName, columnName) {
|
|
1014
|
-
const table = await this.client.openTable(tableName);
|
|
1015
|
-
const schema = await table.schema();
|
|
1016
|
-
return schema.fields.some((field) => field.name === columnName);
|
|
1017
|
-
}
|
|
1018
|
-
translateSchema(schema) {
|
|
1019
|
-
const fields = Object.entries(schema).map(([name, column]) => {
|
|
1020
|
-
let arrowType;
|
|
1021
|
-
switch (column.type.toLowerCase()) {
|
|
1022
|
-
case "text":
|
|
1023
|
-
case "uuid":
|
|
1024
|
-
arrowType = new apacheArrow.Utf8();
|
|
1025
|
-
break;
|
|
1026
|
-
case "int":
|
|
1027
|
-
case "integer":
|
|
1028
|
-
arrowType = new apacheArrow.Int32();
|
|
1029
|
-
break;
|
|
1030
|
-
case "bigint":
|
|
1031
|
-
arrowType = new apacheArrow.Float64();
|
|
1032
|
-
break;
|
|
1033
|
-
case "float":
|
|
1034
|
-
arrowType = new apacheArrow.Float32();
|
|
1035
|
-
break;
|
|
1036
|
-
case "jsonb":
|
|
1037
|
-
case "json":
|
|
1038
|
-
arrowType = new apacheArrow.Utf8();
|
|
1039
|
-
break;
|
|
1040
|
-
case "binary":
|
|
1041
|
-
arrowType = new apacheArrow.Binary();
|
|
1042
|
-
break;
|
|
1043
|
-
case "timestamp":
|
|
1044
|
-
arrowType = new apacheArrow.Float64();
|
|
1045
|
-
break;
|
|
1046
|
-
default:
|
|
1047
|
-
arrowType = new apacheArrow.Utf8();
|
|
1048
|
-
}
|
|
1049
|
-
return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
|
|
1050
|
-
});
|
|
1051
|
-
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
|
+
);
|
|
1052
704
|
}
|
|
1053
|
-
async
|
|
1054
|
-
tableName,
|
|
1055
|
-
schema
|
|
1056
|
-
}) {
|
|
705
|
+
async deleteThread({ threadId }) {
|
|
1057
706
|
try {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
throw new Error("tableName is required for createTable.");
|
|
1063
|
-
}
|
|
1064
|
-
if (!schema) {
|
|
1065
|
-
throw new Error("schema is required for createTable.");
|
|
1066
|
-
}
|
|
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}'`);
|
|
1067
711
|
} catch (error$1) {
|
|
1068
712
|
throw new error.MastraError(
|
|
1069
713
|
{
|
|
1070
|
-
id: "
|
|
714
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_THREAD", "FAILED"),
|
|
1071
715
|
domain: error.ErrorDomain.STORAGE,
|
|
1072
|
-
category: error.ErrorCategory.
|
|
1073
|
-
details: { tableName }
|
|
716
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1074
717
|
},
|
|
1075
718
|
error$1
|
|
1076
719
|
);
|
|
1077
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: [] };
|
|
1078
738
|
try {
|
|
1079
|
-
const
|
|
1080
|
-
|
|
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() };
|
|
1081
751
|
} catch (error$1) {
|
|
1082
|
-
if (error$1.message?.includes("already exists")) {
|
|
1083
|
-
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
752
|
throw new error.MastraError(
|
|
1087
753
|
{
|
|
1088
|
-
id: "
|
|
754
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
1089
755
|
domain: error.ErrorDomain.STORAGE,
|
|
1090
756
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1091
|
-
details: {
|
|
757
|
+
details: {
|
|
758
|
+
messageIds: JSON.stringify(messageIds)
|
|
759
|
+
}
|
|
1092
760
|
},
|
|
1093
761
|
error$1
|
|
1094
762
|
);
|
|
1095
763
|
}
|
|
1096
764
|
}
|
|
1097
|
-
async
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
}
|
|
1102
|
-
if (!tableName) {
|
|
1103
|
-
throw new Error("tableName is required for dropTable.");
|
|
1104
|
-
}
|
|
1105
|
-
} catch (validationError) {
|
|
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())) {
|
|
1106
769
|
throw new error.MastraError(
|
|
1107
770
|
{
|
|
1108
|
-
id: "
|
|
771
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
1109
772
|
domain: error.ErrorDomain.STORAGE,
|
|
1110
|
-
category: error.ErrorCategory.
|
|
1111
|
-
|
|
1112
|
-
details: { tableName }
|
|
773
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
774
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
1113
775
|
},
|
|
1114
|
-
|
|
776
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
1115
777
|
);
|
|
1116
778
|
}
|
|
779
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
780
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1117
781
|
try {
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
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
|
+
);
|
|
1123
792
|
}
|
|
1124
|
-
|
|
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)}'`);
|
|
799
|
+
}
|
|
800
|
+
if (filter?.dateRange?.start) {
|
|
801
|
+
const startTime = filter.dateRange.start instanceof Date ? filter.dateRange.start.getTime() : new Date(filter.dateRange.start).getTime();
|
|
802
|
+
const startOp = filter.dateRange.startExclusive ? ">" : ">=";
|
|
803
|
+
conditions.push(`\`createdAt\` ${startOp} ${startTime}`);
|
|
804
|
+
}
|
|
805
|
+
if (filter?.dateRange?.end) {
|
|
806
|
+
const endTime = filter.dateRange.end instanceof Date ? filter.dateRange.end.getTime() : new Date(filter.dateRange.end).getTime();
|
|
807
|
+
const endOp = filter.dateRange.endExclusive ? "<" : "<=";
|
|
808
|
+
conditions.push(`\`createdAt\` ${endOp} ${endTime}`);
|
|
809
|
+
}
|
|
810
|
+
const whereClause = conditions.join(" AND ");
|
|
811
|
+
const total = await table.countRows(whereClause);
|
|
812
|
+
const query = table.query().where(whereClause);
|
|
813
|
+
let allRecords = await query.toArray();
|
|
814
|
+
allRecords.sort((a, b) => {
|
|
815
|
+
const aValue = field === "createdAt" ? a.createdAt : a[field];
|
|
816
|
+
const bValue = field === "createdAt" ? b.createdAt : b[field];
|
|
817
|
+
if (aValue == null && bValue == null) return 0;
|
|
818
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
819
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
820
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
821
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
822
|
+
}
|
|
823
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
824
|
+
});
|
|
825
|
+
const paginatedRecords = allRecords.slice(offset, offset + perPage);
|
|
826
|
+
const messages = paginatedRecords.map((row) => this.normalizeMessage(row));
|
|
827
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
828
|
+
return {
|
|
829
|
+
messages: [],
|
|
830
|
+
total: 0,
|
|
831
|
+
page,
|
|
832
|
+
perPage: perPageForResponse,
|
|
833
|
+
hasMore: false
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
837
|
+
if (include && include.length > 0) {
|
|
838
|
+
const threadIds2 = [...new Set(include.map((item) => item.threadId || threadId))];
|
|
839
|
+
const allThreadMessages = [];
|
|
840
|
+
for (const tid of threadIds2) {
|
|
841
|
+
const threadQuery = table.query().where(`thread_id = '${tid}'`);
|
|
842
|
+
let threadRecords = await threadQuery.toArray();
|
|
843
|
+
allThreadMessages.push(...threadRecords);
|
|
844
|
+
}
|
|
845
|
+
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
846
|
+
const contextMessages = this.processMessagesWithContext(allThreadMessages, include);
|
|
847
|
+
const includedMessages = contextMessages.map((row) => this.normalizeMessage(row));
|
|
848
|
+
for (const includeMsg of includedMessages) {
|
|
849
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
850
|
+
messages.push(includeMsg);
|
|
851
|
+
messageIds.add(includeMsg.id);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
856
|
+
let finalMessages = list.get.all.db();
|
|
857
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
858
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
859
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
860
|
+
if (aValue == null && bValue == null) return 0;
|
|
861
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
862
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
863
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
864
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
865
|
+
}
|
|
866
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
867
|
+
});
|
|
868
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
869
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
870
|
+
const fetchedAll = perPageInput === false || allThreadMessagesReturned;
|
|
871
|
+
const hasMore = !fetchedAll && offset + perPage < total;
|
|
872
|
+
return {
|
|
873
|
+
messages: finalMessages,
|
|
874
|
+
total,
|
|
875
|
+
page,
|
|
876
|
+
perPage: perPageForResponse,
|
|
877
|
+
hasMore
|
|
878
|
+
};
|
|
879
|
+
} catch (error$1) {
|
|
880
|
+
const mastraError = new error.MastraError(
|
|
1125
881
|
{
|
|
1126
|
-
id: "
|
|
882
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "FAILED"),
|
|
1127
883
|
domain: error.ErrorDomain.STORAGE,
|
|
1128
884
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1129
|
-
details: {
|
|
885
|
+
details: {
|
|
886
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
887
|
+
resourceId: resourceId ?? ""
|
|
888
|
+
}
|
|
1130
889
|
},
|
|
1131
890
|
error$1
|
|
1132
891
|
);
|
|
892
|
+
this.logger?.error?.(mastraError.toString());
|
|
893
|
+
this.logger?.trackException?.(mastraError);
|
|
894
|
+
return {
|
|
895
|
+
messages: [],
|
|
896
|
+
total: 0,
|
|
897
|
+
page,
|
|
898
|
+
perPage: perPageForResponse,
|
|
899
|
+
hasMore: false
|
|
900
|
+
};
|
|
1133
901
|
}
|
|
1134
902
|
}
|
|
1135
|
-
async
|
|
1136
|
-
tableName,
|
|
1137
|
-
schema,
|
|
1138
|
-
ifNotExists
|
|
1139
|
-
}) {
|
|
903
|
+
async saveMessages(args) {
|
|
1140
904
|
try {
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
if (!tableName) {
|
|
1145
|
-
throw new Error("tableName is required for alterTable.");
|
|
905
|
+
const { messages } = args;
|
|
906
|
+
if (messages.length === 0) {
|
|
907
|
+
return { messages: [] };
|
|
1146
908
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
909
|
+
const threadId = messages[0]?.threadId;
|
|
910
|
+
if (!threadId) {
|
|
911
|
+
throw new Error("Thread ID is required");
|
|
1149
912
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
913
|
+
for (const message of messages) {
|
|
914
|
+
if (!message.id) {
|
|
915
|
+
throw new Error("Message ID is required");
|
|
916
|
+
}
|
|
917
|
+
if (!message.threadId) {
|
|
918
|
+
throw new Error("Thread ID is required for all messages");
|
|
919
|
+
}
|
|
920
|
+
if (message.resourceId === null || message.resourceId === void 0) {
|
|
921
|
+
throw new Error("Resource ID cannot be null or undefined");
|
|
922
|
+
}
|
|
923
|
+
if (!message.content) {
|
|
924
|
+
throw new Error("Message content is required");
|
|
925
|
+
}
|
|
1153
926
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
{
|
|
1157
|
-
id: "STORAGE_LANCE_STORAGE_ALTER_TABLE_INVALID_ARGS",
|
|
1158
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1159
|
-
category: error.ErrorCategory.USER,
|
|
1160
|
-
text: validationError.message,
|
|
1161
|
-
details: { tableName }
|
|
1162
|
-
},
|
|
1163
|
-
validationError
|
|
1164
|
-
);
|
|
1165
|
-
}
|
|
1166
|
-
try {
|
|
1167
|
-
const table = await this.client.openTable(tableName);
|
|
1168
|
-
const currentSchema = await table.schema();
|
|
1169
|
-
const existingFields = new Set(currentSchema.fields.map((f) => f.name));
|
|
1170
|
-
const typeMap = {
|
|
1171
|
-
text: "string",
|
|
1172
|
-
integer: "int",
|
|
1173
|
-
bigint: "bigint",
|
|
1174
|
-
timestamp: "timestamp",
|
|
1175
|
-
jsonb: "string",
|
|
1176
|
-
uuid: "string"
|
|
1177
|
-
};
|
|
1178
|
-
const columnsToAdd = ifNotExists.filter((col) => schema[col] && !existingFields.has(col)).map((col) => {
|
|
1179
|
-
const colDef = schema[col];
|
|
927
|
+
const transformedMessages = messages.map((message) => {
|
|
928
|
+
const { threadId: threadId2, type, ...rest } = message;
|
|
1180
929
|
return {
|
|
1181
|
-
|
|
1182
|
-
|
|
930
|
+
...rest,
|
|
931
|
+
thread_id: threadId2,
|
|
932
|
+
type: type ?? "v2",
|
|
933
|
+
content: JSON.stringify(message.content)
|
|
1183
934
|
};
|
|
1184
935
|
});
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
936
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
937
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
938
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
939
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
940
|
+
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
941
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
942
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
943
|
+
return { messages: list.get.all.db() };
|
|
1189
944
|
} catch (error$1) {
|
|
1190
945
|
throw new error.MastraError(
|
|
1191
946
|
{
|
|
1192
|
-
id: "
|
|
947
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_MESSAGES", "FAILED"),
|
|
1193
948
|
domain: error.ErrorDomain.STORAGE,
|
|
1194
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1195
|
-
details: { tableName }
|
|
949
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1196
950
|
},
|
|
1197
951
|
error$1
|
|
1198
952
|
);
|
|
1199
953
|
}
|
|
1200
954
|
}
|
|
1201
|
-
async
|
|
955
|
+
async listThreadsByResourceId(args) {
|
|
1202
956
|
try {
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
957
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
958
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
959
|
+
if (page < 0) {
|
|
960
|
+
throw new error.MastraError(
|
|
961
|
+
{
|
|
962
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
963
|
+
domain: error.ErrorDomain.STORAGE,
|
|
964
|
+
category: error.ErrorCategory.USER,
|
|
965
|
+
details: { page }
|
|
966
|
+
},
|
|
967
|
+
new Error("page must be >= 0")
|
|
968
|
+
);
|
|
1208
969
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
970
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
971
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
972
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
973
|
+
const total = await table.countRows(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
974
|
+
const query = table.query().where(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
975
|
+
const records = await query.toArray();
|
|
976
|
+
records.sort((a, b) => {
|
|
977
|
+
const aValue = ["createdAt", "updatedAt"].includes(field) ? new Date(a[field]).getTime() : a[field];
|
|
978
|
+
const bValue = ["createdAt", "updatedAt"].includes(field) ? new Date(b[field]).getTime() : b[field];
|
|
979
|
+
if (aValue == null && bValue == null) return 0;
|
|
980
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
981
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
982
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
983
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
984
|
+
}
|
|
985
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
986
|
+
});
|
|
987
|
+
const paginatedRecords = records.slice(offset, offset + perPage);
|
|
988
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
989
|
+
const threads = paginatedRecords.map(
|
|
990
|
+
(record) => processResultWithTypeConversion(record, schema)
|
|
1219
991
|
);
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
992
|
+
return {
|
|
993
|
+
threads,
|
|
994
|
+
total,
|
|
995
|
+
page,
|
|
996
|
+
perPage: perPageForResponse,
|
|
997
|
+
hasMore: offset + perPage < total
|
|
998
|
+
};
|
|
1224
999
|
} catch (error$1) {
|
|
1225
1000
|
throw new error.MastraError(
|
|
1226
1001
|
{
|
|
1227
|
-
id: "
|
|
1002
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
|
|
1228
1003
|
domain: error.ErrorDomain.STORAGE,
|
|
1229
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1230
|
-
details: { tableName }
|
|
1004
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1231
1005
|
},
|
|
1232
1006
|
error$1
|
|
1233
1007
|
);
|
|
1234
1008
|
}
|
|
1235
1009
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1010
|
+
/**
|
|
1011
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
1012
|
+
* @param records - The sorted array of records to process
|
|
1013
|
+
* @param include - The array of include specifications with context parameters
|
|
1014
|
+
* @returns The processed array with context messages included
|
|
1015
|
+
*/
|
|
1016
|
+
processMessagesWithContext(records, include) {
|
|
1017
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
1018
|
+
if (messagesWithContext.length === 0) {
|
|
1019
|
+
return records;
|
|
1020
|
+
}
|
|
1021
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
1022
|
+
records.forEach((message, index) => {
|
|
1023
|
+
messageIndexMap.set(message.id, index);
|
|
1024
|
+
});
|
|
1025
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
1026
|
+
for (const item of messagesWithContext) {
|
|
1027
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
1028
|
+
if (messageIndex !== void 0) {
|
|
1029
|
+
if (item.withPreviousMessages) {
|
|
1030
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
1031
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
1032
|
+
additionalIndices.add(i);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
if (item.withNextMessages) {
|
|
1036
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
1037
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
1038
|
+
additionalIndices.add(i);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1243
1041
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1042
|
+
}
|
|
1043
|
+
if (additionalIndices.size === 0) {
|
|
1044
|
+
return records;
|
|
1045
|
+
}
|
|
1046
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
1047
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
1048
|
+
records.forEach((record, index) => {
|
|
1049
|
+
if (originalMatchIds.has(record.id)) {
|
|
1050
|
+
allIndices.add(index);
|
|
1246
1051
|
}
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1052
|
+
});
|
|
1053
|
+
additionalIndices.forEach((index) => {
|
|
1054
|
+
allIndices.add(index);
|
|
1055
|
+
});
|
|
1056
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Parse message data from LanceDB record format to MastraDBMessage format
|
|
1060
|
+
*/
|
|
1061
|
+
parseMessageData(data) {
|
|
1062
|
+
const { thread_id, ...rest } = data;
|
|
1063
|
+
return {
|
|
1064
|
+
...rest,
|
|
1065
|
+
threadId: thread_id,
|
|
1066
|
+
content: typeof data.content === "string" ? (() => {
|
|
1067
|
+
try {
|
|
1068
|
+
return JSON.parse(data.content);
|
|
1069
|
+
} catch {
|
|
1070
|
+
return data.content;
|
|
1071
|
+
}
|
|
1072
|
+
})() : data.content,
|
|
1073
|
+
createdAt: new Date(data.createdAt),
|
|
1074
|
+
updatedAt: new Date(data.updatedAt)
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
async updateMessages(args) {
|
|
1078
|
+
const { messages } = args;
|
|
1079
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
1080
|
+
if (!messages.length) {
|
|
1081
|
+
return [];
|
|
1258
1082
|
}
|
|
1083
|
+
const updatedMessages = [];
|
|
1084
|
+
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
1259
1085
|
try {
|
|
1260
|
-
const
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1086
|
+
for (const updateData of messages) {
|
|
1087
|
+
const { id, ...updates } = updateData;
|
|
1088
|
+
const existingMessage = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
1089
|
+
if (!existingMessage) {
|
|
1090
|
+
this.logger.warn("Message not found for update", { id });
|
|
1091
|
+
continue;
|
|
1092
|
+
}
|
|
1093
|
+
const existingMsg = this.parseMessageData(existingMessage);
|
|
1094
|
+
const originalThreadId = existingMsg.threadId;
|
|
1095
|
+
affectedThreadIds.add(originalThreadId);
|
|
1096
|
+
const updatePayload = {};
|
|
1097
|
+
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
1098
|
+
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
1099
|
+
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
1100
|
+
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
1101
|
+
updatePayload.thread_id = updates.threadId;
|
|
1102
|
+
affectedThreadIds.add(updates.threadId);
|
|
1103
|
+
}
|
|
1104
|
+
if (updates.content) {
|
|
1105
|
+
const existingContent = existingMsg.content;
|
|
1106
|
+
let newContent = { ...existingContent };
|
|
1107
|
+
if (updates.content.metadata !== void 0) {
|
|
1108
|
+
newContent.metadata = {
|
|
1109
|
+
...existingContent.metadata || {},
|
|
1110
|
+
...updates.content.metadata || {}
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
if (updates.content.content !== void 0) {
|
|
1114
|
+
newContent.content = updates.content.content;
|
|
1115
|
+
}
|
|
1116
|
+
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
1117
|
+
newContent.parts = updates.content.parts;
|
|
1118
|
+
}
|
|
1119
|
+
updatePayload.content = JSON.stringify(newContent);
|
|
1120
|
+
}
|
|
1121
|
+
await this.#db.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
1122
|
+
const updatedMessage = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
1123
|
+
if (updatedMessage) {
|
|
1124
|
+
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
1267
1125
|
}
|
|
1268
1126
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1127
|
+
for (const threadId of affectedThreadIds) {
|
|
1128
|
+
await this.#db.insert({
|
|
1129
|
+
tableName: storage.TABLE_THREADS,
|
|
1130
|
+
record: { id: threadId, updatedAt: Date.now() }
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
return updatedMessages;
|
|
1271
1134
|
} catch (error$1) {
|
|
1272
1135
|
throw new error.MastraError(
|
|
1273
1136
|
{
|
|
1274
|
-
id: "
|
|
1137
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_MESSAGES", "FAILED"),
|
|
1275
1138
|
domain: error.ErrorDomain.STORAGE,
|
|
1276
1139
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1277
|
-
details: {
|
|
1140
|
+
details: { count: messages.length }
|
|
1278
1141
|
},
|
|
1279
1142
|
error$1
|
|
1280
1143
|
);
|
|
1281
1144
|
}
|
|
1282
1145
|
}
|
|
1283
|
-
async
|
|
1146
|
+
async getResourceById({ resourceId }) {
|
|
1284
1147
|
try {
|
|
1285
|
-
|
|
1286
|
-
|
|
1148
|
+
const resource = await this.#db.load({ tableName: storage.TABLE_RESOURCES, keys: { id: resourceId } });
|
|
1149
|
+
if (!resource) {
|
|
1150
|
+
return null;
|
|
1287
1151
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1152
|
+
let createdAt;
|
|
1153
|
+
let updatedAt;
|
|
1154
|
+
try {
|
|
1155
|
+
if (resource.createdAt instanceof Date) {
|
|
1156
|
+
createdAt = resource.createdAt;
|
|
1157
|
+
} else if (typeof resource.createdAt === "string") {
|
|
1158
|
+
createdAt = new Date(resource.createdAt);
|
|
1159
|
+
} else if (typeof resource.createdAt === "number") {
|
|
1160
|
+
createdAt = new Date(resource.createdAt);
|
|
1161
|
+
} else {
|
|
1162
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1163
|
+
}
|
|
1164
|
+
if (isNaN(createdAt.getTime())) {
|
|
1165
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1166
|
+
}
|
|
1167
|
+
} catch {
|
|
1168
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1290
1169
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1170
|
+
try {
|
|
1171
|
+
if (resource.updatedAt instanceof Date) {
|
|
1172
|
+
updatedAt = resource.updatedAt;
|
|
1173
|
+
} else if (typeof resource.updatedAt === "string") {
|
|
1174
|
+
updatedAt = new Date(resource.updatedAt);
|
|
1175
|
+
} else if (typeof resource.updatedAt === "number") {
|
|
1176
|
+
updatedAt = new Date(resource.updatedAt);
|
|
1177
|
+
} else {
|
|
1178
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1179
|
+
}
|
|
1180
|
+
if (isNaN(updatedAt.getTime())) {
|
|
1181
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1182
|
+
}
|
|
1183
|
+
} catch {
|
|
1184
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1293
1185
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
const processedRecord = { ...record };
|
|
1311
|
-
for (const key in processedRecord) {
|
|
1312
|
-
if (processedRecord[key] == null) continue;
|
|
1313
|
-
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
1314
|
-
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
1315
|
-
}
|
|
1186
|
+
let workingMemory = resource.workingMemory;
|
|
1187
|
+
if (workingMemory === null || workingMemory === void 0) {
|
|
1188
|
+
workingMemory = void 0;
|
|
1189
|
+
} else if (workingMemory === "") {
|
|
1190
|
+
workingMemory = "";
|
|
1191
|
+
} else if (typeof workingMemory === "object") {
|
|
1192
|
+
workingMemory = JSON.stringify(workingMemory);
|
|
1193
|
+
}
|
|
1194
|
+
let metadata = resource.metadata;
|
|
1195
|
+
if (metadata === "" || metadata === null || metadata === void 0) {
|
|
1196
|
+
metadata = void 0;
|
|
1197
|
+
} else if (typeof metadata === "string") {
|
|
1198
|
+
try {
|
|
1199
|
+
metadata = JSON.parse(metadata);
|
|
1200
|
+
} catch {
|
|
1201
|
+
metadata = metadata;
|
|
1316
1202
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1203
|
+
}
|
|
1204
|
+
return {
|
|
1205
|
+
...resource,
|
|
1206
|
+
createdAt,
|
|
1207
|
+
updatedAt,
|
|
1208
|
+
workingMemory,
|
|
1209
|
+
metadata
|
|
1210
|
+
};
|
|
1321
1211
|
} catch (error$1) {
|
|
1322
1212
|
throw new error.MastraError(
|
|
1323
1213
|
{
|
|
1324
|
-
id: "
|
|
1214
|
+
id: storage.createStorageErrorId("LANCE", "GET_RESOURCE_BY_ID", "FAILED"),
|
|
1325
1215
|
domain: error.ErrorDomain.STORAGE,
|
|
1326
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1327
|
-
details: { tableName }
|
|
1216
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1328
1217
|
},
|
|
1329
1218
|
error$1
|
|
1330
1219
|
);
|
|
1331
1220
|
}
|
|
1332
1221
|
}
|
|
1333
|
-
async
|
|
1222
|
+
async saveResource({ resource }) {
|
|
1334
1223
|
try {
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1224
|
+
const record = {
|
|
1225
|
+
...resource,
|
|
1226
|
+
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
1227
|
+
createdAt: resource.createdAt.getTime(),
|
|
1228
|
+
// Store as timestamp (milliseconds)
|
|
1229
|
+
updatedAt: resource.updatedAt.getTime()
|
|
1230
|
+
// Store as timestamp (milliseconds)
|
|
1231
|
+
};
|
|
1232
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
1233
|
+
await table.add([record], { mode: "append" });
|
|
1234
|
+
return resource;
|
|
1235
|
+
} catch (error$1) {
|
|
1345
1236
|
throw new error.MastraError(
|
|
1346
1237
|
{
|
|
1347
|
-
id: "
|
|
1238
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_RESOURCE", "FAILED"),
|
|
1348
1239
|
domain: error.ErrorDomain.STORAGE,
|
|
1349
|
-
category: error.ErrorCategory.
|
|
1350
|
-
text: validationError.message,
|
|
1351
|
-
details: { tableName }
|
|
1240
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1352
1241
|
},
|
|
1353
|
-
|
|
1242
|
+
error$1
|
|
1354
1243
|
);
|
|
1355
1244
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1245
|
+
}
|
|
1246
|
+
async updateResource({
|
|
1247
|
+
resourceId,
|
|
1248
|
+
workingMemory,
|
|
1249
|
+
metadata
|
|
1250
|
+
}) {
|
|
1251
|
+
const maxRetries = 3;
|
|
1252
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1253
|
+
try {
|
|
1254
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
1255
|
+
if (!existingResource) {
|
|
1256
|
+
const newResource = {
|
|
1257
|
+
id: resourceId,
|
|
1258
|
+
workingMemory,
|
|
1259
|
+
metadata: metadata || {},
|
|
1260
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1261
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1262
|
+
};
|
|
1263
|
+
return this.saveResource({ resource: newResource });
|
|
1264
|
+
}
|
|
1265
|
+
const updatedResource = {
|
|
1266
|
+
...existingResource,
|
|
1267
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
1268
|
+
metadata: {
|
|
1269
|
+
...existingResource.metadata,
|
|
1270
|
+
...metadata
|
|
1271
|
+
},
|
|
1272
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1273
|
+
};
|
|
1274
|
+
const record = {
|
|
1275
|
+
id: resourceId,
|
|
1276
|
+
workingMemory: updatedResource.workingMemory || "",
|
|
1277
|
+
metadata: updatedResource.metadata ? JSON.stringify(updatedResource.metadata) : "",
|
|
1278
|
+
updatedAt: updatedResource.updatedAt.getTime()
|
|
1279
|
+
// Store as timestamp (milliseconds)
|
|
1280
|
+
};
|
|
1281
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
1282
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1283
|
+
return updatedResource;
|
|
1284
|
+
} catch (error$1) {
|
|
1285
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
1286
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
1287
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
throw new error.MastraError(
|
|
1291
|
+
{
|
|
1292
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_RESOURCE", "FAILED"),
|
|
1293
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1294
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1295
|
+
},
|
|
1296
|
+
error$1
|
|
1297
|
+
);
|
|
1380
1298
|
}
|
|
1381
|
-
return processResultWithTypeConversion(result[0], tableSchema);
|
|
1382
|
-
} catch (error$1) {
|
|
1383
|
-
if (error$1 instanceof error.MastraError) throw error$1;
|
|
1384
|
-
throw new error.MastraError(
|
|
1385
|
-
{
|
|
1386
|
-
id: "STORAGE_LANCE_STORAGE_LOAD_FAILED",
|
|
1387
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1388
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1389
|
-
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
1390
|
-
},
|
|
1391
|
-
error$1
|
|
1392
|
-
);
|
|
1393
1299
|
}
|
|
1300
|
+
throw new Error("Unexpected end of retry loop");
|
|
1394
1301
|
}
|
|
1395
1302
|
};
|
|
1396
1303
|
var StoreScoresLance = class extends storage.ScoresStorage {
|
|
1397
1304
|
client;
|
|
1398
|
-
|
|
1305
|
+
#db;
|
|
1306
|
+
constructor(config) {
|
|
1399
1307
|
super();
|
|
1308
|
+
const client = resolveLanceConfig(config);
|
|
1400
1309
|
this.client = client;
|
|
1310
|
+
this.#db = new LanceDB({ client });
|
|
1311
|
+
}
|
|
1312
|
+
async init() {
|
|
1313
|
+
await this.#db.createTable({ tableName: storage.TABLE_SCORERS, schema: storage.SCORERS_SCHEMA });
|
|
1314
|
+
await this.#db.alterTable({
|
|
1315
|
+
tableName: storage.TABLE_SCORERS,
|
|
1316
|
+
schema: storage.SCORERS_SCHEMA,
|
|
1317
|
+
ifNotExists: ["spanId", "requestContext"]
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
async dangerouslyClearAll() {
|
|
1321
|
+
await this.#db.clearTable({ tableName: storage.TABLE_SCORERS });
|
|
1401
1322
|
}
|
|
1402
1323
|
async saveScore(score) {
|
|
1324
|
+
let validatedScore;
|
|
1325
|
+
try {
|
|
1326
|
+
validatedScore = evals.saveScorePayloadSchema.parse(score);
|
|
1327
|
+
} catch (error$1) {
|
|
1328
|
+
throw new error.MastraError(
|
|
1329
|
+
{
|
|
1330
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_SCORE", "VALIDATION_FAILED"),
|
|
1331
|
+
text: "Failed to save score in LanceStorage",
|
|
1332
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1333
|
+
category: error.ErrorCategory.USER,
|
|
1334
|
+
details: {
|
|
1335
|
+
scorer: typeof score.scorer?.id === "string" ? score.scorer.id : String(score.scorer?.id ?? "unknown"),
|
|
1336
|
+
entityId: score.entityId ?? "unknown",
|
|
1337
|
+
entityType: score.entityType ?? "unknown",
|
|
1338
|
+
traceId: score.traceId ?? "",
|
|
1339
|
+
spanId: score.spanId ?? ""
|
|
1340
|
+
}
|
|
1341
|
+
},
|
|
1342
|
+
error$1
|
|
1343
|
+
);
|
|
1344
|
+
}
|
|
1345
|
+
const id = crypto.randomUUID();
|
|
1346
|
+
const now = /* @__PURE__ */ new Date();
|
|
1403
1347
|
try {
|
|
1404
|
-
const id = crypto.randomUUID();
|
|
1405
1348
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1406
1349
|
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1407
1350
|
const allowedFields = new Set(schema.fields.map((f) => f.name));
|
|
1408
1351
|
const filteredScore = {};
|
|
1409
|
-
Object.keys(
|
|
1352
|
+
for (const key of Object.keys(validatedScore)) {
|
|
1410
1353
|
if (allowedFields.has(key)) {
|
|
1411
|
-
filteredScore[key] =
|
|
1354
|
+
filteredScore[key] = validatedScore[key];
|
|
1412
1355
|
}
|
|
1413
|
-
}
|
|
1356
|
+
}
|
|
1414
1357
|
for (const key in filteredScore) {
|
|
1415
1358
|
if (filteredScore[key] !== null && typeof filteredScore[key] === "object" && !(filteredScore[key] instanceof Date)) {
|
|
1416
1359
|
filteredScore[key] = JSON.stringify(filteredScore[key]);
|
|
1417
1360
|
}
|
|
1418
1361
|
}
|
|
1419
1362
|
filteredScore.id = id;
|
|
1363
|
+
filteredScore.createdAt = now;
|
|
1364
|
+
filteredScore.updatedAt = now;
|
|
1420
1365
|
await table.add([filteredScore], { mode: "append" });
|
|
1421
|
-
return { score };
|
|
1366
|
+
return { score: { ...validatedScore, id, createdAt: now, updatedAt: now } };
|
|
1422
1367
|
} catch (error$1) {
|
|
1423
1368
|
throw new error.MastraError(
|
|
1424
1369
|
{
|
|
1425
|
-
id: "
|
|
1370
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_SCORE", "FAILED"),
|
|
1426
1371
|
text: "Failed to save score in LanceStorage",
|
|
1427
1372
|
domain: error.ErrorDomain.STORAGE,
|
|
1428
1373
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1438,12 +1383,11 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1438
1383
|
const query = table.query().where(`id = '${id}'`).limit(1);
|
|
1439
1384
|
const records = await query.toArray();
|
|
1440
1385
|
if (records.length === 0) return null;
|
|
1441
|
-
|
|
1442
|
-
return processResultWithTypeConversion(records[0], schema);
|
|
1386
|
+
return await this.transformScoreRow(records[0]);
|
|
1443
1387
|
} catch (error$1) {
|
|
1444
1388
|
throw new error.MastraError(
|
|
1445
1389
|
{
|
|
1446
|
-
id: "
|
|
1390
|
+
id: storage.createStorageErrorId("LANCE", "GET_SCORE_BY_ID", "FAILED"),
|
|
1447
1391
|
text: "Failed to get score by id in LanceStorage",
|
|
1448
1392
|
domain: error.ErrorDomain.STORAGE,
|
|
1449
1393
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1453,7 +1397,23 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1453
1397
|
);
|
|
1454
1398
|
}
|
|
1455
1399
|
}
|
|
1456
|
-
|
|
1400
|
+
/**
|
|
1401
|
+
* LanceDB-specific score row transformation.
|
|
1402
|
+
*
|
|
1403
|
+
* Note: This implementation does NOT use coreTransformScoreRow because:
|
|
1404
|
+
* 1. LanceDB stores schema information in the table itself (requires async fetch)
|
|
1405
|
+
* 2. Uses processResultWithTypeConversion utility for LanceDB-specific type handling
|
|
1406
|
+
*/
|
|
1407
|
+
async transformScoreRow(row) {
|
|
1408
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1409
|
+
const transformed = processResultWithTypeConversion(row, schema);
|
|
1410
|
+
return {
|
|
1411
|
+
...transformed,
|
|
1412
|
+
createdAt: row.createdAt,
|
|
1413
|
+
updatedAt: row.updatedAt
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
async listScoresByScorerId({
|
|
1457
1417
|
scorerId,
|
|
1458
1418
|
pagination,
|
|
1459
1419
|
entityId,
|
|
@@ -1461,9 +1421,10 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1461
1421
|
source
|
|
1462
1422
|
}) {
|
|
1463
1423
|
try {
|
|
1424
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1425
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1426
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1464
1427
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1465
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1466
|
-
const offset = page * perPage;
|
|
1467
1428
|
let query = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1468
1429
|
if (source) {
|
|
1469
1430
|
query = query.where(`\`source\` = '${source}'`);
|
|
@@ -1474,30 +1435,38 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1474
1435
|
if (entityType) {
|
|
1475
1436
|
query = query.where(`\`entityType\` = '${entityType}'`);
|
|
1476
1437
|
}
|
|
1477
|
-
query = query.limit(perPage);
|
|
1478
|
-
if (offset > 0) query.offset(offset);
|
|
1479
|
-
const records = await query.toArray();
|
|
1480
|
-
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1481
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1482
1438
|
let totalQuery = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1483
1439
|
if (source) {
|
|
1484
1440
|
totalQuery = totalQuery.where(`\`source\` = '${source}'`);
|
|
1485
1441
|
}
|
|
1442
|
+
if (entityId) {
|
|
1443
|
+
totalQuery = totalQuery.where(`\`entityId\` = '${entityId}'`);
|
|
1444
|
+
}
|
|
1445
|
+
if (entityType) {
|
|
1446
|
+
totalQuery = totalQuery.where(`\`entityType\` = '${entityType}'`);
|
|
1447
|
+
}
|
|
1486
1448
|
const allRecords = await totalQuery.toArray();
|
|
1487
1449
|
const total = allRecords.length;
|
|
1450
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1451
|
+
if (perPageInput !== false) {
|
|
1452
|
+
query = query.limit(perPage);
|
|
1453
|
+
if (start > 0) query = query.offset(start);
|
|
1454
|
+
}
|
|
1455
|
+
const records = await query.toArray();
|
|
1456
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1488
1457
|
return {
|
|
1489
1458
|
pagination: {
|
|
1490
1459
|
page,
|
|
1491
|
-
perPage,
|
|
1460
|
+
perPage: perPageForResponse,
|
|
1492
1461
|
total,
|
|
1493
|
-
hasMore:
|
|
1462
|
+
hasMore: end < total
|
|
1494
1463
|
},
|
|
1495
1464
|
scores
|
|
1496
1465
|
};
|
|
1497
1466
|
} catch (error$1) {
|
|
1498
1467
|
throw new error.MastraError(
|
|
1499
1468
|
{
|
|
1500
|
-
id: "
|
|
1469
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
|
|
1501
1470
|
text: "Failed to get scores by scorerId in LanceStorage",
|
|
1502
1471
|
domain: error.ErrorDomain.STORAGE,
|
|
1503
1472
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1507,34 +1476,38 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1507
1476
|
);
|
|
1508
1477
|
}
|
|
1509
1478
|
}
|
|
1510
|
-
async
|
|
1479
|
+
async listScoresByRunId({
|
|
1511
1480
|
runId,
|
|
1512
1481
|
pagination
|
|
1513
1482
|
}) {
|
|
1514
1483
|
try {
|
|
1484
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1485
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1486
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1515
1487
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1516
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1517
|
-
const offset = page * perPage;
|
|
1518
|
-
const query = table.query().where(`\`runId\` = '${runId}'`).limit(perPage);
|
|
1519
|
-
if (offset > 0) query.offset(offset);
|
|
1520
|
-
const records = await query.toArray();
|
|
1521
|
-
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1522
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1523
1488
|
const allRecords = await table.query().where(`\`runId\` = '${runId}'`).toArray();
|
|
1524
1489
|
const total = allRecords.length;
|
|
1490
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1491
|
+
let query = table.query().where(`\`runId\` = '${runId}'`);
|
|
1492
|
+
if (perPageInput !== false) {
|
|
1493
|
+
query = query.limit(perPage);
|
|
1494
|
+
if (start > 0) query = query.offset(start);
|
|
1495
|
+
}
|
|
1496
|
+
const records = await query.toArray();
|
|
1497
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1525
1498
|
return {
|
|
1526
1499
|
pagination: {
|
|
1527
1500
|
page,
|
|
1528
|
-
perPage,
|
|
1501
|
+
perPage: perPageForResponse,
|
|
1529
1502
|
total,
|
|
1530
|
-
hasMore:
|
|
1503
|
+
hasMore: end < total
|
|
1531
1504
|
},
|
|
1532
1505
|
scores
|
|
1533
1506
|
};
|
|
1534
1507
|
} catch (error$1) {
|
|
1535
1508
|
throw new error.MastraError(
|
|
1536
1509
|
{
|
|
1537
|
-
id: "
|
|
1510
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_RUN_ID", "FAILED"),
|
|
1538
1511
|
text: "Failed to get scores by runId in LanceStorage",
|
|
1539
1512
|
domain: error.ErrorDomain.STORAGE,
|
|
1540
1513
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1544,35 +1517,39 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1544
1517
|
);
|
|
1545
1518
|
}
|
|
1546
1519
|
}
|
|
1547
|
-
async
|
|
1520
|
+
async listScoresByEntityId({
|
|
1548
1521
|
entityId,
|
|
1549
1522
|
entityType,
|
|
1550
1523
|
pagination
|
|
1551
1524
|
}) {
|
|
1552
1525
|
try {
|
|
1526
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1527
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1528
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1553
1529
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1554
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1555
|
-
const offset = page * perPage;
|
|
1556
|
-
const query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).limit(perPage);
|
|
1557
|
-
if (offset > 0) query.offset(offset);
|
|
1558
|
-
const records = await query.toArray();
|
|
1559
|
-
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1560
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1561
1530
|
const allRecords = await table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).toArray();
|
|
1562
1531
|
const total = allRecords.length;
|
|
1532
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1533
|
+
let query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`);
|
|
1534
|
+
if (perPageInput !== false) {
|
|
1535
|
+
query = query.limit(perPage);
|
|
1536
|
+
if (start > 0) query = query.offset(start);
|
|
1537
|
+
}
|
|
1538
|
+
const records = await query.toArray();
|
|
1539
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1563
1540
|
return {
|
|
1564
1541
|
pagination: {
|
|
1565
1542
|
page,
|
|
1566
|
-
perPage,
|
|
1543
|
+
perPage: perPageForResponse,
|
|
1567
1544
|
total,
|
|
1568
|
-
hasMore:
|
|
1545
|
+
hasMore: end < total
|
|
1569
1546
|
},
|
|
1570
1547
|
scores
|
|
1571
1548
|
};
|
|
1572
1549
|
} catch (error$1) {
|
|
1573
1550
|
throw new error.MastraError(
|
|
1574
1551
|
{
|
|
1575
|
-
id: "
|
|
1552
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
|
|
1576
1553
|
text: "Failed to get scores by entityId and entityType in LanceStorage",
|
|
1577
1554
|
domain: error.ErrorDomain.STORAGE,
|
|
1578
1555
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1582,199 +1559,52 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1582
1559
|
);
|
|
1583
1560
|
}
|
|
1584
1561
|
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
constructor({ client, operations }) {
|
|
1590
|
-
super();
|
|
1591
|
-
this.client = client;
|
|
1592
|
-
this.operations = operations;
|
|
1593
|
-
}
|
|
1594
|
-
async saveTrace({ trace }) {
|
|
1595
|
-
try {
|
|
1596
|
-
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
1597
|
-
const record = {
|
|
1598
|
-
...trace,
|
|
1599
|
-
attributes: JSON.stringify(trace.attributes),
|
|
1600
|
-
status: JSON.stringify(trace.status),
|
|
1601
|
-
events: JSON.stringify(trace.events),
|
|
1602
|
-
links: JSON.stringify(trace.links),
|
|
1603
|
-
other: JSON.stringify(trace.other)
|
|
1604
|
-
};
|
|
1605
|
-
await table.add([record], { mode: "append" });
|
|
1606
|
-
return trace;
|
|
1607
|
-
} catch (error$1) {
|
|
1608
|
-
throw new error.MastraError(
|
|
1609
|
-
{
|
|
1610
|
-
id: "LANCE_STORE_SAVE_TRACE_FAILED",
|
|
1611
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1612
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1613
|
-
},
|
|
1614
|
-
error$1
|
|
1615
|
-
);
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
async getTraceById({ traceId }) {
|
|
1619
|
-
try {
|
|
1620
|
-
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
1621
|
-
const query = table.query().where(`id = '${traceId}'`);
|
|
1622
|
-
const records = await query.toArray();
|
|
1623
|
-
return records[0];
|
|
1624
|
-
} catch (error$1) {
|
|
1625
|
-
throw new error.MastraError(
|
|
1626
|
-
{
|
|
1627
|
-
id: "LANCE_STORE_GET_TRACE_BY_ID_FAILED",
|
|
1628
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1629
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1630
|
-
},
|
|
1631
|
-
error$1
|
|
1632
|
-
);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
async getTraces({
|
|
1636
|
-
name,
|
|
1637
|
-
scope,
|
|
1638
|
-
page = 1,
|
|
1639
|
-
perPage = 10,
|
|
1640
|
-
attributes
|
|
1562
|
+
async listScoresBySpan({
|
|
1563
|
+
traceId,
|
|
1564
|
+
spanId,
|
|
1565
|
+
pagination
|
|
1641
1566
|
}) {
|
|
1642
1567
|
try {
|
|
1643
|
-
const
|
|
1644
|
-
const
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
}
|
|
1651
|
-
if (
|
|
1652
|
-
query
|
|
1653
|
-
|
|
1654
|
-
const offset = (page - 1) * perPage;
|
|
1655
|
-
query.limit(perPage);
|
|
1656
|
-
if (offset > 0) {
|
|
1657
|
-
query.offset(offset);
|
|
1658
|
-
}
|
|
1659
|
-
const records = await query.toArray();
|
|
1660
|
-
return records.map((record) => {
|
|
1661
|
-
const processed = {
|
|
1662
|
-
...record,
|
|
1663
|
-
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1664
|
-
status: record.status ? JSON.parse(record.status) : {},
|
|
1665
|
-
events: record.events ? JSON.parse(record.events) : [],
|
|
1666
|
-
links: record.links ? JSON.parse(record.links) : [],
|
|
1667
|
-
other: record.other ? JSON.parse(record.other) : {},
|
|
1668
|
-
startTime: new Date(record.startTime),
|
|
1669
|
-
endTime: new Date(record.endTime),
|
|
1670
|
-
createdAt: new Date(record.createdAt)
|
|
1671
|
-
};
|
|
1672
|
-
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1673
|
-
processed.parentSpanId = "";
|
|
1674
|
-
} else {
|
|
1675
|
-
processed.parentSpanId = String(processed.parentSpanId);
|
|
1676
|
-
}
|
|
1677
|
-
return processed;
|
|
1678
|
-
});
|
|
1679
|
-
} catch (error$1) {
|
|
1680
|
-
throw new error.MastraError(
|
|
1681
|
-
{
|
|
1682
|
-
id: "LANCE_STORE_GET_TRACES_FAILED",
|
|
1683
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1684
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1685
|
-
details: { name: name ?? "", scope: scope ?? "" }
|
|
1686
|
-
},
|
|
1687
|
-
error$1
|
|
1688
|
-
);
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
async getTracesPaginated(args) {
|
|
1692
|
-
try {
|
|
1693
|
-
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
1694
|
-
const query = table.query();
|
|
1695
|
-
const conditions = [];
|
|
1696
|
-
if (args.name) {
|
|
1697
|
-
conditions.push(`name = '${args.name}'`);
|
|
1698
|
-
}
|
|
1699
|
-
if (args.scope) {
|
|
1700
|
-
conditions.push(`scope = '${args.scope}'`);
|
|
1701
|
-
}
|
|
1702
|
-
if (args.attributes) {
|
|
1703
|
-
const attributesStr = JSON.stringify(args.attributes);
|
|
1704
|
-
conditions.push(`attributes LIKE '%${attributesStr.replace(/"/g, '\\"')}%'`);
|
|
1705
|
-
}
|
|
1706
|
-
if (args.dateRange?.start) {
|
|
1707
|
-
conditions.push(`\`createdAt\` >= ${args.dateRange.start.getTime()}`);
|
|
1708
|
-
}
|
|
1709
|
-
if (args.dateRange?.end) {
|
|
1710
|
-
conditions.push(`\`createdAt\` <= ${args.dateRange.end.getTime()}`);
|
|
1711
|
-
}
|
|
1712
|
-
if (conditions.length > 0) {
|
|
1713
|
-
const whereClause = conditions.join(" AND ");
|
|
1714
|
-
query.where(whereClause);
|
|
1715
|
-
}
|
|
1716
|
-
let total = 0;
|
|
1717
|
-
if (conditions.length > 0) {
|
|
1718
|
-
const countQuery = table.query().where(conditions.join(" AND "));
|
|
1719
|
-
const allRecords = await countQuery.toArray();
|
|
1720
|
-
total = allRecords.length;
|
|
1721
|
-
} else {
|
|
1722
|
-
total = await table.countRows();
|
|
1723
|
-
}
|
|
1724
|
-
const page = args.page || 0;
|
|
1725
|
-
const perPage = args.perPage || 10;
|
|
1726
|
-
const offset = page * perPage;
|
|
1727
|
-
query.limit(perPage);
|
|
1728
|
-
if (offset > 0) {
|
|
1729
|
-
query.offset(offset);
|
|
1568
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1569
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1570
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1571
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1572
|
+
const allRecords = await table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`).toArray();
|
|
1573
|
+
const total = allRecords.length;
|
|
1574
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1575
|
+
let query = table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`);
|
|
1576
|
+
if (perPageInput !== false) {
|
|
1577
|
+
query = query.limit(perPage);
|
|
1578
|
+
if (start > 0) query = query.offset(start);
|
|
1730
1579
|
}
|
|
1731
1580
|
const records = await query.toArray();
|
|
1732
|
-
const
|
|
1733
|
-
const processed = {
|
|
1734
|
-
...record,
|
|
1735
|
-
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1736
|
-
status: record.status ? JSON.parse(record.status) : {},
|
|
1737
|
-
events: record.events ? JSON.parse(record.events) : [],
|
|
1738
|
-
links: record.links ? JSON.parse(record.links) : [],
|
|
1739
|
-
other: record.other ? JSON.parse(record.other) : {},
|
|
1740
|
-
startTime: new Date(record.startTime),
|
|
1741
|
-
endTime: new Date(record.endTime),
|
|
1742
|
-
createdAt: new Date(record.createdAt)
|
|
1743
|
-
};
|
|
1744
|
-
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1745
|
-
processed.parentSpanId = "";
|
|
1746
|
-
} else {
|
|
1747
|
-
processed.parentSpanId = String(processed.parentSpanId);
|
|
1748
|
-
}
|
|
1749
|
-
return processed;
|
|
1750
|
-
});
|
|
1581
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1751
1582
|
return {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1583
|
+
pagination: {
|
|
1584
|
+
page,
|
|
1585
|
+
perPage: perPageForResponse,
|
|
1586
|
+
total,
|
|
1587
|
+
hasMore: end < total
|
|
1588
|
+
},
|
|
1589
|
+
scores
|
|
1757
1590
|
};
|
|
1758
1591
|
} catch (error$1) {
|
|
1759
1592
|
throw new error.MastraError(
|
|
1760
1593
|
{
|
|
1761
|
-
id: "
|
|
1594
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_SPAN", "FAILED"),
|
|
1595
|
+
text: "Failed to get scores by traceId and spanId in LanceStorage",
|
|
1762
1596
|
domain: error.ErrorDomain.STORAGE,
|
|
1763
1597
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1764
|
-
details: {
|
|
1598
|
+
details: { error: error$1?.message }
|
|
1765
1599
|
},
|
|
1766
1600
|
error$1
|
|
1767
1601
|
);
|
|
1768
1602
|
}
|
|
1769
1603
|
}
|
|
1770
|
-
async batchTraceInsert({ records }) {
|
|
1771
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1772
|
-
await this.operations.batchInsert({
|
|
1773
|
-
tableName: storage.TABLE_TRACES,
|
|
1774
|
-
records
|
|
1775
|
-
});
|
|
1776
|
-
}
|
|
1777
1604
|
};
|
|
1605
|
+
function escapeSql(str) {
|
|
1606
|
+
return str.replace(/'/g, "''");
|
|
1607
|
+
}
|
|
1778
1608
|
function parseWorkflowRun(row) {
|
|
1779
1609
|
let parsedSnapshot = row.snapshot;
|
|
1780
1610
|
if (typeof parsedSnapshot === "string") {
|
|
@@ -1795,54 +1625,104 @@ function parseWorkflowRun(row) {
|
|
|
1795
1625
|
}
|
|
1796
1626
|
var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
1797
1627
|
client;
|
|
1798
|
-
|
|
1628
|
+
#db;
|
|
1629
|
+
constructor(config) {
|
|
1799
1630
|
super();
|
|
1631
|
+
const client = resolveLanceConfig(config);
|
|
1800
1632
|
this.client = client;
|
|
1633
|
+
this.#db = new LanceDB({ client });
|
|
1634
|
+
}
|
|
1635
|
+
async init() {
|
|
1636
|
+
const schema = storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT];
|
|
1637
|
+
await this.#db.createTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT, schema });
|
|
1638
|
+
await this.#db.alterTable({
|
|
1639
|
+
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
1640
|
+
schema,
|
|
1641
|
+
ifNotExists: ["resourceId"]
|
|
1642
|
+
});
|
|
1801
1643
|
}
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1644
|
+
async dangerouslyClearAll() {
|
|
1645
|
+
await this.#db.clearTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT });
|
|
1646
|
+
}
|
|
1647
|
+
async updateWorkflowResults({
|
|
1648
|
+
workflowName,
|
|
1649
|
+
runId,
|
|
1650
|
+
stepId,
|
|
1651
|
+
result,
|
|
1652
|
+
requestContext
|
|
1808
1653
|
}) {
|
|
1809
|
-
|
|
1654
|
+
let snapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
|
|
1655
|
+
if (!snapshot) {
|
|
1656
|
+
snapshot = {
|
|
1657
|
+
context: {},
|
|
1658
|
+
activePaths: [],
|
|
1659
|
+
timestamp: Date.now(),
|
|
1660
|
+
suspendedPaths: {},
|
|
1661
|
+
activeStepsPath: {},
|
|
1662
|
+
resumeLabels: {},
|
|
1663
|
+
serializedStepGraph: [],
|
|
1664
|
+
status: "pending",
|
|
1665
|
+
value: {},
|
|
1666
|
+
waitingPaths: {},
|
|
1667
|
+
runId,
|
|
1668
|
+
requestContext: {}
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
snapshot.context[stepId] = result;
|
|
1672
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
1673
|
+
await this.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
1674
|
+
return snapshot.context;
|
|
1810
1675
|
}
|
|
1811
|
-
updateWorkflowState({
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1676
|
+
async updateWorkflowState({
|
|
1677
|
+
workflowName,
|
|
1678
|
+
runId,
|
|
1679
|
+
opts
|
|
1815
1680
|
}) {
|
|
1816
|
-
|
|
1681
|
+
const snapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
|
|
1682
|
+
if (!snapshot) {
|
|
1683
|
+
return void 0;
|
|
1684
|
+
}
|
|
1685
|
+
if (!snapshot.context) {
|
|
1686
|
+
throw new Error(`Snapshot not found for runId ${runId}`);
|
|
1687
|
+
}
|
|
1688
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
1689
|
+
await this.persistWorkflowSnapshot({ workflowName, runId, snapshot: updatedSnapshot });
|
|
1690
|
+
return updatedSnapshot;
|
|
1817
1691
|
}
|
|
1818
1692
|
async persistWorkflowSnapshot({
|
|
1819
1693
|
workflowName,
|
|
1820
1694
|
runId,
|
|
1821
|
-
|
|
1695
|
+
resourceId,
|
|
1696
|
+
snapshot,
|
|
1697
|
+
createdAt,
|
|
1698
|
+
updatedAt
|
|
1822
1699
|
}) {
|
|
1823
1700
|
try {
|
|
1824
1701
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1825
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1702
|
+
const query = table.query().where(`workflow_name = '${escapeSql(workflowName)}' AND run_id = '${escapeSql(runId)}'`);
|
|
1826
1703
|
const records = await query.toArray();
|
|
1827
|
-
let
|
|
1828
|
-
const now = Date.now();
|
|
1704
|
+
let createdAtValue;
|
|
1705
|
+
const now = createdAt?.getTime() ?? Date.now();
|
|
1829
1706
|
if (records.length > 0) {
|
|
1830
|
-
|
|
1707
|
+
createdAtValue = records[0].createdAt ?? now;
|
|
1831
1708
|
} else {
|
|
1832
|
-
|
|
1709
|
+
createdAtValue = now;
|
|
1833
1710
|
}
|
|
1711
|
+
const { status, value, ...rest } = snapshot;
|
|
1834
1712
|
const record = {
|
|
1835
1713
|
workflow_name: workflowName,
|
|
1836
1714
|
run_id: runId,
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1715
|
+
resourceId,
|
|
1716
|
+
snapshot: JSON.stringify({ status, value, ...rest }),
|
|
1717
|
+
// this is to ensure status is always just before value, for when querying the db by status
|
|
1718
|
+
createdAt: createdAtValue,
|
|
1719
|
+
updatedAt: updatedAt ?? now
|
|
1840
1720
|
};
|
|
1841
1721
|
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1842
1722
|
} catch (error$1) {
|
|
1843
1723
|
throw new error.MastraError(
|
|
1844
1724
|
{
|
|
1845
|
-
id: "
|
|
1725
|
+
id: storage.createStorageErrorId("LANCE", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1846
1726
|
domain: error.ErrorDomain.STORAGE,
|
|
1847
1727
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1848
1728
|
details: { workflowName, runId }
|
|
@@ -1857,13 +1737,13 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1857
1737
|
}) {
|
|
1858
1738
|
try {
|
|
1859
1739
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1860
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1740
|
+
const query = table.query().where(`workflow_name = '${escapeSql(workflowName)}' AND run_id = '${escapeSql(runId)}'`);
|
|
1861
1741
|
const records = await query.toArray();
|
|
1862
1742
|
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
1863
1743
|
} catch (error$1) {
|
|
1864
1744
|
throw new error.MastraError(
|
|
1865
1745
|
{
|
|
1866
|
-
id: "
|
|
1746
|
+
id: storage.createStorageErrorId("LANCE", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1867
1747
|
domain: error.ErrorDomain.STORAGE,
|
|
1868
1748
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1869
1749
|
details: { workflowName, runId }
|
|
@@ -1875,9 +1755,9 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1875
1755
|
async getWorkflowRunById(args) {
|
|
1876
1756
|
try {
|
|
1877
1757
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1878
|
-
let whereClause = `run_id = '${args.runId}'`;
|
|
1758
|
+
let whereClause = `run_id = '${escapeSql(args.runId)}'`;
|
|
1879
1759
|
if (args.workflowName) {
|
|
1880
|
-
whereClause += ` AND workflow_name = '${args.workflowName}'`;
|
|
1760
|
+
whereClause += ` AND workflow_name = '${escapeSql(args.workflowName)}'`;
|
|
1881
1761
|
}
|
|
1882
1762
|
const query = table.query().where(whereClause);
|
|
1883
1763
|
const records = await query.toArray();
|
|
@@ -1887,7 +1767,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1887
1767
|
} catch (error$1) {
|
|
1888
1768
|
throw new error.MastraError(
|
|
1889
1769
|
{
|
|
1890
|
-
id: "
|
|
1770
|
+
id: storage.createStorageErrorId("LANCE", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1891
1771
|
domain: error.ErrorDomain.STORAGE,
|
|
1892
1772
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1893
1773
|
details: { runId: args.runId, workflowName: args.workflowName ?? "" }
|
|
@@ -1896,16 +1776,37 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1896
1776
|
);
|
|
1897
1777
|
}
|
|
1898
1778
|
}
|
|
1899
|
-
async
|
|
1779
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
1780
|
+
try {
|
|
1781
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1782
|
+
const whereClause = `run_id = '${escapeSql(runId)}' AND workflow_name = '${escapeSql(workflowName)}'`;
|
|
1783
|
+
await table.delete(whereClause);
|
|
1784
|
+
} catch (error$1) {
|
|
1785
|
+
throw new error.MastraError(
|
|
1786
|
+
{
|
|
1787
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1788
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1789
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1790
|
+
details: { runId, workflowName }
|
|
1791
|
+
},
|
|
1792
|
+
error$1
|
|
1793
|
+
);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
async listWorkflowRuns(args) {
|
|
1900
1797
|
try {
|
|
1901
1798
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1902
1799
|
let query = table.query();
|
|
1903
1800
|
const conditions = [];
|
|
1904
1801
|
if (args?.workflowName) {
|
|
1905
|
-
conditions.push(`workflow_name = '${args.workflowName
|
|
1802
|
+
conditions.push(`workflow_name = '${escapeSql(args.workflowName)}'`);
|
|
1803
|
+
}
|
|
1804
|
+
if (args?.status) {
|
|
1805
|
+
const escapedStatus = args.status.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
1806
|
+
conditions.push(`\`snapshot\` LIKE '%"status":"${escapedStatus}","value"%'`);
|
|
1906
1807
|
}
|
|
1907
1808
|
if (args?.resourceId) {
|
|
1908
|
-
conditions.push(`\`resourceId\` = '${args.resourceId}'`);
|
|
1809
|
+
conditions.push(`\`resourceId\` = '${escapeSql(args.resourceId)}'`);
|
|
1909
1810
|
}
|
|
1910
1811
|
if (args?.fromDate instanceof Date) {
|
|
1911
1812
|
conditions.push(`\`createdAt\` >= ${args.fromDate.getTime()}`);
|
|
@@ -1920,11 +1821,22 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1920
1821
|
} else {
|
|
1921
1822
|
total = await table.countRows();
|
|
1922
1823
|
}
|
|
1923
|
-
if (args?.
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1824
|
+
if (args?.perPage !== void 0 && args?.page !== void 0) {
|
|
1825
|
+
const normalizedPerPage = storage.normalizePerPage(args.perPage, Number.MAX_SAFE_INTEGER);
|
|
1826
|
+
if (args.page < 0 || !Number.isInteger(args.page)) {
|
|
1827
|
+
throw new error.MastraError(
|
|
1828
|
+
{
|
|
1829
|
+
id: storage.createStorageErrorId("LANCE", "LIST_WORKFLOW_RUNS", "INVALID_PAGINATION"),
|
|
1830
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1831
|
+
category: error.ErrorCategory.USER,
|
|
1832
|
+
details: { page: args.page, perPage: args.perPage }
|
|
1833
|
+
},
|
|
1834
|
+
new Error(`Invalid pagination parameters: page=${args.page}, perPage=${args.perPage}`)
|
|
1835
|
+
);
|
|
1836
|
+
}
|
|
1837
|
+
const offset = args.page * normalizedPerPage;
|
|
1838
|
+
query.limit(normalizedPerPage);
|
|
1839
|
+
query.offset(offset);
|
|
1928
1840
|
}
|
|
1929
1841
|
const records = await query.toArray();
|
|
1930
1842
|
return {
|
|
@@ -1934,10 +1846,10 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1934
1846
|
} catch (error$1) {
|
|
1935
1847
|
throw new error.MastraError(
|
|
1936
1848
|
{
|
|
1937
|
-
id: "
|
|
1849
|
+
id: storage.createStorageErrorId("LANCE", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
1938
1850
|
domain: error.ErrorDomain.STORAGE,
|
|
1939
1851
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1940
|
-
details: {
|
|
1852
|
+
details: { resourceId: args?.resourceId ?? "", workflowName: args?.workflowName ?? "" }
|
|
1941
1853
|
},
|
|
1942
1854
|
error$1
|
|
1943
1855
|
);
|
|
@@ -1951,295 +1863,95 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1951
1863
|
lanceClient;
|
|
1952
1864
|
/**
|
|
1953
1865
|
* Creates a new instance of LanceStorage
|
|
1866
|
+
* @param id The unique identifier for this storage instance
|
|
1867
|
+
* @param name The name for this storage instance
|
|
1954
1868
|
* @param uri The URI to connect to LanceDB
|
|
1955
|
-
* @param
|
|
1869
|
+
* @param connectionOptions connection options for LanceDB
|
|
1870
|
+
* @param storageOptions storage options including disableInit
|
|
1956
1871
|
*
|
|
1957
1872
|
* Usage:
|
|
1958
1873
|
*
|
|
1959
1874
|
* Connect to a local database
|
|
1960
1875
|
* ```ts
|
|
1961
|
-
* const store = await LanceStorage.create('/path/to/db');
|
|
1876
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db');
|
|
1962
1877
|
* ```
|
|
1963
1878
|
*
|
|
1964
1879
|
* Connect to a LanceDB cloud database
|
|
1965
1880
|
* ```ts
|
|
1966
|
-
* const store = await LanceStorage.create('db://host:port');
|
|
1881
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 'db://host:port');
|
|
1967
1882
|
* ```
|
|
1968
1883
|
*
|
|
1969
1884
|
* Connect to a cloud database
|
|
1970
1885
|
* ```ts
|
|
1971
|
-
* const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1886
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 's3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1887
|
+
* ```
|
|
1888
|
+
*
|
|
1889
|
+
* Disable auto-init for runtime (after CI/CD has run migrations)
|
|
1890
|
+
* ```ts
|
|
1891
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db', undefined, { disableInit: true });
|
|
1972
1892
|
* ```
|
|
1973
1893
|
*/
|
|
1974
|
-
static async create(name, uri,
|
|
1975
|
-
const instance = new _LanceStorage(name);
|
|
1894
|
+
static async create(id, name, uri, connectionOptions, storageOptions) {
|
|
1895
|
+
const instance = new _LanceStorage(id, name, storageOptions?.disableInit);
|
|
1976
1896
|
try {
|
|
1977
|
-
instance.lanceClient = await lancedb.connect(uri,
|
|
1978
|
-
const operations = new StoreOperationsLance({ client: instance.lanceClient });
|
|
1897
|
+
instance.lanceClient = await lancedb.connect(uri, connectionOptions);
|
|
1979
1898
|
instance.stores = {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
e
|
|
1998
|
-
);
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
/**
|
|
2002
|
-
* @internal
|
|
2003
|
-
* Private constructor to enforce using the create factory method
|
|
2004
|
-
*/
|
|
2005
|
-
constructor(name) {
|
|
2006
|
-
super({ name });
|
|
2007
|
-
const operations = new StoreOperationsLance({ client: this.lanceClient });
|
|
2008
|
-
this.stores = {
|
|
2009
|
-
operations: new StoreOperationsLance({ client: this.lanceClient }),
|
|
2010
|
-
workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
|
|
2011
|
-
traces: new StoreTracesLance({ client: this.lanceClient, operations }),
|
|
2012
|
-
scores: new StoreScoresLance({ client: this.lanceClient }),
|
|
2013
|
-
legacyEvals: new StoreLegacyEvalsLance({ client: this.lanceClient }),
|
|
2014
|
-
memory: new StoreMemoryLance({ client: this.lanceClient, operations })
|
|
2015
|
-
};
|
|
2016
|
-
}
|
|
2017
|
-
async createTable({
|
|
2018
|
-
tableName,
|
|
2019
|
-
schema
|
|
2020
|
-
}) {
|
|
2021
|
-
return this.stores.operations.createTable({ tableName, schema });
|
|
2022
|
-
}
|
|
2023
|
-
async dropTable({ tableName }) {
|
|
2024
|
-
return this.stores.operations.dropTable({ tableName });
|
|
2025
|
-
}
|
|
2026
|
-
async alterTable({
|
|
2027
|
-
tableName,
|
|
2028
|
-
schema,
|
|
2029
|
-
ifNotExists
|
|
2030
|
-
}) {
|
|
2031
|
-
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
2032
|
-
}
|
|
2033
|
-
async clearTable({ tableName }) {
|
|
2034
|
-
return this.stores.operations.clearTable({ tableName });
|
|
2035
|
-
}
|
|
2036
|
-
async insert({ tableName, record }) {
|
|
2037
|
-
return this.stores.operations.insert({ tableName, record });
|
|
2038
|
-
}
|
|
2039
|
-
async batchInsert({ tableName, records }) {
|
|
2040
|
-
return this.stores.operations.batchInsert({ tableName, records });
|
|
2041
|
-
}
|
|
2042
|
-
async load({ tableName, keys }) {
|
|
2043
|
-
return this.stores.operations.load({ tableName, keys });
|
|
2044
|
-
}
|
|
2045
|
-
async getThreadById({ threadId }) {
|
|
2046
|
-
return this.stores.memory.getThreadById({ threadId });
|
|
2047
|
-
}
|
|
2048
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
2049
|
-
return this.stores.memory.getThreadsByResourceId({ resourceId });
|
|
1899
|
+
workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
|
|
1900
|
+
scores: new StoreScoresLance({ client: instance.lanceClient }),
|
|
1901
|
+
memory: new StoreMemoryLance({ client: instance.lanceClient })
|
|
1902
|
+
};
|
|
1903
|
+
return instance;
|
|
1904
|
+
} catch (e) {
|
|
1905
|
+
throw new error.MastraError(
|
|
1906
|
+
{
|
|
1907
|
+
id: storage.createStorageErrorId("LANCE", "CONNECT", "FAILED"),
|
|
1908
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1909
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1910
|
+
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
1911
|
+
details: { uri, optionsProvided: !!connectionOptions }
|
|
1912
|
+
},
|
|
1913
|
+
e
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
2050
1916
|
}
|
|
2051
1917
|
/**
|
|
2052
|
-
*
|
|
2053
|
-
*
|
|
2054
|
-
*
|
|
1918
|
+
* Creates a new instance of LanceStorage from a pre-configured LanceDB connection.
|
|
1919
|
+
* Use this when you need to configure the connection before initialization.
|
|
1920
|
+
*
|
|
1921
|
+
* @param id The unique identifier for this storage instance
|
|
1922
|
+
* @param name The name for this storage instance
|
|
1923
|
+
* @param client Pre-configured LanceDB connection
|
|
1924
|
+
* @param options Storage options including disableInit
|
|
1925
|
+
*
|
|
1926
|
+
* @example
|
|
1927
|
+
* ```typescript
|
|
1928
|
+
* import { connect } from '@lancedb/lancedb';
|
|
1929
|
+
*
|
|
1930
|
+
* const client = await connect('/path/to/db', {
|
|
1931
|
+
* // Custom connection options
|
|
1932
|
+
* });
|
|
1933
|
+
*
|
|
1934
|
+
* const store = LanceStorage.fromClient('my-id', 'MyStorage', client);
|
|
1935
|
+
* ```
|
|
2055
1936
|
*/
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
}) {
|
|
2064
|
-
return this.stores.memory.updateThread({ id, title, metadata });
|
|
2065
|
-
}
|
|
2066
|
-
async deleteThread({ threadId }) {
|
|
2067
|
-
return this.stores.memory.deleteThread({ threadId });
|
|
2068
|
-
}
|
|
2069
|
-
get supports() {
|
|
2070
|
-
return {
|
|
2071
|
-
selectByIncludeResourceScope: true,
|
|
2072
|
-
resourceWorkingMemory: true,
|
|
2073
|
-
hasColumn: true,
|
|
2074
|
-
createTable: true,
|
|
2075
|
-
deleteMessages: false
|
|
1937
|
+
static fromClient(id, name, client, options) {
|
|
1938
|
+
const instance = new _LanceStorage(id, name, options?.disableInit);
|
|
1939
|
+
instance.lanceClient = client;
|
|
1940
|
+
instance.stores = {
|
|
1941
|
+
workflows: new StoreWorkflowsLance({ client }),
|
|
1942
|
+
scores: new StoreScoresLance({ client }),
|
|
1943
|
+
memory: new StoreMemoryLance({ client })
|
|
2076
1944
|
};
|
|
2077
|
-
|
|
2078
|
-
async getResourceById({ resourceId }) {
|
|
2079
|
-
return this.stores.memory.getResourceById({ resourceId });
|
|
2080
|
-
}
|
|
2081
|
-
async saveResource({ resource }) {
|
|
2082
|
-
return this.stores.memory.saveResource({ resource });
|
|
2083
|
-
}
|
|
2084
|
-
async updateResource({
|
|
2085
|
-
resourceId,
|
|
2086
|
-
workingMemory,
|
|
2087
|
-
metadata
|
|
2088
|
-
}) {
|
|
2089
|
-
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
1945
|
+
return instance;
|
|
2090
1946
|
}
|
|
2091
1947
|
/**
|
|
2092
|
-
*
|
|
2093
|
-
*
|
|
2094
|
-
*
|
|
2095
|
-
* @returns The processed array with context messages included
|
|
1948
|
+
* @internal
|
|
1949
|
+
* Private constructor to enforce using the create factory method.
|
|
1950
|
+
* Note: stores is initialized in create() after the lanceClient is connected.
|
|
2096
1951
|
*/
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
return records;
|
|
2101
|
-
}
|
|
2102
|
-
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
2103
|
-
records.forEach((message, index) => {
|
|
2104
|
-
messageIndexMap.set(message.id, index);
|
|
2105
|
-
});
|
|
2106
|
-
const additionalIndices = /* @__PURE__ */ new Set();
|
|
2107
|
-
for (const item of messagesWithContext) {
|
|
2108
|
-
const messageIndex = messageIndexMap.get(item.id);
|
|
2109
|
-
if (messageIndex !== void 0) {
|
|
2110
|
-
if (item.withPreviousMessages) {
|
|
2111
|
-
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
2112
|
-
for (let i = startIdx; i < messageIndex; i++) {
|
|
2113
|
-
additionalIndices.add(i);
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
if (item.withNextMessages) {
|
|
2117
|
-
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
2118
|
-
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
2119
|
-
additionalIndices.add(i);
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2124
|
-
if (additionalIndices.size === 0) {
|
|
2125
|
-
return records;
|
|
2126
|
-
}
|
|
2127
|
-
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
2128
|
-
const allIndices = /* @__PURE__ */ new Set();
|
|
2129
|
-
records.forEach((record, index) => {
|
|
2130
|
-
if (originalMatchIds.has(record.id)) {
|
|
2131
|
-
allIndices.add(index);
|
|
2132
|
-
}
|
|
2133
|
-
});
|
|
2134
|
-
additionalIndices.forEach((index) => {
|
|
2135
|
-
allIndices.add(index);
|
|
2136
|
-
});
|
|
2137
|
-
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
2138
|
-
}
|
|
2139
|
-
async getMessages({
|
|
2140
|
-
threadId,
|
|
2141
|
-
resourceId,
|
|
2142
|
-
selectBy,
|
|
2143
|
-
format,
|
|
2144
|
-
threadConfig
|
|
2145
|
-
}) {
|
|
2146
|
-
return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format, threadConfig });
|
|
2147
|
-
}
|
|
2148
|
-
async getMessagesById({
|
|
2149
|
-
messageIds,
|
|
2150
|
-
format
|
|
2151
|
-
}) {
|
|
2152
|
-
return this.stores.memory.getMessagesById({ messageIds, format });
|
|
2153
|
-
}
|
|
2154
|
-
async saveMessages(args) {
|
|
2155
|
-
return this.stores.memory.saveMessages(args);
|
|
2156
|
-
}
|
|
2157
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
2158
|
-
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2159
|
-
}
|
|
2160
|
-
async getMessagesPaginated(args) {
|
|
2161
|
-
return this.stores.memory.getMessagesPaginated(args);
|
|
2162
|
-
}
|
|
2163
|
-
async updateMessages(_args) {
|
|
2164
|
-
return this.stores.memory.updateMessages(_args);
|
|
2165
|
-
}
|
|
2166
|
-
async getTraceById(args) {
|
|
2167
|
-
return this.stores.traces.getTraceById(args);
|
|
2168
|
-
}
|
|
2169
|
-
async getTraces(args) {
|
|
2170
|
-
return this.stores.traces.getTraces(args);
|
|
2171
|
-
}
|
|
2172
|
-
async getTracesPaginated(args) {
|
|
2173
|
-
return this.stores.traces.getTracesPaginated(args);
|
|
2174
|
-
}
|
|
2175
|
-
async getEvalsByAgentName(agentName, type) {
|
|
2176
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2177
|
-
}
|
|
2178
|
-
async getEvals(options) {
|
|
2179
|
-
return this.stores.legacyEvals.getEvals(options);
|
|
2180
|
-
}
|
|
2181
|
-
async getWorkflowRuns(args) {
|
|
2182
|
-
return this.stores.workflows.getWorkflowRuns(args);
|
|
2183
|
-
}
|
|
2184
|
-
async getWorkflowRunById(args) {
|
|
2185
|
-
return this.stores.workflows.getWorkflowRunById(args);
|
|
2186
|
-
}
|
|
2187
|
-
async updateWorkflowResults({
|
|
2188
|
-
workflowName,
|
|
2189
|
-
runId,
|
|
2190
|
-
stepId,
|
|
2191
|
-
result,
|
|
2192
|
-
runtimeContext
|
|
2193
|
-
}) {
|
|
2194
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
|
|
2195
|
-
}
|
|
2196
|
-
async updateWorkflowState({
|
|
2197
|
-
workflowName,
|
|
2198
|
-
runId,
|
|
2199
|
-
opts
|
|
2200
|
-
}) {
|
|
2201
|
-
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
2202
|
-
}
|
|
2203
|
-
async persistWorkflowSnapshot({
|
|
2204
|
-
workflowName,
|
|
2205
|
-
runId,
|
|
2206
|
-
snapshot
|
|
2207
|
-
}) {
|
|
2208
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
2209
|
-
}
|
|
2210
|
-
async loadWorkflowSnapshot({
|
|
2211
|
-
workflowName,
|
|
2212
|
-
runId
|
|
2213
|
-
}) {
|
|
2214
|
-
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
2215
|
-
}
|
|
2216
|
-
async getScoreById({ id: _id }) {
|
|
2217
|
-
return this.stores.scores.getScoreById({ id: _id });
|
|
2218
|
-
}
|
|
2219
|
-
async getScoresByScorerId({
|
|
2220
|
-
scorerId,
|
|
2221
|
-
source,
|
|
2222
|
-
entityId,
|
|
2223
|
-
entityType,
|
|
2224
|
-
pagination
|
|
2225
|
-
}) {
|
|
2226
|
-
return this.stores.scores.getScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
|
|
2227
|
-
}
|
|
2228
|
-
async saveScore(_score) {
|
|
2229
|
-
return this.stores.scores.saveScore(_score);
|
|
2230
|
-
}
|
|
2231
|
-
async getScoresByRunId({
|
|
2232
|
-
runId,
|
|
2233
|
-
pagination
|
|
2234
|
-
}) {
|
|
2235
|
-
return this.stores.scores.getScoresByRunId({ runId, pagination });
|
|
2236
|
-
}
|
|
2237
|
-
async getScoresByEntityId({
|
|
2238
|
-
entityId,
|
|
2239
|
-
entityType,
|
|
2240
|
-
pagination
|
|
2241
|
-
}) {
|
|
2242
|
-
return this.stores.scores.getScoresByEntityId({ entityId, entityType, pagination });
|
|
1952
|
+
constructor(id, name, disableInit) {
|
|
1953
|
+
super({ id, name, disableInit });
|
|
1954
|
+
this.stores = {};
|
|
2243
1955
|
}
|
|
2244
1956
|
};
|
|
2245
1957
|
var LanceFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
@@ -2588,14 +2300,14 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2588
2300
|
* ```
|
|
2589
2301
|
*/
|
|
2590
2302
|
static async create(uri, options) {
|
|
2591
|
-
const instance = new _LanceVectorStore();
|
|
2303
|
+
const instance = new _LanceVectorStore(options?.id || crypto.randomUUID());
|
|
2592
2304
|
try {
|
|
2593
2305
|
instance.lanceClient = await lancedb.connect(uri, options);
|
|
2594
2306
|
return instance;
|
|
2595
2307
|
} catch (e) {
|
|
2596
2308
|
throw new error.MastraError(
|
|
2597
2309
|
{
|
|
2598
|
-
id: "
|
|
2310
|
+
id: storage.createVectorErrorId("LANCE", "CONNECT", "FAILED"),
|
|
2599
2311
|
domain: error.ErrorDomain.STORAGE,
|
|
2600
2312
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2601
2313
|
details: { uri }
|
|
@@ -2608,8 +2320,8 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2608
2320
|
* @internal
|
|
2609
2321
|
* Private constructor to enforce using the create factory method
|
|
2610
2322
|
*/
|
|
2611
|
-
constructor() {
|
|
2612
|
-
super();
|
|
2323
|
+
constructor(id) {
|
|
2324
|
+
super({ id });
|
|
2613
2325
|
}
|
|
2614
2326
|
close() {
|
|
2615
2327
|
if (this.lanceClient) {
|
|
@@ -2638,7 +2350,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2638
2350
|
} catch (error$1) {
|
|
2639
2351
|
throw new error.MastraError(
|
|
2640
2352
|
{
|
|
2641
|
-
id: "
|
|
2353
|
+
id: storage.createVectorErrorId("LANCE", "QUERY", "INVALID_ARGS"),
|
|
2642
2354
|
domain: error.ErrorDomain.STORAGE,
|
|
2643
2355
|
category: error.ErrorCategory.USER,
|
|
2644
2356
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2686,7 +2398,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2686
2398
|
} catch (error$1) {
|
|
2687
2399
|
throw new error.MastraError(
|
|
2688
2400
|
{
|
|
2689
|
-
id: "
|
|
2401
|
+
id: storage.createVectorErrorId("LANCE", "QUERY", "FAILED"),
|
|
2690
2402
|
domain: error.ErrorDomain.STORAGE,
|
|
2691
2403
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2692
2404
|
details: { tableName, includeVector, columnsCount: columns?.length, includeAllColumns }
|
|
@@ -2738,7 +2450,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2738
2450
|
} catch (error$1) {
|
|
2739
2451
|
throw new error.MastraError(
|
|
2740
2452
|
{
|
|
2741
|
-
id: "
|
|
2453
|
+
id: storage.createVectorErrorId("LANCE", "UPSERT", "INVALID_ARGS"),
|
|
2742
2454
|
domain: error.ErrorDomain.STORAGE,
|
|
2743
2455
|
category: error.ErrorCategory.USER,
|
|
2744
2456
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2774,7 +2486,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2774
2486
|
} catch (error$1) {
|
|
2775
2487
|
throw new error.MastraError(
|
|
2776
2488
|
{
|
|
2777
|
-
id: "
|
|
2489
|
+
id: storage.createVectorErrorId("LANCE", "UPSERT", "FAILED"),
|
|
2778
2490
|
domain: error.ErrorDomain.STORAGE,
|
|
2779
2491
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2780
2492
|
details: { tableName, vectorCount: vectors.length, metadataCount: metadata.length, idsCount: ids.length }
|
|
@@ -2801,7 +2513,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2801
2513
|
async createTable(tableName, data, options) {
|
|
2802
2514
|
if (!this.lanceClient) {
|
|
2803
2515
|
throw new error.MastraError({
|
|
2804
|
-
id: "
|
|
2516
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_TABLE", "INVALID_ARGS"),
|
|
2805
2517
|
domain: error.ErrorDomain.STORAGE,
|
|
2806
2518
|
category: error.ErrorCategory.USER,
|
|
2807
2519
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2816,7 +2528,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2816
2528
|
} catch (error$1) {
|
|
2817
2529
|
throw new error.MastraError(
|
|
2818
2530
|
{
|
|
2819
|
-
id: "
|
|
2531
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_TABLE", "FAILED"),
|
|
2820
2532
|
domain: error.ErrorDomain.STORAGE,
|
|
2821
2533
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2822
2534
|
details: { tableName }
|
|
@@ -2828,7 +2540,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2828
2540
|
async listTables() {
|
|
2829
2541
|
if (!this.lanceClient) {
|
|
2830
2542
|
throw new error.MastraError({
|
|
2831
|
-
id: "
|
|
2543
|
+
id: storage.createVectorErrorId("LANCE", "LIST_TABLES", "INVALID_ARGS"),
|
|
2832
2544
|
domain: error.ErrorDomain.STORAGE,
|
|
2833
2545
|
category: error.ErrorCategory.USER,
|
|
2834
2546
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2840,7 +2552,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2840
2552
|
} catch (error$1) {
|
|
2841
2553
|
throw new error.MastraError(
|
|
2842
2554
|
{
|
|
2843
|
-
id: "
|
|
2555
|
+
id: storage.createVectorErrorId("LANCE", "LIST_TABLES", "FAILED"),
|
|
2844
2556
|
domain: error.ErrorDomain.STORAGE,
|
|
2845
2557
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2846
2558
|
},
|
|
@@ -2851,7 +2563,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2851
2563
|
async getTableSchema(tableName) {
|
|
2852
2564
|
if (!this.lanceClient) {
|
|
2853
2565
|
throw new error.MastraError({
|
|
2854
|
-
id: "
|
|
2566
|
+
id: storage.createVectorErrorId("LANCE", "GET_TABLE_SCHEMA", "INVALID_ARGS"),
|
|
2855
2567
|
domain: error.ErrorDomain.STORAGE,
|
|
2856
2568
|
category: error.ErrorCategory.USER,
|
|
2857
2569
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2864,7 +2576,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2864
2576
|
} catch (error$1) {
|
|
2865
2577
|
throw new error.MastraError(
|
|
2866
2578
|
{
|
|
2867
|
-
id: "
|
|
2579
|
+
id: storage.createVectorErrorId("LANCE", "GET_TABLE_SCHEMA", "FAILED"),
|
|
2868
2580
|
domain: error.ErrorDomain.STORAGE,
|
|
2869
2581
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2870
2582
|
details: { tableName }
|
|
@@ -2899,7 +2611,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2899
2611
|
} catch (err) {
|
|
2900
2612
|
throw new error.MastraError(
|
|
2901
2613
|
{
|
|
2902
|
-
id: "
|
|
2614
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "INVALID_ARGS"),
|
|
2903
2615
|
domain: error.ErrorDomain.STORAGE,
|
|
2904
2616
|
category: error.ErrorCategory.USER,
|
|
2905
2617
|
details: { tableName: tableName || "", indexName, dimension, metric }
|
|
@@ -2944,7 +2656,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2944
2656
|
} catch (error$1) {
|
|
2945
2657
|
throw new error.MastraError(
|
|
2946
2658
|
{
|
|
2947
|
-
id: "
|
|
2659
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "FAILED"),
|
|
2948
2660
|
domain: error.ErrorDomain.STORAGE,
|
|
2949
2661
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2950
2662
|
details: { tableName: tableName || "", indexName, dimension }
|
|
@@ -2956,7 +2668,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2956
2668
|
async listIndexes() {
|
|
2957
2669
|
if (!this.lanceClient) {
|
|
2958
2670
|
throw new error.MastraError({
|
|
2959
|
-
id: "
|
|
2671
|
+
id: storage.createVectorErrorId("LANCE", "LIST_INDEXES", "INVALID_ARGS"),
|
|
2960
2672
|
domain: error.ErrorDomain.STORAGE,
|
|
2961
2673
|
category: error.ErrorCategory.USER,
|
|
2962
2674
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2975,7 +2687,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2975
2687
|
} catch (error$1) {
|
|
2976
2688
|
throw new error.MastraError(
|
|
2977
2689
|
{
|
|
2978
|
-
id: "
|
|
2690
|
+
id: storage.createVectorErrorId("LANCE", "LIST_INDEXES", "FAILED"),
|
|
2979
2691
|
domain: error.ErrorDomain.STORAGE,
|
|
2980
2692
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2981
2693
|
},
|
|
@@ -2994,7 +2706,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2994
2706
|
} catch (err) {
|
|
2995
2707
|
throw new error.MastraError(
|
|
2996
2708
|
{
|
|
2997
|
-
id: "
|
|
2709
|
+
id: storage.createVectorErrorId("LANCE", "DESCRIBE_INDEX", "INVALID_ARGS"),
|
|
2998
2710
|
domain: error.ErrorDomain.STORAGE,
|
|
2999
2711
|
category: error.ErrorCategory.USER,
|
|
3000
2712
|
details: { indexName }
|
|
@@ -3029,7 +2741,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3029
2741
|
} catch (error$1) {
|
|
3030
2742
|
throw new error.MastraError(
|
|
3031
2743
|
{
|
|
3032
|
-
id: "
|
|
2744
|
+
id: storage.createVectorErrorId("LANCE", "DESCRIBE_INDEX", "FAILED"),
|
|
3033
2745
|
domain: error.ErrorDomain.STORAGE,
|
|
3034
2746
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3035
2747
|
details: { indexName }
|
|
@@ -3049,7 +2761,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3049
2761
|
} catch (err) {
|
|
3050
2762
|
throw new error.MastraError(
|
|
3051
2763
|
{
|
|
3052
|
-
id: "
|
|
2764
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_INDEX", "INVALID_ARGS"),
|
|
3053
2765
|
domain: error.ErrorDomain.STORAGE,
|
|
3054
2766
|
category: error.ErrorCategory.USER,
|
|
3055
2767
|
details: { indexName }
|
|
@@ -3072,7 +2784,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3072
2784
|
} catch (error$1) {
|
|
3073
2785
|
throw new error.MastraError(
|
|
3074
2786
|
{
|
|
3075
|
-
id: "
|
|
2787
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_INDEX", "FAILED"),
|
|
3076
2788
|
domain: error.ErrorDomain.STORAGE,
|
|
3077
2789
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3078
2790
|
details: { indexName }
|
|
@@ -3087,7 +2799,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3087
2799
|
async deleteAllTables() {
|
|
3088
2800
|
if (!this.lanceClient) {
|
|
3089
2801
|
throw new error.MastraError({
|
|
3090
|
-
id: "
|
|
2802
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_ALL_TABLES", "INVALID_ARGS"),
|
|
3091
2803
|
domain: error.ErrorDomain.STORAGE,
|
|
3092
2804
|
category: error.ErrorCategory.USER,
|
|
3093
2805
|
details: { methodName: "deleteAllTables" },
|
|
@@ -3099,7 +2811,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3099
2811
|
} catch (error$1) {
|
|
3100
2812
|
throw new error.MastraError(
|
|
3101
2813
|
{
|
|
3102
|
-
id: "
|
|
2814
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_ALL_TABLES", "FAILED"),
|
|
3103
2815
|
domain: error.ErrorDomain.STORAGE,
|
|
3104
2816
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3105
2817
|
details: { methodName: "deleteAllTables" }
|
|
@@ -3111,7 +2823,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3111
2823
|
async deleteTable(tableName) {
|
|
3112
2824
|
if (!this.lanceClient) {
|
|
3113
2825
|
throw new error.MastraError({
|
|
3114
|
-
id: "
|
|
2826
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_TABLE", "INVALID_ARGS"),
|
|
3115
2827
|
domain: error.ErrorDomain.STORAGE,
|
|
3116
2828
|
category: error.ErrorCategory.USER,
|
|
3117
2829
|
details: { tableName },
|
|
@@ -3123,7 +2835,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3123
2835
|
} catch (error$1) {
|
|
3124
2836
|
throw new error.MastraError(
|
|
3125
2837
|
{
|
|
3126
|
-
id: "
|
|
2838
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_TABLE", "FAILED"),
|
|
3127
2839
|
domain: error.ErrorDomain.STORAGE,
|
|
3128
2840
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3129
2841
|
details: { tableName }
|
|
@@ -3132,7 +2844,44 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3132
2844
|
);
|
|
3133
2845
|
}
|
|
3134
2846
|
}
|
|
3135
|
-
async updateVector(
|
|
2847
|
+
async updateVector(params) {
|
|
2848
|
+
const { indexName, update } = params;
|
|
2849
|
+
if ("id" in params && "filter" in params && params.id && params.filter) {
|
|
2850
|
+
throw new error.MastraError({
|
|
2851
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "MUTUALLY_EXCLUSIVE"),
|
|
2852
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2853
|
+
category: error.ErrorCategory.USER,
|
|
2854
|
+
text: "id and filter are mutually exclusive",
|
|
2855
|
+
details: { indexName }
|
|
2856
|
+
});
|
|
2857
|
+
}
|
|
2858
|
+
if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
|
|
2859
|
+
throw new error.MastraError({
|
|
2860
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "NO_TARGET"),
|
|
2861
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2862
|
+
category: error.ErrorCategory.USER,
|
|
2863
|
+
text: "Either id or filter must be provided",
|
|
2864
|
+
details: { indexName }
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
|
|
2868
|
+
throw new error.MastraError({
|
|
2869
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "EMPTY_FILTER"),
|
|
2870
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2871
|
+
category: error.ErrorCategory.USER,
|
|
2872
|
+
text: "Cannot update with empty filter",
|
|
2873
|
+
details: { indexName }
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
if (!update.vector && !update.metadata) {
|
|
2877
|
+
throw new error.MastraError({
|
|
2878
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "NO_PAYLOAD"),
|
|
2879
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2880
|
+
category: error.ErrorCategory.USER,
|
|
2881
|
+
text: "No updates provided",
|
|
2882
|
+
details: { indexName }
|
|
2883
|
+
});
|
|
2884
|
+
}
|
|
3136
2885
|
try {
|
|
3137
2886
|
if (!this.lanceClient) {
|
|
3138
2887
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
@@ -3140,21 +2889,6 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3140
2889
|
if (!indexName) {
|
|
3141
2890
|
throw new Error("indexName is required");
|
|
3142
2891
|
}
|
|
3143
|
-
if (!id) {
|
|
3144
|
-
throw new Error("id is required");
|
|
3145
|
-
}
|
|
3146
|
-
} catch (err) {
|
|
3147
|
-
throw new error.MastraError(
|
|
3148
|
-
{
|
|
3149
|
-
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED_INVALID_ARGS",
|
|
3150
|
-
domain: error.ErrorDomain.STORAGE,
|
|
3151
|
-
category: error.ErrorCategory.USER,
|
|
3152
|
-
details: { indexName, id }
|
|
3153
|
-
},
|
|
3154
|
-
err
|
|
3155
|
-
);
|
|
3156
|
-
}
|
|
3157
|
-
try {
|
|
3158
2892
|
const tables = await this.lanceClient.tableNames();
|
|
3159
2893
|
for (const tableName of tables) {
|
|
3160
2894
|
this.logger.debug("Checking table:" + tableName);
|
|
@@ -3164,39 +2898,66 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3164
2898
|
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3165
2899
|
if (hasColumn) {
|
|
3166
2900
|
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3167
|
-
|
|
3168
|
-
if (
|
|
3169
|
-
|
|
2901
|
+
let whereClause;
|
|
2902
|
+
if ("id" in params && params.id) {
|
|
2903
|
+
whereClause = `id = '${params.id}'`;
|
|
2904
|
+
} else if ("filter" in params && params.filter) {
|
|
2905
|
+
const translator = new LanceFilterTranslator();
|
|
2906
|
+
const processFilterKeys = (filter) => {
|
|
2907
|
+
const processedFilter = {};
|
|
2908
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
2909
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
2910
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
2911
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
2912
|
+
});
|
|
2913
|
+
} else {
|
|
2914
|
+
processedFilter[`metadata_${key}`] = value;
|
|
2915
|
+
}
|
|
2916
|
+
});
|
|
2917
|
+
return processedFilter;
|
|
2918
|
+
};
|
|
2919
|
+
const prefixedFilter = processFilterKeys(params.filter);
|
|
2920
|
+
whereClause = translator.translate(prefixedFilter) || "";
|
|
2921
|
+
if (!whereClause) {
|
|
2922
|
+
throw new Error("Failed to translate filter to SQL");
|
|
2923
|
+
}
|
|
2924
|
+
} else {
|
|
2925
|
+
throw new Error("Either id or filter must be provided");
|
|
3170
2926
|
}
|
|
3171
|
-
const
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
2927
|
+
const existingRecords = await table.query().where(whereClause).select(schema.fields.map((field) => field.name)).toArray();
|
|
2928
|
+
if (existingRecords.length === 0) {
|
|
2929
|
+
this.logger.info(`No records found matching criteria in table ${tableName}`);
|
|
2930
|
+
return;
|
|
2931
|
+
}
|
|
2932
|
+
const updatedRecords = existingRecords.map((record) => {
|
|
2933
|
+
const rowData = {};
|
|
2934
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
2935
|
+
if (key !== "_distance") {
|
|
2936
|
+
if (key === indexName) {
|
|
2937
|
+
if (update.vector) {
|
|
2938
|
+
rowData[key] = update.vector;
|
|
3182
2939
|
} else {
|
|
3183
|
-
|
|
2940
|
+
if (Array.isArray(value)) {
|
|
2941
|
+
rowData[key] = [...value];
|
|
2942
|
+
} else if (typeof value === "object" && value !== null) {
|
|
2943
|
+
rowData[key] = Array.from(value);
|
|
2944
|
+
} else {
|
|
2945
|
+
rowData[key] = value;
|
|
2946
|
+
}
|
|
3184
2947
|
}
|
|
2948
|
+
} else {
|
|
2949
|
+
rowData[key] = value;
|
|
3185
2950
|
}
|
|
3186
|
-
} else {
|
|
3187
|
-
rowData[key] = value;
|
|
3188
2951
|
}
|
|
2952
|
+
});
|
|
2953
|
+
if (update.metadata) {
|
|
2954
|
+
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
2955
|
+
rowData[`metadata_${key}`] = value;
|
|
2956
|
+
});
|
|
3189
2957
|
}
|
|
2958
|
+
return rowData;
|
|
3190
2959
|
});
|
|
3191
|
-
|
|
3192
|
-
rowData[indexName] = update.vector;
|
|
3193
|
-
}
|
|
3194
|
-
if (update.metadata) {
|
|
3195
|
-
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
3196
|
-
rowData[`metadata_${key}`] = value;
|
|
3197
|
-
});
|
|
3198
|
-
}
|
|
3199
|
-
await table.add([rowData], { mode: "overwrite" });
|
|
2960
|
+
await table.add(updatedRecords, { mode: "overwrite" });
|
|
3200
2961
|
return;
|
|
3201
2962
|
}
|
|
3202
2963
|
} catch (err) {
|
|
@@ -3206,12 +2967,19 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3206
2967
|
}
|
|
3207
2968
|
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3208
2969
|
} catch (error$1) {
|
|
2970
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
3209
2971
|
throw new error.MastraError(
|
|
3210
2972
|
{
|
|
3211
|
-
id: "
|
|
2973
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "FAILED"),
|
|
3212
2974
|
domain: error.ErrorDomain.STORAGE,
|
|
3213
2975
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3214
|
-
details: {
|
|
2976
|
+
details: {
|
|
2977
|
+
indexName,
|
|
2978
|
+
..."id" in params && params.id && { id: params.id },
|
|
2979
|
+
..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) },
|
|
2980
|
+
hasVector: !!update.vector,
|
|
2981
|
+
hasMetadata: !!update.metadata
|
|
2982
|
+
}
|
|
3215
2983
|
},
|
|
3216
2984
|
error$1
|
|
3217
2985
|
);
|
|
@@ -3231,10 +2999,13 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3231
2999
|
} catch (err) {
|
|
3232
3000
|
throw new error.MastraError(
|
|
3233
3001
|
{
|
|
3234
|
-
id: "
|
|
3002
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTOR", "INVALID_ARGS"),
|
|
3235
3003
|
domain: error.ErrorDomain.STORAGE,
|
|
3236
3004
|
category: error.ErrorCategory.USER,
|
|
3237
|
-
details: {
|
|
3005
|
+
details: {
|
|
3006
|
+
indexName,
|
|
3007
|
+
...id && { id }
|
|
3008
|
+
}
|
|
3238
3009
|
},
|
|
3239
3010
|
err
|
|
3240
3011
|
);
|
|
@@ -3261,10 +3032,13 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3261
3032
|
} catch (error$1) {
|
|
3262
3033
|
throw new error.MastraError(
|
|
3263
3034
|
{
|
|
3264
|
-
id: "
|
|
3035
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTOR", "FAILED"),
|
|
3265
3036
|
domain: error.ErrorDomain.STORAGE,
|
|
3266
3037
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3267
|
-
details: {
|
|
3038
|
+
details: {
|
|
3039
|
+
indexName,
|
|
3040
|
+
...id && { id }
|
|
3041
|
+
}
|
|
3268
3042
|
},
|
|
3269
3043
|
error$1
|
|
3270
3044
|
);
|
|
@@ -3295,9 +3069,115 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3295
3069
|
});
|
|
3296
3070
|
return result;
|
|
3297
3071
|
}
|
|
3072
|
+
async deleteVectors({ indexName, filter, ids }) {
|
|
3073
|
+
if (ids && filter) {
|
|
3074
|
+
throw new error.MastraError({
|
|
3075
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "MUTUALLY_EXCLUSIVE"),
|
|
3076
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3077
|
+
category: error.ErrorCategory.USER,
|
|
3078
|
+
text: "ids and filter are mutually exclusive",
|
|
3079
|
+
details: { indexName }
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
if (!ids && !filter) {
|
|
3083
|
+
throw new error.MastraError({
|
|
3084
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "NO_TARGET"),
|
|
3085
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3086
|
+
category: error.ErrorCategory.USER,
|
|
3087
|
+
text: "Either filter or ids must be provided",
|
|
3088
|
+
details: { indexName }
|
|
3089
|
+
});
|
|
3090
|
+
}
|
|
3091
|
+
if (ids && ids.length === 0) {
|
|
3092
|
+
throw new error.MastraError({
|
|
3093
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "EMPTY_IDS"),
|
|
3094
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3095
|
+
category: error.ErrorCategory.USER,
|
|
3096
|
+
text: "Cannot delete with empty ids array",
|
|
3097
|
+
details: { indexName }
|
|
3098
|
+
});
|
|
3099
|
+
}
|
|
3100
|
+
if (filter && Object.keys(filter).length === 0) {
|
|
3101
|
+
throw new error.MastraError({
|
|
3102
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "EMPTY_FILTER"),
|
|
3103
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3104
|
+
category: error.ErrorCategory.USER,
|
|
3105
|
+
text: "Cannot delete with empty filter",
|
|
3106
|
+
details: { indexName }
|
|
3107
|
+
});
|
|
3108
|
+
}
|
|
3109
|
+
try {
|
|
3110
|
+
if (!this.lanceClient) {
|
|
3111
|
+
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
3112
|
+
}
|
|
3113
|
+
if (!indexName) {
|
|
3114
|
+
throw new Error("indexName is required");
|
|
3115
|
+
}
|
|
3116
|
+
const tables = await this.lanceClient.tableNames();
|
|
3117
|
+
for (const tableName of tables) {
|
|
3118
|
+
this.logger.debug("Checking table:" + tableName);
|
|
3119
|
+
const table = await this.lanceClient.openTable(tableName);
|
|
3120
|
+
try {
|
|
3121
|
+
const schema = await table.schema();
|
|
3122
|
+
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3123
|
+
if (hasColumn) {
|
|
3124
|
+
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3125
|
+
if (ids) {
|
|
3126
|
+
const idsConditions = ids.map((id) => `id = '${id}'`).join(" OR ");
|
|
3127
|
+
await table.delete(idsConditions);
|
|
3128
|
+
} else if (filter) {
|
|
3129
|
+
const translator = new LanceFilterTranslator();
|
|
3130
|
+
const processFilterKeys = (filter2) => {
|
|
3131
|
+
const processedFilter = {};
|
|
3132
|
+
Object.entries(filter2).forEach(([key, value]) => {
|
|
3133
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3134
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
3135
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
3136
|
+
});
|
|
3137
|
+
} else {
|
|
3138
|
+
processedFilter[`metadata_${key}`] = value;
|
|
3139
|
+
}
|
|
3140
|
+
});
|
|
3141
|
+
return processedFilter;
|
|
3142
|
+
};
|
|
3143
|
+
const prefixedFilter = processFilterKeys(filter);
|
|
3144
|
+
const whereClause = translator.translate(prefixedFilter);
|
|
3145
|
+
if (!whereClause) {
|
|
3146
|
+
throw new Error("Failed to translate filter to SQL");
|
|
3147
|
+
}
|
|
3148
|
+
await table.delete(whereClause);
|
|
3149
|
+
}
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
} catch (err) {
|
|
3153
|
+
this.logger.error(`Error checking schema for table ${tableName}:` + err);
|
|
3154
|
+
continue;
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3158
|
+
} catch (error$1) {
|
|
3159
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
3160
|
+
throw new error.MastraError(
|
|
3161
|
+
{
|
|
3162
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "FAILED"),
|
|
3163
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3164
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
3165
|
+
details: {
|
|
3166
|
+
indexName,
|
|
3167
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
3168
|
+
...ids && { idsCount: ids.length }
|
|
3169
|
+
}
|
|
3170
|
+
},
|
|
3171
|
+
error$1
|
|
3172
|
+
);
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3298
3175
|
};
|
|
3299
3176
|
|
|
3300
3177
|
exports.LanceStorage = LanceStorage;
|
|
3301
3178
|
exports.LanceVectorStore = LanceVectorStore;
|
|
3179
|
+
exports.StoreMemoryLance = StoreMemoryLance;
|
|
3180
|
+
exports.StoreScoresLance = StoreScoresLance;
|
|
3181
|
+
exports.StoreWorkflowsLance = StoreWorkflowsLance;
|
|
3302
3182
|
//# sourceMappingURL=index.cjs.map
|
|
3303
3183
|
//# sourceMappingURL=index.cjs.map
|