@mastra/lance 0.0.0-share-agent-metadata-with-cloud-20250718123411 → 0.0.0-span-scorring-test-20251124132129
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 +948 -2
- package/README.md +64 -7
- package/dist/index.cjs +1657 -695
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1658 -696
- package/dist/index.js.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +79 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -0
- package/dist/storage/domains/operations/index.d.ts +40 -0
- package/dist/storage/domains/operations/index.d.ts.map +1 -0
- package/dist/storage/domains/scores/index.d.ts +50 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -0
- package/dist/storage/domains/utils.d.ts +10 -0
- package/dist/storage/domains/utils.d.ts.map +1 -0
- package/dist/storage/domains/workflows/index.d.ts +50 -0
- package/dist/storage/domains/workflows/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +211 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/vector/filter.d.ts +41 -0
- package/dist/vector/filter.d.ts.map +1 -0
- package/dist/vector/index.d.ts +88 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/dist/vector/types.d.ts +15 -0
- package/dist/vector/types.d.ts.map +1 -0
- package/package.json +31 -12
- package/dist/_tsup-dts-rollup.d.cts +0 -409
- package/dist/_tsup-dts-rollup.d.ts +0 -409
- package/dist/index.d.cts +0 -2
- package/eslint.config.js +0 -6
- package/src/index.ts +0 -2
- package/src/storage/index.test.ts +0 -1336
- package/src/storage/index.ts +0 -1447
- package/src/vector/filter.test.ts +0 -295
- package/src/vector/filter.ts +0 -443
- package/src/vector/index.test.ts +0 -1493
- package/src/vector/index.ts +0 -941
- package/src/vector/types.ts +0 -16
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -11
package/dist/index.cjs
CHANGED
|
@@ -1,112 +1,859 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var lancedb = require('@lancedb/lancedb');
|
|
4
|
-
var agent = require('@mastra/core/agent');
|
|
5
4
|
var error = require('@mastra/core/error');
|
|
6
5
|
var storage = require('@mastra/core/storage');
|
|
6
|
+
var agent = require('@mastra/core/agent');
|
|
7
7
|
var apacheArrow = require('apache-arrow');
|
|
8
|
+
var evals = require('@mastra/core/evals');
|
|
8
9
|
var vector = require('@mastra/core/vector');
|
|
9
10
|
var filter = require('@mastra/core/vector/filter');
|
|
10
11
|
|
|
11
12
|
// src/storage/index.ts
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
function getPrimaryKeys(tableName) {
|
|
14
|
+
let primaryId = ["id"];
|
|
15
|
+
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
16
|
+
primaryId = ["workflow_name", "run_id"];
|
|
17
|
+
}
|
|
18
|
+
return primaryId;
|
|
19
|
+
}
|
|
20
|
+
function validateKeyTypes(keys, tableSchema) {
|
|
21
|
+
const fieldTypes = new Map(
|
|
22
|
+
tableSchema.fields.map((field) => [field.name, field.type?.toString().toLowerCase()])
|
|
23
|
+
);
|
|
24
|
+
for (const [key, value] of Object.entries(keys)) {
|
|
25
|
+
const fieldType = fieldTypes.get(key);
|
|
26
|
+
if (!fieldType) {
|
|
27
|
+
throw new Error(`Field '${key}' does not exist in table schema`);
|
|
28
|
+
}
|
|
29
|
+
if (value !== null) {
|
|
30
|
+
if ((fieldType.includes("int") || fieldType.includes("bigint")) && typeof value !== "number") {
|
|
31
|
+
throw new Error(`Expected numeric value for field '${key}', got ${typeof value}`);
|
|
32
|
+
}
|
|
33
|
+
if (fieldType.includes("utf8") && typeof value !== "string") {
|
|
34
|
+
throw new Error(`Expected string value for field '${key}', got ${typeof value}`);
|
|
35
|
+
}
|
|
36
|
+
if (fieldType.includes("timestamp") && !(value instanceof Date) && typeof value !== "string") {
|
|
37
|
+
throw new Error(`Expected Date or string value for field '${key}', got ${typeof value}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function processResultWithTypeConversion(rawResult, tableSchema) {
|
|
43
|
+
const fieldTypeMap = /* @__PURE__ */ new Map();
|
|
44
|
+
tableSchema.fields.forEach((field) => {
|
|
45
|
+
const fieldName = field.name;
|
|
46
|
+
const fieldTypeStr = field.type.toString().toLowerCase();
|
|
47
|
+
fieldTypeMap.set(fieldName, fieldTypeStr);
|
|
48
|
+
});
|
|
49
|
+
if (Array.isArray(rawResult)) {
|
|
50
|
+
return rawResult.map((item) => processResultWithTypeConversion(item, tableSchema));
|
|
51
|
+
}
|
|
52
|
+
const processedResult = { ...rawResult };
|
|
53
|
+
for (const key in processedResult) {
|
|
54
|
+
const fieldTypeStr = fieldTypeMap.get(key);
|
|
55
|
+
if (!fieldTypeStr) continue;
|
|
56
|
+
if (typeof processedResult[key] === "string") {
|
|
57
|
+
if (fieldTypeStr.includes("int32") || fieldTypeStr.includes("float32")) {
|
|
58
|
+
if (!isNaN(Number(processedResult[key]))) {
|
|
59
|
+
processedResult[key] = Number(processedResult[key]);
|
|
60
|
+
}
|
|
61
|
+
} else if (fieldTypeStr.includes("int64")) {
|
|
62
|
+
processedResult[key] = Number(processedResult[key]);
|
|
63
|
+
} else if (fieldTypeStr.includes("utf8") && key !== "id") {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(processedResult[key]);
|
|
66
|
+
if (typeof parsed === "object") {
|
|
67
|
+
processedResult[key] = JSON.parse(processedResult[key]);
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else if (typeof processedResult[key] === "bigint") {
|
|
73
|
+
processedResult[key] = Number(processedResult[key]);
|
|
74
|
+
} else if (fieldTypeStr.includes("float64") && ["createdAt", "updatedAt"].includes(key)) {
|
|
75
|
+
processedResult[key] = new Date(processedResult[key]);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return processedResult;
|
|
79
|
+
}
|
|
80
|
+
async function getTableSchema({
|
|
81
|
+
tableName,
|
|
82
|
+
client
|
|
83
|
+
}) {
|
|
84
|
+
try {
|
|
85
|
+
if (!client) {
|
|
86
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
87
|
+
}
|
|
88
|
+
if (!tableName) {
|
|
89
|
+
throw new Error("tableName is required for getTableSchema.");
|
|
90
|
+
}
|
|
91
|
+
} catch (validationError) {
|
|
92
|
+
throw new error.MastraError(
|
|
93
|
+
{
|
|
94
|
+
id: "STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_INVALID_ARGS",
|
|
95
|
+
domain: error.ErrorDomain.STORAGE,
|
|
96
|
+
category: error.ErrorCategory.USER,
|
|
97
|
+
text: validationError.message,
|
|
98
|
+
details: { tableName }
|
|
99
|
+
},
|
|
100
|
+
validationError
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const table = await client.openTable(tableName);
|
|
105
|
+
const rawSchema = await table.schema();
|
|
106
|
+
const fields = rawSchema.fields;
|
|
107
|
+
return {
|
|
108
|
+
fields,
|
|
109
|
+
metadata: /* @__PURE__ */ new Map(),
|
|
110
|
+
get names() {
|
|
111
|
+
return fields.map((field) => field.name);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
} catch (error$1) {
|
|
115
|
+
throw new error.MastraError(
|
|
116
|
+
{
|
|
117
|
+
id: "STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_FAILED",
|
|
118
|
+
domain: error.ErrorDomain.STORAGE,
|
|
119
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
120
|
+
details: { tableName }
|
|
121
|
+
},
|
|
122
|
+
error$1
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/storage/domains/memory/index.ts
|
|
128
|
+
var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
129
|
+
client;
|
|
130
|
+
operations;
|
|
131
|
+
constructor({ client, operations }) {
|
|
132
|
+
super();
|
|
133
|
+
this.client = client;
|
|
134
|
+
this.operations = operations;
|
|
135
|
+
}
|
|
136
|
+
// Utility to escape single quotes in SQL strings
|
|
137
|
+
escapeSql(str) {
|
|
138
|
+
return str.replace(/'/g, "''");
|
|
139
|
+
}
|
|
140
|
+
async getThreadById({ threadId }) {
|
|
141
|
+
try {
|
|
142
|
+
const thread = await this.operations.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
143
|
+
if (!thread) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
...thread,
|
|
148
|
+
createdAt: new Date(thread.createdAt),
|
|
149
|
+
updatedAt: new Date(thread.updatedAt)
|
|
150
|
+
};
|
|
151
|
+
} catch (error$1) {
|
|
152
|
+
throw new error.MastraError(
|
|
153
|
+
{
|
|
154
|
+
id: "LANCE_STORE_GET_THREAD_BY_ID_FAILED",
|
|
155
|
+
domain: error.ErrorDomain.STORAGE,
|
|
156
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
157
|
+
},
|
|
158
|
+
error$1
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
14
162
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @param
|
|
17
|
-
* @
|
|
18
|
-
*
|
|
19
|
-
* Usage:
|
|
20
|
-
*
|
|
21
|
-
* Connect to a local database
|
|
22
|
-
* ```ts
|
|
23
|
-
* const store = await LanceStorage.create('/path/to/db');
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Connect to a LanceDB cloud database
|
|
27
|
-
* ```ts
|
|
28
|
-
* const store = await LanceStorage.create('db://host:port');
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* Connect to a cloud database
|
|
32
|
-
* ```ts
|
|
33
|
-
* const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
34
|
-
* ```
|
|
163
|
+
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
164
|
+
* @param thread - The thread to save
|
|
165
|
+
* @returns The saved thread
|
|
35
166
|
*/
|
|
36
|
-
|
|
37
|
-
const instance = new _LanceStorage(name);
|
|
167
|
+
async saveThread({ thread }) {
|
|
38
168
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
169
|
+
const record = { ...thread, metadata: JSON.stringify(thread.metadata) };
|
|
170
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
171
|
+
await table.add([record], { mode: "append" });
|
|
172
|
+
return thread;
|
|
173
|
+
} catch (error$1) {
|
|
42
174
|
throw new error.MastraError(
|
|
43
175
|
{
|
|
44
|
-
id: "
|
|
176
|
+
id: "LANCE_STORE_SAVE_THREAD_FAILED",
|
|
177
|
+
domain: error.ErrorDomain.STORAGE,
|
|
178
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
179
|
+
},
|
|
180
|
+
error$1
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async updateThread({
|
|
185
|
+
id,
|
|
186
|
+
title,
|
|
187
|
+
metadata
|
|
188
|
+
}) {
|
|
189
|
+
const maxRetries = 5;
|
|
190
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
191
|
+
try {
|
|
192
|
+
const current = await this.getThreadById({ threadId: id });
|
|
193
|
+
if (!current) {
|
|
194
|
+
throw new Error(`Thread with id ${id} not found`);
|
|
195
|
+
}
|
|
196
|
+
const mergedMetadata = { ...current.metadata, ...metadata };
|
|
197
|
+
const record = {
|
|
198
|
+
id,
|
|
199
|
+
title,
|
|
200
|
+
metadata: JSON.stringify(mergedMetadata),
|
|
201
|
+
updatedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
202
|
+
};
|
|
203
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
204
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
205
|
+
const updatedThread = await this.getThreadById({ threadId: id });
|
|
206
|
+
if (!updatedThread) {
|
|
207
|
+
throw new Error(`Failed to retrieve updated thread ${id}`);
|
|
208
|
+
}
|
|
209
|
+
return updatedThread;
|
|
210
|
+
} catch (error$1) {
|
|
211
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
212
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
213
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
throw new error.MastraError(
|
|
217
|
+
{
|
|
218
|
+
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
219
|
+
domain: error.ErrorDomain.STORAGE,
|
|
220
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
221
|
+
},
|
|
222
|
+
error$1
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
throw new error.MastraError(
|
|
227
|
+
{
|
|
228
|
+
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
229
|
+
domain: error.ErrorDomain.STORAGE,
|
|
230
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
231
|
+
},
|
|
232
|
+
new Error("All retries exhausted")
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
async deleteThread({ threadId }) {
|
|
236
|
+
try {
|
|
237
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
238
|
+
await table.delete(`id = '${threadId}'`);
|
|
239
|
+
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
240
|
+
await messagesTable.delete(`thread_id = '${threadId}'`);
|
|
241
|
+
} catch (error$1) {
|
|
242
|
+
throw new error.MastraError(
|
|
243
|
+
{
|
|
244
|
+
id: "LANCE_STORE_DELETE_THREAD_FAILED",
|
|
245
|
+
domain: error.ErrorDomain.STORAGE,
|
|
246
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
247
|
+
},
|
|
248
|
+
error$1
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
normalizeMessage(message) {
|
|
253
|
+
const { thread_id, ...rest } = message;
|
|
254
|
+
return {
|
|
255
|
+
...rest,
|
|
256
|
+
threadId: thread_id,
|
|
257
|
+
content: typeof message.content === "string" ? (() => {
|
|
258
|
+
try {
|
|
259
|
+
return JSON.parse(message.content);
|
|
260
|
+
} catch {
|
|
261
|
+
return message.content;
|
|
262
|
+
}
|
|
263
|
+
})() : message.content
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
async listMessagesById({ messageIds }) {
|
|
267
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
268
|
+
try {
|
|
269
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
270
|
+
const quotedIds = messageIds.map((id) => `'${id}'`).join(", ");
|
|
271
|
+
const allRecords = await table.query().where(`id IN (${quotedIds})`).toArray();
|
|
272
|
+
const messages = processResultWithTypeConversion(
|
|
273
|
+
allRecords,
|
|
274
|
+
await getTableSchema({ tableName: storage.TABLE_MESSAGES, client: this.client })
|
|
275
|
+
);
|
|
276
|
+
const list = new agent.MessageList().add(
|
|
277
|
+
messages.map(this.normalizeMessage),
|
|
278
|
+
"memory"
|
|
279
|
+
);
|
|
280
|
+
return { messages: list.get.all.db() };
|
|
281
|
+
} catch (error$1) {
|
|
282
|
+
throw new error.MastraError(
|
|
283
|
+
{
|
|
284
|
+
id: "LANCE_STORE_LIST_MESSAGES_BY_ID_FAILED",
|
|
45
285
|
domain: error.ErrorDomain.STORAGE,
|
|
46
286
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
47
|
-
|
|
48
|
-
|
|
287
|
+
details: {
|
|
288
|
+
messageIds: JSON.stringify(messageIds)
|
|
289
|
+
}
|
|
49
290
|
},
|
|
50
|
-
|
|
291
|
+
error$1
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
async listMessages(args) {
|
|
296
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
297
|
+
if (!threadId.trim()) {
|
|
298
|
+
throw new error.MastraError(
|
|
299
|
+
{
|
|
300
|
+
id: "STORAGE_LANCE_LIST_MESSAGES_INVALID_THREAD_ID",
|
|
301
|
+
domain: error.ErrorDomain.STORAGE,
|
|
302
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
303
|
+
details: { threadId }
|
|
304
|
+
},
|
|
305
|
+
new Error("threadId must be a non-empty string")
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
309
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
310
|
+
try {
|
|
311
|
+
if (page < 0) {
|
|
312
|
+
throw new error.MastraError(
|
|
313
|
+
{
|
|
314
|
+
id: "STORAGE_LANCE_LIST_MESSAGES_INVALID_PAGE",
|
|
315
|
+
domain: error.ErrorDomain.STORAGE,
|
|
316
|
+
category: error.ErrorCategory.USER,
|
|
317
|
+
details: { page }
|
|
318
|
+
},
|
|
319
|
+
new Error("page must be >= 0")
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
323
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
324
|
+
const conditions = [`thread_id = '${this.escapeSql(threadId)}'`];
|
|
325
|
+
if (resourceId) {
|
|
326
|
+
conditions.push(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
327
|
+
}
|
|
328
|
+
if (filter?.dateRange?.start) {
|
|
329
|
+
const startTime = filter.dateRange.start instanceof Date ? filter.dateRange.start.getTime() : new Date(filter.dateRange.start).getTime();
|
|
330
|
+
conditions.push(`\`createdAt\` >= ${startTime}`);
|
|
331
|
+
}
|
|
332
|
+
if (filter?.dateRange?.end) {
|
|
333
|
+
const endTime = filter.dateRange.end instanceof Date ? filter.dateRange.end.getTime() : new Date(filter.dateRange.end).getTime();
|
|
334
|
+
conditions.push(`\`createdAt\` <= ${endTime}`);
|
|
335
|
+
}
|
|
336
|
+
const whereClause = conditions.join(" AND ");
|
|
337
|
+
const total = await table.countRows(whereClause);
|
|
338
|
+
const query = table.query().where(whereClause);
|
|
339
|
+
let allRecords = await query.toArray();
|
|
340
|
+
allRecords.sort((a, b) => {
|
|
341
|
+
const aValue = field === "createdAt" ? a.createdAt : a[field];
|
|
342
|
+
const bValue = field === "createdAt" ? b.createdAt : b[field];
|
|
343
|
+
if (aValue == null && bValue == null) return 0;
|
|
344
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
345
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
346
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
347
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
348
|
+
}
|
|
349
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
350
|
+
});
|
|
351
|
+
const paginatedRecords = allRecords.slice(offset, offset + perPage);
|
|
352
|
+
const messages = paginatedRecords.map((row) => this.normalizeMessage(row));
|
|
353
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
354
|
+
return {
|
|
355
|
+
messages: [],
|
|
356
|
+
total: 0,
|
|
357
|
+
page,
|
|
358
|
+
perPage: perPageForResponse,
|
|
359
|
+
hasMore: false
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
363
|
+
if (include && include.length > 0) {
|
|
364
|
+
const threadIds = [...new Set(include.map((item) => item.threadId || threadId))];
|
|
365
|
+
const allThreadMessages = [];
|
|
366
|
+
for (const tid of threadIds) {
|
|
367
|
+
const threadQuery = table.query().where(`thread_id = '${tid}'`);
|
|
368
|
+
let threadRecords = await threadQuery.toArray();
|
|
369
|
+
allThreadMessages.push(...threadRecords);
|
|
370
|
+
}
|
|
371
|
+
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
372
|
+
const contextMessages = this.processMessagesWithContext(allThreadMessages, include);
|
|
373
|
+
const includedMessages = contextMessages.map((row) => this.normalizeMessage(row));
|
|
374
|
+
for (const includeMsg of includedMessages) {
|
|
375
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
376
|
+
messages.push(includeMsg);
|
|
377
|
+
messageIds.add(includeMsg.id);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
382
|
+
let finalMessages = list.get.all.db();
|
|
383
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
384
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
385
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
386
|
+
if (aValue == null && bValue == null) return 0;
|
|
387
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
388
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
389
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
390
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
391
|
+
}
|
|
392
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
393
|
+
});
|
|
394
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
395
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
396
|
+
const fetchedAll = perPageInput === false || allThreadMessagesReturned;
|
|
397
|
+
const hasMore = !fetchedAll && offset + perPage < total;
|
|
398
|
+
return {
|
|
399
|
+
messages: finalMessages,
|
|
400
|
+
total,
|
|
401
|
+
page,
|
|
402
|
+
perPage: perPageForResponse,
|
|
403
|
+
hasMore
|
|
404
|
+
};
|
|
405
|
+
} catch (error$1) {
|
|
406
|
+
const mastraError = new error.MastraError(
|
|
407
|
+
{
|
|
408
|
+
id: "LANCE_STORE_LIST_MESSAGES_FAILED",
|
|
409
|
+
domain: error.ErrorDomain.STORAGE,
|
|
410
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
411
|
+
details: {
|
|
412
|
+
threadId,
|
|
413
|
+
resourceId: resourceId ?? ""
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
error$1
|
|
417
|
+
);
|
|
418
|
+
this.logger?.error?.(mastraError.toString());
|
|
419
|
+
this.logger?.trackException?.(mastraError);
|
|
420
|
+
return {
|
|
421
|
+
messages: [],
|
|
422
|
+
total: 0,
|
|
423
|
+
page,
|
|
424
|
+
perPage: perPageForResponse,
|
|
425
|
+
hasMore: false
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async saveMessages(args) {
|
|
430
|
+
try {
|
|
431
|
+
const { messages } = args;
|
|
432
|
+
if (messages.length === 0) {
|
|
433
|
+
return { messages: [] };
|
|
434
|
+
}
|
|
435
|
+
const threadId = messages[0]?.threadId;
|
|
436
|
+
if (!threadId) {
|
|
437
|
+
throw new Error("Thread ID is required");
|
|
438
|
+
}
|
|
439
|
+
for (const message of messages) {
|
|
440
|
+
if (!message.id) {
|
|
441
|
+
throw new Error("Message ID is required");
|
|
442
|
+
}
|
|
443
|
+
if (!message.threadId) {
|
|
444
|
+
throw new Error("Thread ID is required for all messages");
|
|
445
|
+
}
|
|
446
|
+
if (message.resourceId === null || message.resourceId === void 0) {
|
|
447
|
+
throw new Error("Resource ID cannot be null or undefined");
|
|
448
|
+
}
|
|
449
|
+
if (!message.content) {
|
|
450
|
+
throw new Error("Message content is required");
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
const transformedMessages = messages.map((message) => {
|
|
454
|
+
const { threadId: threadId2, type, ...rest } = message;
|
|
455
|
+
return {
|
|
456
|
+
...rest,
|
|
457
|
+
thread_id: threadId2,
|
|
458
|
+
type: type ?? "v2",
|
|
459
|
+
content: JSON.stringify(message.content)
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
463
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
464
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
465
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
466
|
+
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
467
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
468
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
469
|
+
return { messages: list.get.all.db() };
|
|
470
|
+
} catch (error$1) {
|
|
471
|
+
throw new error.MastraError(
|
|
472
|
+
{
|
|
473
|
+
id: "LANCE_STORE_SAVE_MESSAGES_FAILED",
|
|
474
|
+
domain: error.ErrorDomain.STORAGE,
|
|
475
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
476
|
+
},
|
|
477
|
+
error$1
|
|
51
478
|
);
|
|
52
479
|
}
|
|
53
480
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
481
|
+
async listThreadsByResourceId(args) {
|
|
482
|
+
try {
|
|
483
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
484
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
485
|
+
if (page < 0) {
|
|
486
|
+
throw new error.MastraError(
|
|
487
|
+
{
|
|
488
|
+
id: "STORAGE_LANCE_LIST_THREADS_BY_RESOURCE_ID_INVALID_PAGE",
|
|
489
|
+
domain: error.ErrorDomain.STORAGE,
|
|
490
|
+
category: error.ErrorCategory.USER,
|
|
491
|
+
details: { page }
|
|
492
|
+
},
|
|
493
|
+
new Error("page must be >= 0")
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
497
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
498
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
499
|
+
const total = await table.countRows(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
500
|
+
const query = table.query().where(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
501
|
+
const records = await query.toArray();
|
|
502
|
+
records.sort((a, b) => {
|
|
503
|
+
const aValue = ["createdAt", "updatedAt"].includes(field) ? new Date(a[field]).getTime() : a[field];
|
|
504
|
+
const bValue = ["createdAt", "updatedAt"].includes(field) ? new Date(b[field]).getTime() : b[field];
|
|
505
|
+
if (aValue == null && bValue == null) return 0;
|
|
506
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
507
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
508
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
509
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
510
|
+
}
|
|
511
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
512
|
+
});
|
|
513
|
+
const paginatedRecords = records.slice(offset, offset + perPage);
|
|
514
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
515
|
+
const threads = paginatedRecords.map(
|
|
516
|
+
(record) => processResultWithTypeConversion(record, schema)
|
|
517
|
+
);
|
|
518
|
+
return {
|
|
519
|
+
threads,
|
|
520
|
+
total,
|
|
521
|
+
page,
|
|
522
|
+
perPage: perPageForResponse,
|
|
523
|
+
hasMore: offset + perPage < total
|
|
524
|
+
};
|
|
525
|
+
} catch (error$1) {
|
|
526
|
+
throw new error.MastraError(
|
|
527
|
+
{
|
|
528
|
+
id: "LANCE_STORE_LIST_THREADS_BY_RESOURCE_ID_FAILED",
|
|
529
|
+
domain: error.ErrorDomain.STORAGE,
|
|
530
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
531
|
+
},
|
|
532
|
+
error$1
|
|
533
|
+
);
|
|
60
534
|
}
|
|
61
|
-
return primaryId;
|
|
62
535
|
}
|
|
63
536
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
537
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
538
|
+
* @param records - The sorted array of records to process
|
|
539
|
+
* @param include - The array of include specifications with context parameters
|
|
540
|
+
* @returns The processed array with context messages included
|
|
541
|
+
*/
|
|
542
|
+
processMessagesWithContext(records, include) {
|
|
543
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
544
|
+
if (messagesWithContext.length === 0) {
|
|
545
|
+
return records;
|
|
546
|
+
}
|
|
547
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
548
|
+
records.forEach((message, index) => {
|
|
549
|
+
messageIndexMap.set(message.id, index);
|
|
550
|
+
});
|
|
551
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
552
|
+
for (const item of messagesWithContext) {
|
|
553
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
554
|
+
if (messageIndex !== void 0) {
|
|
555
|
+
if (item.withPreviousMessages) {
|
|
556
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
557
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
558
|
+
additionalIndices.add(i);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (item.withNextMessages) {
|
|
562
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
563
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
564
|
+
additionalIndices.add(i);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (additionalIndices.size === 0) {
|
|
570
|
+
return records;
|
|
571
|
+
}
|
|
572
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
573
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
574
|
+
records.forEach((record, index) => {
|
|
575
|
+
if (originalMatchIds.has(record.id)) {
|
|
576
|
+
allIndices.add(index);
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
additionalIndices.forEach((index) => {
|
|
580
|
+
allIndices.add(index);
|
|
581
|
+
});
|
|
582
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Parse message data from LanceDB record format to MastraDBMessage format
|
|
66
586
|
*/
|
|
67
|
-
|
|
68
|
-
|
|
587
|
+
parseMessageData(data) {
|
|
588
|
+
const { thread_id, ...rest } = data;
|
|
589
|
+
return {
|
|
590
|
+
...rest,
|
|
591
|
+
threadId: thread_id,
|
|
592
|
+
content: typeof data.content === "string" ? (() => {
|
|
593
|
+
try {
|
|
594
|
+
return JSON.parse(data.content);
|
|
595
|
+
} catch {
|
|
596
|
+
return data.content;
|
|
597
|
+
}
|
|
598
|
+
})() : data.content,
|
|
599
|
+
createdAt: new Date(data.createdAt),
|
|
600
|
+
updatedAt: new Date(data.updatedAt)
|
|
601
|
+
};
|
|
69
602
|
}
|
|
70
|
-
async
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
603
|
+
async updateMessages(args) {
|
|
604
|
+
const { messages } = args;
|
|
605
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
606
|
+
if (!messages.length) {
|
|
607
|
+
return [];
|
|
608
|
+
}
|
|
609
|
+
const updatedMessages = [];
|
|
610
|
+
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
74
611
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
612
|
+
for (const updateData of messages) {
|
|
613
|
+
const { id, ...updates } = updateData;
|
|
614
|
+
const existingMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
615
|
+
if (!existingMessage) {
|
|
616
|
+
this.logger.warn("Message not found for update", { id });
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
const existingMsg = this.parseMessageData(existingMessage);
|
|
620
|
+
const originalThreadId = existingMsg.threadId;
|
|
621
|
+
affectedThreadIds.add(originalThreadId);
|
|
622
|
+
const updatePayload = {};
|
|
623
|
+
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
624
|
+
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
625
|
+
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
626
|
+
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
627
|
+
updatePayload.thread_id = updates.threadId;
|
|
628
|
+
affectedThreadIds.add(updates.threadId);
|
|
629
|
+
}
|
|
630
|
+
if (updates.content) {
|
|
631
|
+
const existingContent = existingMsg.content;
|
|
632
|
+
let newContent = { ...existingContent };
|
|
633
|
+
if (updates.content.metadata !== void 0) {
|
|
634
|
+
newContent.metadata = {
|
|
635
|
+
...existingContent.metadata || {},
|
|
636
|
+
...updates.content.metadata || {}
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
if (updates.content.content !== void 0) {
|
|
640
|
+
newContent.content = updates.content.content;
|
|
641
|
+
}
|
|
642
|
+
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
643
|
+
newContent.parts = updates.content.parts;
|
|
644
|
+
}
|
|
645
|
+
updatePayload.content = JSON.stringify(newContent);
|
|
646
|
+
}
|
|
647
|
+
await this.operations.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
648
|
+
const updatedMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
649
|
+
if (updatedMessage) {
|
|
650
|
+
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
651
|
+
}
|
|
77
652
|
}
|
|
78
|
-
|
|
79
|
-
|
|
653
|
+
for (const threadId of affectedThreadIds) {
|
|
654
|
+
await this.operations.insert({
|
|
655
|
+
tableName: storage.TABLE_THREADS,
|
|
656
|
+
record: { id: threadId, updatedAt: Date.now() }
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
return updatedMessages;
|
|
660
|
+
} catch (error$1) {
|
|
661
|
+
throw new error.MastraError(
|
|
662
|
+
{
|
|
663
|
+
id: "LANCE_STORE_UPDATE_MESSAGES_FAILED",
|
|
664
|
+
domain: error.ErrorDomain.STORAGE,
|
|
665
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
666
|
+
details: { count: messages.length }
|
|
667
|
+
},
|
|
668
|
+
error$1
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
async getResourceById({ resourceId }) {
|
|
673
|
+
try {
|
|
674
|
+
const resource = await this.operations.load({ tableName: storage.TABLE_RESOURCES, keys: { id: resourceId } });
|
|
675
|
+
if (!resource) {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
let createdAt;
|
|
679
|
+
let updatedAt;
|
|
680
|
+
try {
|
|
681
|
+
if (resource.createdAt instanceof Date) {
|
|
682
|
+
createdAt = resource.createdAt;
|
|
683
|
+
} else if (typeof resource.createdAt === "string") {
|
|
684
|
+
createdAt = new Date(resource.createdAt);
|
|
685
|
+
} else if (typeof resource.createdAt === "number") {
|
|
686
|
+
createdAt = new Date(resource.createdAt);
|
|
687
|
+
} else {
|
|
688
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
689
|
+
}
|
|
690
|
+
if (isNaN(createdAt.getTime())) {
|
|
691
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
692
|
+
}
|
|
693
|
+
} catch {
|
|
694
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
80
695
|
}
|
|
81
|
-
|
|
82
|
-
|
|
696
|
+
try {
|
|
697
|
+
if (resource.updatedAt instanceof Date) {
|
|
698
|
+
updatedAt = resource.updatedAt;
|
|
699
|
+
} else if (typeof resource.updatedAt === "string") {
|
|
700
|
+
updatedAt = new Date(resource.updatedAt);
|
|
701
|
+
} else if (typeof resource.updatedAt === "number") {
|
|
702
|
+
updatedAt = new Date(resource.updatedAt);
|
|
703
|
+
} else {
|
|
704
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
705
|
+
}
|
|
706
|
+
if (isNaN(updatedAt.getTime())) {
|
|
707
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
708
|
+
}
|
|
709
|
+
} catch {
|
|
710
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
711
|
+
}
|
|
712
|
+
let workingMemory = resource.workingMemory;
|
|
713
|
+
if (workingMemory === null || workingMemory === void 0) {
|
|
714
|
+
workingMemory = void 0;
|
|
715
|
+
} else if (workingMemory === "") {
|
|
716
|
+
workingMemory = "";
|
|
717
|
+
} else if (typeof workingMemory === "object") {
|
|
718
|
+
workingMemory = JSON.stringify(workingMemory);
|
|
719
|
+
}
|
|
720
|
+
let metadata = resource.metadata;
|
|
721
|
+
if (metadata === "" || metadata === null || metadata === void 0) {
|
|
722
|
+
metadata = void 0;
|
|
723
|
+
} else if (typeof metadata === "string") {
|
|
724
|
+
try {
|
|
725
|
+
metadata = JSON.parse(metadata);
|
|
726
|
+
} catch {
|
|
727
|
+
metadata = metadata;
|
|
728
|
+
}
|
|
83
729
|
}
|
|
730
|
+
return {
|
|
731
|
+
...resource,
|
|
732
|
+
createdAt,
|
|
733
|
+
updatedAt,
|
|
734
|
+
workingMemory,
|
|
735
|
+
metadata
|
|
736
|
+
};
|
|
84
737
|
} catch (error$1) {
|
|
85
738
|
throw new error.MastraError(
|
|
86
739
|
{
|
|
87
|
-
id: "
|
|
740
|
+
id: "LANCE_STORE_GET_RESOURCE_BY_ID_FAILED",
|
|
88
741
|
domain: error.ErrorDomain.STORAGE,
|
|
89
|
-
category: error.ErrorCategory.
|
|
90
|
-
details: { tableName }
|
|
742
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
91
743
|
},
|
|
92
744
|
error$1
|
|
93
745
|
);
|
|
94
746
|
}
|
|
747
|
+
}
|
|
748
|
+
async saveResource({ resource }) {
|
|
95
749
|
try {
|
|
96
|
-
const
|
|
97
|
-
|
|
750
|
+
const record = {
|
|
751
|
+
...resource,
|
|
752
|
+
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
753
|
+
createdAt: resource.createdAt.getTime(),
|
|
754
|
+
// Store as timestamp (milliseconds)
|
|
755
|
+
updatedAt: resource.updatedAt.getTime()
|
|
756
|
+
// Store as timestamp (milliseconds)
|
|
757
|
+
};
|
|
758
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
759
|
+
await table.add([record], { mode: "append" });
|
|
760
|
+
return resource;
|
|
98
761
|
} catch (error$1) {
|
|
99
762
|
throw new error.MastraError(
|
|
100
763
|
{
|
|
101
|
-
id: "
|
|
764
|
+
id: "LANCE_STORE_SAVE_RESOURCE_FAILED",
|
|
102
765
|
domain: error.ErrorDomain.STORAGE,
|
|
103
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
104
|
-
details: { tableName }
|
|
766
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
105
767
|
},
|
|
106
768
|
error$1
|
|
107
769
|
);
|
|
108
770
|
}
|
|
109
771
|
}
|
|
772
|
+
async updateResource({
|
|
773
|
+
resourceId,
|
|
774
|
+
workingMemory,
|
|
775
|
+
metadata
|
|
776
|
+
}) {
|
|
777
|
+
const maxRetries = 3;
|
|
778
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
779
|
+
try {
|
|
780
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
781
|
+
if (!existingResource) {
|
|
782
|
+
const newResource = {
|
|
783
|
+
id: resourceId,
|
|
784
|
+
workingMemory,
|
|
785
|
+
metadata: metadata || {},
|
|
786
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
787
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
788
|
+
};
|
|
789
|
+
return this.saveResource({ resource: newResource });
|
|
790
|
+
}
|
|
791
|
+
const updatedResource = {
|
|
792
|
+
...existingResource,
|
|
793
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
794
|
+
metadata: {
|
|
795
|
+
...existingResource.metadata,
|
|
796
|
+
...metadata
|
|
797
|
+
},
|
|
798
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
799
|
+
};
|
|
800
|
+
const record = {
|
|
801
|
+
id: resourceId,
|
|
802
|
+
workingMemory: updatedResource.workingMemory || "",
|
|
803
|
+
metadata: updatedResource.metadata ? JSON.stringify(updatedResource.metadata) : "",
|
|
804
|
+
updatedAt: updatedResource.updatedAt.getTime()
|
|
805
|
+
// Store as timestamp (milliseconds)
|
|
806
|
+
};
|
|
807
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
808
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
809
|
+
return updatedResource;
|
|
810
|
+
} catch (error$1) {
|
|
811
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
812
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
813
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
throw new error.MastraError(
|
|
817
|
+
{
|
|
818
|
+
id: "LANCE_STORE_UPDATE_RESOURCE_FAILED",
|
|
819
|
+
domain: error.ErrorDomain.STORAGE,
|
|
820
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
821
|
+
},
|
|
822
|
+
error$1
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
throw new Error("Unexpected end of retry loop");
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
var StoreOperationsLance = class extends storage.StoreOperations {
|
|
830
|
+
client;
|
|
831
|
+
constructor({ client }) {
|
|
832
|
+
super();
|
|
833
|
+
this.client = client;
|
|
834
|
+
}
|
|
835
|
+
getDefaultValue(type) {
|
|
836
|
+
switch (type) {
|
|
837
|
+
case "text":
|
|
838
|
+
return "''";
|
|
839
|
+
case "timestamp":
|
|
840
|
+
return "CURRENT_TIMESTAMP";
|
|
841
|
+
case "integer":
|
|
842
|
+
case "bigint":
|
|
843
|
+
return "0";
|
|
844
|
+
case "jsonb":
|
|
845
|
+
return "'{}'";
|
|
846
|
+
case "uuid":
|
|
847
|
+
return "''";
|
|
848
|
+
default:
|
|
849
|
+
return super.getDefaultValue(type);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
async hasColumn(tableName, columnName) {
|
|
853
|
+
const table = await this.client.openTable(tableName);
|
|
854
|
+
const schema = await table.schema();
|
|
855
|
+
return schema.fields.some((field) => field.name === columnName);
|
|
856
|
+
}
|
|
110
857
|
translateSchema(schema) {
|
|
111
858
|
const fields = Object.entries(schema).map(([name, column]) => {
|
|
112
859
|
let arrowType;
|
|
@@ -142,40 +889,42 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
142
889
|
});
|
|
143
890
|
return new apacheArrow.Schema(fields);
|
|
144
891
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
async dropTable(tableName) {
|
|
892
|
+
async createTable({
|
|
893
|
+
tableName,
|
|
894
|
+
schema
|
|
895
|
+
}) {
|
|
150
896
|
try {
|
|
151
|
-
if (!this.
|
|
897
|
+
if (!this.client) {
|
|
152
898
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
153
899
|
}
|
|
154
900
|
if (!tableName) {
|
|
155
|
-
throw new Error("tableName is required for
|
|
901
|
+
throw new Error("tableName is required for createTable.");
|
|
156
902
|
}
|
|
157
|
-
|
|
903
|
+
if (!schema) {
|
|
904
|
+
throw new Error("schema is required for createTable.");
|
|
905
|
+
}
|
|
906
|
+
} catch (error$1) {
|
|
158
907
|
throw new error.MastraError(
|
|
159
908
|
{
|
|
160
|
-
id: "
|
|
909
|
+
id: "STORAGE_LANCE_STORAGE_CREATE_TABLE_INVALID_ARGS",
|
|
161
910
|
domain: error.ErrorDomain.STORAGE,
|
|
162
911
|
category: error.ErrorCategory.USER,
|
|
163
|
-
text: validationError.message,
|
|
164
912
|
details: { tableName }
|
|
165
913
|
},
|
|
166
|
-
|
|
914
|
+
error$1
|
|
167
915
|
);
|
|
168
916
|
}
|
|
169
917
|
try {
|
|
170
|
-
|
|
918
|
+
const arrowSchema = this.translateSchema(schema);
|
|
919
|
+
await this.client.createEmptyTable(tableName, arrowSchema);
|
|
171
920
|
} catch (error$1) {
|
|
172
|
-
if (error$1.
|
|
173
|
-
this.logger.debug(`Table '${tableName}'
|
|
921
|
+
if (error$1.message?.includes("already exists")) {
|
|
922
|
+
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
174
923
|
return;
|
|
175
924
|
}
|
|
176
925
|
throw new error.MastraError(
|
|
177
926
|
{
|
|
178
|
-
id: "
|
|
927
|
+
id: "STORAGE_LANCE_STORAGE_CREATE_TABLE_FAILED",
|
|
179
928
|
domain: error.ErrorDomain.STORAGE,
|
|
180
929
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
181
930
|
details: { tableName }
|
|
@@ -184,23 +933,18 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
184
933
|
);
|
|
185
934
|
}
|
|
186
935
|
}
|
|
187
|
-
|
|
188
|
-
* Get table schema
|
|
189
|
-
* @param tableName Name of the table
|
|
190
|
-
* @returns Table schema
|
|
191
|
-
*/
|
|
192
|
-
async getTableSchema(tableName) {
|
|
936
|
+
async dropTable({ tableName }) {
|
|
193
937
|
try {
|
|
194
|
-
if (!this.
|
|
938
|
+
if (!this.client) {
|
|
195
939
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
196
940
|
}
|
|
197
941
|
if (!tableName) {
|
|
198
|
-
throw new Error("tableName is required for
|
|
942
|
+
throw new Error("tableName is required for dropTable.");
|
|
199
943
|
}
|
|
200
944
|
} catch (validationError) {
|
|
201
945
|
throw new error.MastraError(
|
|
202
946
|
{
|
|
203
|
-
id: "
|
|
947
|
+
id: "STORAGE_LANCE_STORAGE_DROP_TABLE_INVALID_ARGS",
|
|
204
948
|
domain: error.ErrorDomain.STORAGE,
|
|
205
949
|
category: error.ErrorCategory.USER,
|
|
206
950
|
text: validationError.message,
|
|
@@ -210,20 +954,15 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
210
954
|
);
|
|
211
955
|
}
|
|
212
956
|
try {
|
|
213
|
-
|
|
214
|
-
const rawSchema = await table.schema();
|
|
215
|
-
const fields = rawSchema.fields;
|
|
216
|
-
return {
|
|
217
|
-
fields,
|
|
218
|
-
metadata: /* @__PURE__ */ new Map(),
|
|
219
|
-
get names() {
|
|
220
|
-
return fields.map((field) => field.name);
|
|
221
|
-
}
|
|
222
|
-
};
|
|
957
|
+
await this.client.dropTable(tableName);
|
|
223
958
|
} catch (error$1) {
|
|
959
|
+
if (error$1.toString().includes("was not found") || error$1.message?.includes("Table not found")) {
|
|
960
|
+
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
224
963
|
throw new error.MastraError(
|
|
225
964
|
{
|
|
226
|
-
id: "
|
|
965
|
+
id: "STORAGE_LANCE_STORAGE_DROP_TABLE_FAILED",
|
|
227
966
|
domain: error.ErrorDomain.STORAGE,
|
|
228
967
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
229
968
|
details: { tableName }
|
|
@@ -232,36 +971,13 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
232
971
|
);
|
|
233
972
|
}
|
|
234
973
|
}
|
|
235
|
-
getDefaultValue(type) {
|
|
236
|
-
switch (type) {
|
|
237
|
-
case "text":
|
|
238
|
-
return "''";
|
|
239
|
-
case "timestamp":
|
|
240
|
-
return "CURRENT_TIMESTAMP";
|
|
241
|
-
case "integer":
|
|
242
|
-
case "bigint":
|
|
243
|
-
return "0";
|
|
244
|
-
case "jsonb":
|
|
245
|
-
return "'{}'";
|
|
246
|
-
case "uuid":
|
|
247
|
-
return "''";
|
|
248
|
-
default:
|
|
249
|
-
return super.getDefaultValue(type);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Alters table schema to add columns if they don't exist
|
|
254
|
-
* @param tableName Name of the table
|
|
255
|
-
* @param schema Schema of the table
|
|
256
|
-
* @param ifNotExists Array of column names to add if they don't exist
|
|
257
|
-
*/
|
|
258
974
|
async alterTable({
|
|
259
975
|
tableName,
|
|
260
976
|
schema,
|
|
261
977
|
ifNotExists
|
|
262
978
|
}) {
|
|
263
979
|
try {
|
|
264
|
-
if (!this.
|
|
980
|
+
if (!this.client) {
|
|
265
981
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
266
982
|
}
|
|
267
983
|
if (!tableName) {
|
|
@@ -287,7 +1003,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
287
1003
|
);
|
|
288
1004
|
}
|
|
289
1005
|
try {
|
|
290
|
-
const table = await this.
|
|
1006
|
+
const table = await this.client.openTable(tableName);
|
|
291
1007
|
const currentSchema = await table.schema();
|
|
292
1008
|
const existingFields = new Set(currentSchema.fields.map((f) => f.name));
|
|
293
1009
|
const typeMap = {
|
|
@@ -323,7 +1039,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
323
1039
|
}
|
|
324
1040
|
async clearTable({ tableName }) {
|
|
325
1041
|
try {
|
|
326
|
-
if (!this.
|
|
1042
|
+
if (!this.client) {
|
|
327
1043
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
328
1044
|
}
|
|
329
1045
|
if (!tableName) {
|
|
@@ -342,7 +1058,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
342
1058
|
);
|
|
343
1059
|
}
|
|
344
1060
|
try {
|
|
345
|
-
const table = await this.
|
|
1061
|
+
const table = await this.client.openTable(tableName);
|
|
346
1062
|
await table.delete("1=1");
|
|
347
1063
|
} catch (error$1) {
|
|
348
1064
|
throw new error.MastraError(
|
|
@@ -356,14 +1072,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
356
1072
|
);
|
|
357
1073
|
}
|
|
358
1074
|
}
|
|
359
|
-
/**
|
|
360
|
-
* Insert a single record into a table. This function overwrites the existing record if it exists. Use this function for inserting records into tables with custom schemas.
|
|
361
|
-
* @param tableName The name of the table to insert into.
|
|
362
|
-
* @param record The record to insert.
|
|
363
|
-
*/
|
|
364
1075
|
async insert({ tableName, record }) {
|
|
365
1076
|
try {
|
|
366
|
-
if (!this.
|
|
1077
|
+
if (!this.client) {
|
|
367
1078
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
368
1079
|
}
|
|
369
1080
|
if (!tableName) {
|
|
@@ -385,8 +1096,8 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
385
1096
|
);
|
|
386
1097
|
}
|
|
387
1098
|
try {
|
|
388
|
-
const table = await this.
|
|
389
|
-
const primaryId =
|
|
1099
|
+
const table = await this.client.openTable(tableName);
|
|
1100
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
390
1101
|
const processedRecord = { ...record };
|
|
391
1102
|
for (const key in processedRecord) {
|
|
392
1103
|
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
@@ -394,6 +1105,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
394
1105
|
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
395
1106
|
}
|
|
396
1107
|
}
|
|
1108
|
+
console.info(await table.schema());
|
|
397
1109
|
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([processedRecord]);
|
|
398
1110
|
} catch (error$1) {
|
|
399
1111
|
throw new error.MastraError(
|
|
@@ -407,14 +1119,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
407
1119
|
);
|
|
408
1120
|
}
|
|
409
1121
|
}
|
|
410
|
-
/**
|
|
411
|
-
* Insert multiple records into a table. This function overwrites the existing records if they exist. Use this function for inserting records into tables with custom schemas.
|
|
412
|
-
* @param tableName The name of the table to insert into.
|
|
413
|
-
* @param records The records to insert.
|
|
414
|
-
*/
|
|
415
1122
|
async batchInsert({ tableName, records }) {
|
|
416
1123
|
try {
|
|
417
|
-
if (!this.
|
|
1124
|
+
if (!this.client) {
|
|
418
1125
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
419
1126
|
}
|
|
420
1127
|
if (!tableName) {
|
|
@@ -436,8 +1143,8 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
436
1143
|
);
|
|
437
1144
|
}
|
|
438
1145
|
try {
|
|
439
|
-
const table = await this.
|
|
440
|
-
const primaryId =
|
|
1146
|
+
const table = await this.client.openTable(tableName);
|
|
1147
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
441
1148
|
const processedRecords = records.map((record) => {
|
|
442
1149
|
const processedRecord = { ...record };
|
|
443
1150
|
for (const key in processedRecord) {
|
|
@@ -461,16 +1168,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
461
1168
|
);
|
|
462
1169
|
}
|
|
463
1170
|
}
|
|
464
|
-
/**
|
|
465
|
-
* Load a record from the database by its key(s)
|
|
466
|
-
* @param tableName The name of the table to query
|
|
467
|
-
* @param keys Record of key-value pairs to use for lookup
|
|
468
|
-
* @throws Error if invalid types are provided for keys
|
|
469
|
-
* @returns The loaded record with proper type conversions, or null if not found
|
|
470
|
-
*/
|
|
471
1171
|
async load({ tableName, keys }) {
|
|
472
1172
|
try {
|
|
473
|
-
if (!this.
|
|
1173
|
+
if (!this.client) {
|
|
474
1174
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
475
1175
|
}
|
|
476
1176
|
if (!tableName) {
|
|
@@ -492,11 +1192,11 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
492
1192
|
);
|
|
493
1193
|
}
|
|
494
1194
|
try {
|
|
495
|
-
const table = await this.
|
|
496
|
-
const tableSchema = await
|
|
1195
|
+
const table = await this.client.openTable(tableName);
|
|
1196
|
+
const tableSchema = await getTableSchema({ tableName, client: this.client });
|
|
497
1197
|
const query = table.query();
|
|
498
1198
|
if (Object.keys(keys).length > 0) {
|
|
499
|
-
|
|
1199
|
+
validateKeyTypes(keys, tableSchema);
|
|
500
1200
|
const filterConditions = Object.entries(keys).map(([key, value]) => {
|
|
501
1201
|
const isCamelCase = /^[a-z][a-zA-Z]*$/.test(key) && /[A-Z]/.test(key);
|
|
502
1202
|
const quotedKey = isCamelCase ? `\`${key}\`` : key;
|
|
@@ -516,7 +1216,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
516
1216
|
this.logger.debug("No record found");
|
|
517
1217
|
return null;
|
|
518
1218
|
}
|
|
519
|
-
return
|
|
1219
|
+
return processResultWithTypeConversion(result[0], tableSchema);
|
|
520
1220
|
} catch (error$1) {
|
|
521
1221
|
if (error$1 instanceof error.MastraError) throw error$1;
|
|
522
1222
|
throw new error.MastraError(
|
|
@@ -530,634 +1230,729 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
530
1230
|
);
|
|
531
1231
|
}
|
|
532
1232
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
validateKeyTypes(keys, tableSchema) {
|
|
540
|
-
const fieldTypes = new Map(
|
|
541
|
-
tableSchema.fields.map((field) => [field.name, field.type?.toString().toLowerCase()])
|
|
542
|
-
);
|
|
543
|
-
for (const [key, value] of Object.entries(keys)) {
|
|
544
|
-
const fieldType = fieldTypes.get(key);
|
|
545
|
-
if (!fieldType) {
|
|
546
|
-
throw new Error(`Field '${key}' does not exist in table schema`);
|
|
547
|
-
}
|
|
548
|
-
if (value !== null) {
|
|
549
|
-
if ((fieldType.includes("int") || fieldType.includes("bigint")) && typeof value !== "number") {
|
|
550
|
-
throw new Error(`Expected numeric value for field '${key}', got ${typeof value}`);
|
|
551
|
-
}
|
|
552
|
-
if (fieldType.includes("utf8") && typeof value !== "string") {
|
|
553
|
-
throw new Error(`Expected string value for field '${key}', got ${typeof value}`);
|
|
554
|
-
}
|
|
555
|
-
if (fieldType.includes("timestamp") && !(value instanceof Date) && typeof value !== "string") {
|
|
556
|
-
throw new Error(`Expected Date or string value for field '${key}', got ${typeof value}`);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Process a database result with appropriate type conversions based on the table schema
|
|
563
|
-
* @param rawResult The raw result object from the database
|
|
564
|
-
* @param tableSchema The schema of the table containing type information
|
|
565
|
-
* @returns Processed result with correct data types
|
|
566
|
-
*/
|
|
567
|
-
processResultWithTypeConversion(rawResult, tableSchema) {
|
|
568
|
-
const fieldTypeMap = /* @__PURE__ */ new Map();
|
|
569
|
-
tableSchema.fields.forEach((field) => {
|
|
570
|
-
const fieldName = field.name;
|
|
571
|
-
const fieldTypeStr = field.type.toString().toLowerCase();
|
|
572
|
-
fieldTypeMap.set(fieldName, fieldTypeStr);
|
|
573
|
-
});
|
|
574
|
-
if (Array.isArray(rawResult)) {
|
|
575
|
-
return rawResult.map((item) => this.processResultWithTypeConversion(item, tableSchema));
|
|
576
|
-
}
|
|
577
|
-
const processedResult = { ...rawResult };
|
|
578
|
-
for (const key in processedResult) {
|
|
579
|
-
const fieldTypeStr = fieldTypeMap.get(key);
|
|
580
|
-
if (!fieldTypeStr) continue;
|
|
581
|
-
if (typeof processedResult[key] === "string") {
|
|
582
|
-
if (fieldTypeStr.includes("int32") || fieldTypeStr.includes("float32")) {
|
|
583
|
-
if (!isNaN(Number(processedResult[key]))) {
|
|
584
|
-
processedResult[key] = Number(processedResult[key]);
|
|
585
|
-
}
|
|
586
|
-
} else if (fieldTypeStr.includes("int64")) {
|
|
587
|
-
processedResult[key] = Number(processedResult[key]);
|
|
588
|
-
} else if (fieldTypeStr.includes("utf8")) {
|
|
589
|
-
try {
|
|
590
|
-
processedResult[key] = JSON.parse(processedResult[key]);
|
|
591
|
-
} catch (e) {
|
|
592
|
-
this.logger.debug(`Failed to parse JSON for key ${key}: ${e}`);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
} else if (typeof processedResult[key] === "bigint") {
|
|
596
|
-
processedResult[key] = Number(processedResult[key]);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
return processedResult;
|
|
600
|
-
}
|
|
601
|
-
getThreadById({ threadId }) {
|
|
602
|
-
try {
|
|
603
|
-
return this.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
604
|
-
} catch (error$1) {
|
|
605
|
-
throw new error.MastraError(
|
|
606
|
-
{
|
|
607
|
-
id: "LANCE_STORE_GET_THREAD_BY_ID_FAILED",
|
|
608
|
-
domain: error.ErrorDomain.STORAGE,
|
|
609
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
610
|
-
},
|
|
611
|
-
error$1
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
616
|
-
try {
|
|
617
|
-
const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
|
|
618
|
-
const query = table.query().where(`\`resourceId\` = '${resourceId}'`);
|
|
619
|
-
const records = await query.toArray();
|
|
620
|
-
return this.processResultWithTypeConversion(
|
|
621
|
-
records,
|
|
622
|
-
await this.getTableSchema(storage.TABLE_THREADS)
|
|
623
|
-
);
|
|
624
|
-
} catch (error$1) {
|
|
625
|
-
throw new error.MastraError(
|
|
626
|
-
{
|
|
627
|
-
id: "LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
628
|
-
domain: error.ErrorDomain.STORAGE,
|
|
629
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
630
|
-
},
|
|
631
|
-
error$1
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
637
|
-
* @param thread - The thread to save
|
|
638
|
-
* @returns The saved thread
|
|
639
|
-
*/
|
|
640
|
-
async saveThread({ thread }) {
|
|
641
|
-
try {
|
|
642
|
-
const record = { ...thread, metadata: JSON.stringify(thread.metadata) };
|
|
643
|
-
const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
|
|
644
|
-
await table.add([record], { mode: "append" });
|
|
645
|
-
return thread;
|
|
646
|
-
} catch (error$1) {
|
|
647
|
-
throw new error.MastraError(
|
|
648
|
-
{
|
|
649
|
-
id: "LANCE_STORE_SAVE_THREAD_FAILED",
|
|
650
|
-
domain: error.ErrorDomain.STORAGE,
|
|
651
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
652
|
-
},
|
|
653
|
-
error$1
|
|
654
|
-
);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
async updateThread({
|
|
658
|
-
id,
|
|
659
|
-
title,
|
|
660
|
-
metadata
|
|
661
|
-
}) {
|
|
662
|
-
try {
|
|
663
|
-
const record = { id, title, metadata: JSON.stringify(metadata) };
|
|
664
|
-
const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
|
|
665
|
-
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
666
|
-
const query = table.query().where(`id = '${id}'`);
|
|
667
|
-
const records = await query.toArray();
|
|
668
|
-
return this.processResultWithTypeConversion(
|
|
669
|
-
records[0],
|
|
670
|
-
await this.getTableSchema(storage.TABLE_THREADS)
|
|
671
|
-
);
|
|
672
|
-
} catch (error$1) {
|
|
673
|
-
throw new error.MastraError(
|
|
674
|
-
{
|
|
675
|
-
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
676
|
-
domain: error.ErrorDomain.STORAGE,
|
|
677
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
678
|
-
},
|
|
679
|
-
error$1
|
|
680
|
-
);
|
|
681
|
-
}
|
|
1233
|
+
};
|
|
1234
|
+
var StoreScoresLance = class extends storage.ScoresStorage {
|
|
1235
|
+
client;
|
|
1236
|
+
constructor({ client }) {
|
|
1237
|
+
super();
|
|
1238
|
+
this.client = client;
|
|
682
1239
|
}
|
|
683
|
-
async
|
|
1240
|
+
async saveScore(score) {
|
|
1241
|
+
let validatedScore;
|
|
684
1242
|
try {
|
|
685
|
-
|
|
686
|
-
await table.delete(`id = '${threadId}'`);
|
|
1243
|
+
validatedScore = evals.saveScorePayloadSchema.parse(score);
|
|
687
1244
|
} catch (error$1) {
|
|
688
1245
|
throw new error.MastraError(
|
|
689
1246
|
{
|
|
690
|
-
id: "
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
return records;
|
|
708
|
-
}
|
|
709
|
-
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
710
|
-
records.forEach((message, index) => {
|
|
711
|
-
messageIndexMap.set(message.id, index);
|
|
712
|
-
});
|
|
713
|
-
const additionalIndices = /* @__PURE__ */ new Set();
|
|
714
|
-
for (const item of messagesWithContext) {
|
|
715
|
-
const messageIndex = messageIndexMap.get(item.id);
|
|
716
|
-
if (messageIndex !== void 0) {
|
|
717
|
-
if (item.withPreviousMessages) {
|
|
718
|
-
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
719
|
-
for (let i = startIdx; i < messageIndex; i++) {
|
|
720
|
-
additionalIndices.add(i);
|
|
721
|
-
}
|
|
1247
|
+
id: "LANCE_STORAGE_SAVE_SCORE_FAILED",
|
|
1248
|
+
text: "Failed to save score in LanceStorage",
|
|
1249
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1250
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1251
|
+
},
|
|
1252
|
+
error$1
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
try {
|
|
1256
|
+
const id = crypto.randomUUID();
|
|
1257
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1258
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1259
|
+
const allowedFields = new Set(schema.fields.map((f) => f.name));
|
|
1260
|
+
const filteredScore = {};
|
|
1261
|
+
Object.keys(validatedScore).forEach((key) => {
|
|
1262
|
+
if (allowedFields.has(key)) {
|
|
1263
|
+
filteredScore[key] = score[key];
|
|
722
1264
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}
|
|
1265
|
+
});
|
|
1266
|
+
for (const key in filteredScore) {
|
|
1267
|
+
if (filteredScore[key] !== null && typeof filteredScore[key] === "object" && !(filteredScore[key] instanceof Date)) {
|
|
1268
|
+
filteredScore[key] = JSON.stringify(filteredScore[key]);
|
|
728
1269
|
}
|
|
729
1270
|
}
|
|
1271
|
+
filteredScore.id = id;
|
|
1272
|
+
await table.add([filteredScore], { mode: "append" });
|
|
1273
|
+
return { score };
|
|
1274
|
+
} catch (error$1) {
|
|
1275
|
+
throw new error.MastraError(
|
|
1276
|
+
{
|
|
1277
|
+
id: "LANCE_STORAGE_SAVE_SCORE_FAILED",
|
|
1278
|
+
text: "Failed to save score in LanceStorage",
|
|
1279
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1280
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1281
|
+
details: { error: error$1?.message }
|
|
1282
|
+
},
|
|
1283
|
+
error$1
|
|
1284
|
+
);
|
|
730
1285
|
}
|
|
731
|
-
if (additionalIndices.size === 0) {
|
|
732
|
-
return records;
|
|
733
|
-
}
|
|
734
|
-
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
735
|
-
const allIndices = /* @__PURE__ */ new Set();
|
|
736
|
-
records.forEach((record, index) => {
|
|
737
|
-
if (originalMatchIds.has(record.id)) {
|
|
738
|
-
allIndices.add(index);
|
|
739
|
-
}
|
|
740
|
-
});
|
|
741
|
-
additionalIndices.forEach((index) => {
|
|
742
|
-
allIndices.add(index);
|
|
743
|
-
});
|
|
744
|
-
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
745
1286
|
}
|
|
746
|
-
async
|
|
747
|
-
threadId,
|
|
748
|
-
resourceId,
|
|
749
|
-
selectBy,
|
|
750
|
-
format,
|
|
751
|
-
threadConfig
|
|
752
|
-
}) {
|
|
1287
|
+
async getScoreById({ id }) {
|
|
753
1288
|
try {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
if (selectBy) {
|
|
761
|
-
if (selectBy.include && selectBy.include.length > 0) {
|
|
762
|
-
const includeIds = selectBy.include.map((item) => item.id);
|
|
763
|
-
const includeClause = includeIds.map((id) => `\`id\` = '${id}'`).join(" OR ");
|
|
764
|
-
query = query.where(`(\`threadId\` = '${threadId}' OR (${includeClause}))`);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
let records = await query.toArray();
|
|
768
|
-
records.sort((a, b) => {
|
|
769
|
-
const dateA = new Date(a.createdAt).getTime();
|
|
770
|
-
const dateB = new Date(b.createdAt).getTime();
|
|
771
|
-
return dateA - dateB;
|
|
772
|
-
});
|
|
773
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
774
|
-
records = this.processMessagesWithContext(records, selectBy.include);
|
|
775
|
-
}
|
|
776
|
-
if (limit !== Number.MAX_SAFE_INTEGER) {
|
|
777
|
-
records = records.slice(-limit);
|
|
778
|
-
}
|
|
779
|
-
const messages = this.processResultWithTypeConversion(records, await this.getTableSchema(storage.TABLE_MESSAGES));
|
|
780
|
-
const normalized = messages.map((msg) => ({
|
|
781
|
-
...msg,
|
|
782
|
-
content: typeof msg.content === "string" ? (() => {
|
|
783
|
-
try {
|
|
784
|
-
return JSON.parse(msg.content);
|
|
785
|
-
} catch {
|
|
786
|
-
return msg.content;
|
|
787
|
-
}
|
|
788
|
-
})() : msg.content
|
|
789
|
-
}));
|
|
790
|
-
const list = new agent.MessageList({ threadId, resourceId }).add(normalized, "memory");
|
|
791
|
-
if (format === "v2") return list.get.all.v2();
|
|
792
|
-
return list.get.all.v1();
|
|
1289
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1290
|
+
const query = table.query().where(`id = '${id}'`).limit(1);
|
|
1291
|
+
const records = await query.toArray();
|
|
1292
|
+
if (records.length === 0) return null;
|
|
1293
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1294
|
+
return processResultWithTypeConversion(records[0], schema);
|
|
793
1295
|
} catch (error$1) {
|
|
794
1296
|
throw new error.MastraError(
|
|
795
1297
|
{
|
|
796
|
-
id: "
|
|
1298
|
+
id: "LANCE_STORAGE_GET_SCORE_BY_ID_FAILED",
|
|
1299
|
+
text: "Failed to get score by id in LanceStorage",
|
|
797
1300
|
domain: error.ErrorDomain.STORAGE,
|
|
798
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1301
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1302
|
+
details: { error: error$1?.message }
|
|
799
1303
|
},
|
|
800
1304
|
error$1
|
|
801
1305
|
);
|
|
802
1306
|
}
|
|
803
1307
|
}
|
|
804
|
-
async
|
|
1308
|
+
async listScoresByScorerId({
|
|
1309
|
+
scorerId,
|
|
1310
|
+
pagination,
|
|
1311
|
+
entityId,
|
|
1312
|
+
entityType,
|
|
1313
|
+
source
|
|
1314
|
+
}) {
|
|
805
1315
|
try {
|
|
806
|
-
const {
|
|
807
|
-
|
|
808
|
-
|
|
1316
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1317
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1318
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1319
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1320
|
+
let query = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1321
|
+
if (source) {
|
|
1322
|
+
query = query.where(`\`source\` = '${source}'`);
|
|
809
1323
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
throw new Error("Thread ID is required");
|
|
1324
|
+
if (entityId) {
|
|
1325
|
+
query = query.where(`\`entityId\` = '${entityId}'`);
|
|
813
1326
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
})
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
if (
|
|
822
|
-
|
|
1327
|
+
if (entityType) {
|
|
1328
|
+
query = query.where(`\`entityType\` = '${entityType}'`);
|
|
1329
|
+
}
|
|
1330
|
+
let totalQuery = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1331
|
+
if (source) {
|
|
1332
|
+
totalQuery = totalQuery.where(`\`source\` = '${source}'`);
|
|
1333
|
+
}
|
|
1334
|
+
if (entityId) {
|
|
1335
|
+
totalQuery = totalQuery.where(`\`entityId\` = '${entityId}'`);
|
|
1336
|
+
}
|
|
1337
|
+
if (entityType) {
|
|
1338
|
+
totalQuery = totalQuery.where(`\`entityType\` = '${entityType}'`);
|
|
1339
|
+
}
|
|
1340
|
+
const allRecords = await totalQuery.toArray();
|
|
1341
|
+
const total = allRecords.length;
|
|
1342
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1343
|
+
if (perPageInput !== false) {
|
|
1344
|
+
query = query.limit(perPage);
|
|
1345
|
+
if (start > 0) query = query.offset(start);
|
|
1346
|
+
}
|
|
1347
|
+
const records = await query.toArray();
|
|
1348
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1349
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1350
|
+
return {
|
|
1351
|
+
pagination: {
|
|
1352
|
+
page,
|
|
1353
|
+
perPage: perPageForResponse,
|
|
1354
|
+
total,
|
|
1355
|
+
hasMore: end < total
|
|
1356
|
+
},
|
|
1357
|
+
scores
|
|
1358
|
+
};
|
|
823
1359
|
} catch (error$1) {
|
|
824
1360
|
throw new error.MastraError(
|
|
825
1361
|
{
|
|
826
|
-
id: "
|
|
1362
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_SCORER_ID_FAILED",
|
|
1363
|
+
text: "Failed to get scores by scorerId in LanceStorage",
|
|
827
1364
|
domain: error.ErrorDomain.STORAGE,
|
|
828
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1365
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1366
|
+
details: { error: error$1?.message }
|
|
829
1367
|
},
|
|
830
1368
|
error$1
|
|
831
1369
|
);
|
|
832
1370
|
}
|
|
833
1371
|
}
|
|
834
|
-
async
|
|
1372
|
+
async listScoresByRunId({
|
|
1373
|
+
runId,
|
|
1374
|
+
pagination
|
|
1375
|
+
}) {
|
|
835
1376
|
try {
|
|
836
|
-
const
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1377
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1378
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1379
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1380
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1381
|
+
const allRecords = await table.query().where(`\`runId\` = '${runId}'`).toArray();
|
|
1382
|
+
const total = allRecords.length;
|
|
1383
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1384
|
+
let query = table.query().where(`\`runId\` = '${runId}'`);
|
|
1385
|
+
if (perPageInput !== false) {
|
|
1386
|
+
query = query.limit(perPage);
|
|
1387
|
+
if (start > 0) query = query.offset(start);
|
|
1388
|
+
}
|
|
1389
|
+
const records = await query.toArray();
|
|
1390
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1391
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1392
|
+
return {
|
|
1393
|
+
pagination: {
|
|
1394
|
+
page,
|
|
1395
|
+
perPage: perPageForResponse,
|
|
1396
|
+
total,
|
|
1397
|
+
hasMore: end < total
|
|
1398
|
+
},
|
|
1399
|
+
scores
|
|
844
1400
|
};
|
|
845
|
-
await table.add([record], { mode: "append" });
|
|
846
|
-
return trace;
|
|
847
1401
|
} catch (error$1) {
|
|
848
1402
|
throw new error.MastraError(
|
|
849
1403
|
{
|
|
850
|
-
id: "
|
|
1404
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_RUN_ID_FAILED",
|
|
1405
|
+
text: "Failed to get scores by runId in LanceStorage",
|
|
851
1406
|
domain: error.ErrorDomain.STORAGE,
|
|
852
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1407
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1408
|
+
details: { error: error$1?.message }
|
|
853
1409
|
},
|
|
854
1410
|
error$1
|
|
855
1411
|
);
|
|
856
1412
|
}
|
|
857
1413
|
}
|
|
858
|
-
async
|
|
1414
|
+
async listScoresByEntityId({
|
|
1415
|
+
entityId,
|
|
1416
|
+
entityType,
|
|
1417
|
+
pagination
|
|
1418
|
+
}) {
|
|
859
1419
|
try {
|
|
860
|
-
const
|
|
861
|
-
const
|
|
1420
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1421
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1422
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1423
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1424
|
+
const allRecords = await table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).toArray();
|
|
1425
|
+
const total = allRecords.length;
|
|
1426
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1427
|
+
let query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`);
|
|
1428
|
+
if (perPageInput !== false) {
|
|
1429
|
+
query = query.limit(perPage);
|
|
1430
|
+
if (start > 0) query = query.offset(start);
|
|
1431
|
+
}
|
|
862
1432
|
const records = await query.toArray();
|
|
863
|
-
|
|
1433
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1434
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1435
|
+
return {
|
|
1436
|
+
pagination: {
|
|
1437
|
+
page,
|
|
1438
|
+
perPage: perPageForResponse,
|
|
1439
|
+
total,
|
|
1440
|
+
hasMore: end < total
|
|
1441
|
+
},
|
|
1442
|
+
scores
|
|
1443
|
+
};
|
|
864
1444
|
} catch (error$1) {
|
|
865
1445
|
throw new error.MastraError(
|
|
866
1446
|
{
|
|
867
|
-
id: "
|
|
1447
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_ENTITY_ID_FAILED",
|
|
1448
|
+
text: "Failed to get scores by entityId and entityType in LanceStorage",
|
|
868
1449
|
domain: error.ErrorDomain.STORAGE,
|
|
869
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1450
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1451
|
+
details: { error: error$1?.message }
|
|
870
1452
|
},
|
|
871
1453
|
error$1
|
|
872
1454
|
);
|
|
873
1455
|
}
|
|
874
1456
|
}
|
|
875
|
-
async
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
perPage = 10,
|
|
880
|
-
attributes
|
|
1457
|
+
async listScoresBySpan({
|
|
1458
|
+
traceId,
|
|
1459
|
+
spanId,
|
|
1460
|
+
pagination
|
|
881
1461
|
}) {
|
|
882
1462
|
try {
|
|
883
|
-
const
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
}
|
|
891
|
-
if (
|
|
892
|
-
query
|
|
893
|
-
|
|
894
|
-
const offset = (page - 1) * perPage;
|
|
895
|
-
query.limit(perPage);
|
|
896
|
-
if (offset > 0) {
|
|
897
|
-
query.offset(offset);
|
|
1463
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1464
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
1465
|
+
const { offset: start, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1466
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1467
|
+
const allRecords = await table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`).toArray();
|
|
1468
|
+
const total = allRecords.length;
|
|
1469
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1470
|
+
let query = table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`);
|
|
1471
|
+
if (perPageInput !== false) {
|
|
1472
|
+
query = query.limit(perPage);
|
|
1473
|
+
if (start > 0) query = query.offset(start);
|
|
898
1474
|
}
|
|
899
1475
|
const records = await query.toArray();
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
};
|
|
912
|
-
});
|
|
1476
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1477
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1478
|
+
return {
|
|
1479
|
+
pagination: {
|
|
1480
|
+
page,
|
|
1481
|
+
perPage: perPageForResponse,
|
|
1482
|
+
total,
|
|
1483
|
+
hasMore: end < total
|
|
1484
|
+
},
|
|
1485
|
+
scores
|
|
1486
|
+
};
|
|
913
1487
|
} catch (error$1) {
|
|
914
1488
|
throw new error.MastraError(
|
|
915
1489
|
{
|
|
916
|
-
id: "
|
|
1490
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_SPAN_FAILED",
|
|
1491
|
+
text: "Failed to get scores by traceId and spanId in LanceStorage",
|
|
917
1492
|
domain: error.ErrorDomain.STORAGE,
|
|
918
1493
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
919
|
-
details: {
|
|
1494
|
+
details: { error: error$1?.message }
|
|
920
1495
|
},
|
|
921
1496
|
error$1
|
|
922
1497
|
);
|
|
923
1498
|
}
|
|
924
1499
|
}
|
|
925
|
-
|
|
1500
|
+
};
|
|
1501
|
+
function parseWorkflowRun(row) {
|
|
1502
|
+
let parsedSnapshot = row.snapshot;
|
|
1503
|
+
if (typeof parsedSnapshot === "string") {
|
|
1504
|
+
try {
|
|
1505
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1506
|
+
} catch (e) {
|
|
1507
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
return {
|
|
1511
|
+
workflowName: row.workflow_name,
|
|
1512
|
+
runId: row.run_id,
|
|
1513
|
+
snapshot: parsedSnapshot,
|
|
1514
|
+
createdAt: storage.ensureDate(row.createdAt),
|
|
1515
|
+
updatedAt: storage.ensureDate(row.updatedAt),
|
|
1516
|
+
resourceId: row.resourceId
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
1520
|
+
client;
|
|
1521
|
+
constructor({ client }) {
|
|
1522
|
+
super();
|
|
1523
|
+
this.client = client;
|
|
1524
|
+
}
|
|
1525
|
+
updateWorkflowResults({
|
|
1526
|
+
// workflowName,
|
|
1527
|
+
// runId,
|
|
1528
|
+
// stepId,
|
|
1529
|
+
// result,
|
|
1530
|
+
// requestContext,
|
|
1531
|
+
}) {
|
|
1532
|
+
throw new Error("Method not implemented.");
|
|
1533
|
+
}
|
|
1534
|
+
updateWorkflowState({
|
|
1535
|
+
// workflowName,
|
|
1536
|
+
// runId,
|
|
1537
|
+
// opts,
|
|
1538
|
+
}) {
|
|
1539
|
+
throw new Error("Method not implemented.");
|
|
1540
|
+
}
|
|
1541
|
+
async persistWorkflowSnapshot({
|
|
1542
|
+
workflowName,
|
|
1543
|
+
runId,
|
|
1544
|
+
resourceId,
|
|
1545
|
+
snapshot
|
|
1546
|
+
}) {
|
|
926
1547
|
try {
|
|
927
|
-
const table = await this.
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1548
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1549
|
+
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1550
|
+
const records = await query.toArray();
|
|
1551
|
+
let createdAt;
|
|
1552
|
+
const now = Date.now();
|
|
1553
|
+
if (records.length > 0) {
|
|
1554
|
+
createdAt = records[0].createdAt ?? now;
|
|
1555
|
+
} else {
|
|
1556
|
+
createdAt = now;
|
|
1557
|
+
}
|
|
1558
|
+
const { status, value, ...rest } = snapshot;
|
|
1559
|
+
const record = {
|
|
1560
|
+
workflow_name: workflowName,
|
|
1561
|
+
run_id: runId,
|
|
1562
|
+
resourceId,
|
|
1563
|
+
snapshot: JSON.stringify({ status, value, ...rest }),
|
|
1564
|
+
// this is to ensure status is always just before value, for when querying the db by status
|
|
1565
|
+
createdAt,
|
|
1566
|
+
updatedAt: now
|
|
1567
|
+
};
|
|
1568
|
+
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
942
1569
|
} catch (error$1) {
|
|
943
1570
|
throw new error.MastraError(
|
|
944
1571
|
{
|
|
945
|
-
id: "
|
|
1572
|
+
id: "LANCE_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
|
|
946
1573
|
domain: error.ErrorDomain.STORAGE,
|
|
947
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1574
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1575
|
+
details: { workflowName, runId }
|
|
948
1576
|
},
|
|
949
1577
|
error$1
|
|
950
1578
|
);
|
|
951
1579
|
}
|
|
952
1580
|
}
|
|
953
|
-
async
|
|
1581
|
+
async loadWorkflowSnapshot({
|
|
1582
|
+
workflowName,
|
|
1583
|
+
runId
|
|
1584
|
+
}) {
|
|
954
1585
|
try {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
}
|
|
958
|
-
const table = await this.lanceClient.openTable(storage.TABLE_EVALS);
|
|
959
|
-
const query = table.query().where(`agent_name = '${agentName}'`);
|
|
1586
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1587
|
+
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
960
1588
|
const records = await query.toArray();
|
|
961
|
-
return records.
|
|
962
|
-
return {
|
|
963
|
-
id: record.id,
|
|
964
|
-
input: record.input,
|
|
965
|
-
output: record.output,
|
|
966
|
-
agentName: record.agent_name,
|
|
967
|
-
metricName: record.metric_name,
|
|
968
|
-
result: JSON.parse(record.result),
|
|
969
|
-
instructions: record.instructions,
|
|
970
|
-
testInfo: JSON.parse(record.test_info),
|
|
971
|
-
globalRunId: record.global_run_id,
|
|
972
|
-
runId: record.run_id,
|
|
973
|
-
createdAt: new Date(record.created_at).toString()
|
|
974
|
-
};
|
|
975
|
-
});
|
|
1589
|
+
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
976
1590
|
} catch (error$1) {
|
|
977
1591
|
throw new error.MastraError(
|
|
978
1592
|
{
|
|
979
|
-
id: "
|
|
1593
|
+
id: "LANCE_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
|
|
980
1594
|
domain: error.ErrorDomain.STORAGE,
|
|
981
1595
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
982
|
-
details: {
|
|
1596
|
+
details: { workflowName, runId }
|
|
983
1597
|
},
|
|
984
1598
|
error$1
|
|
985
1599
|
);
|
|
986
1600
|
}
|
|
987
1601
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1602
|
+
async getWorkflowRunById(args) {
|
|
1603
|
+
try {
|
|
1604
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1605
|
+
let whereClause = `run_id = '${args.runId}'`;
|
|
1606
|
+
if (args.workflowName) {
|
|
1607
|
+
whereClause += ` AND workflow_name = '${args.workflowName}'`;
|
|
995
1608
|
}
|
|
1609
|
+
const query = table.query().where(whereClause);
|
|
1610
|
+
const records = await query.toArray();
|
|
1611
|
+
if (records.length === 0) return null;
|
|
1612
|
+
const record = records[0];
|
|
1613
|
+
return parseWorkflowRun(record);
|
|
1614
|
+
} catch (error$1) {
|
|
1615
|
+
throw new error.MastraError(
|
|
1616
|
+
{
|
|
1617
|
+
id: "LANCE_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
|
|
1618
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1619
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1620
|
+
details: { runId: args.runId, workflowName: args.workflowName ?? "" }
|
|
1621
|
+
},
|
|
1622
|
+
error$1
|
|
1623
|
+
);
|
|
996
1624
|
}
|
|
997
|
-
return {
|
|
998
|
-
workflowName: row.workflow_name,
|
|
999
|
-
runId: row.run_id,
|
|
1000
|
-
snapshot: parsedSnapshot,
|
|
1001
|
-
createdAt: this.ensureDate(row.createdAt),
|
|
1002
|
-
updatedAt: this.ensureDate(row.updatedAt),
|
|
1003
|
-
resourceId: row.resourceId
|
|
1004
|
-
};
|
|
1005
1625
|
}
|
|
1006
|
-
async
|
|
1626
|
+
async listWorkflowRuns(args) {
|
|
1007
1627
|
try {
|
|
1008
|
-
const table = await this.
|
|
1009
|
-
|
|
1628
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1629
|
+
let query = table.query();
|
|
1630
|
+
const conditions = [];
|
|
1010
1631
|
if (args?.workflowName) {
|
|
1011
|
-
|
|
1632
|
+
conditions.push(`workflow_name = '${args.workflowName.replace(/'/g, "''")}'`);
|
|
1633
|
+
}
|
|
1634
|
+
if (args?.status) {
|
|
1635
|
+
const escapedStatus = args.status.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
1636
|
+
conditions.push(`\`snapshot\` LIKE '%"status":"${escapedStatus}","value"%'`);
|
|
1012
1637
|
}
|
|
1013
|
-
if (args?.
|
|
1014
|
-
|
|
1638
|
+
if (args?.resourceId) {
|
|
1639
|
+
conditions.push(`\`resourceId\` = '${args.resourceId}'`);
|
|
1015
1640
|
}
|
|
1016
|
-
if (args?.
|
|
1017
|
-
|
|
1641
|
+
if (args?.fromDate instanceof Date) {
|
|
1642
|
+
conditions.push(`\`createdAt\` >= ${args.fromDate.getTime()}`);
|
|
1018
1643
|
}
|
|
1019
|
-
if (args?.
|
|
1020
|
-
|
|
1644
|
+
if (args?.toDate instanceof Date) {
|
|
1645
|
+
conditions.push(`\`createdAt\` <= ${args.toDate.getTime()}`);
|
|
1021
1646
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1647
|
+
let total = 0;
|
|
1648
|
+
if (conditions.length > 0) {
|
|
1649
|
+
query = query.where(conditions.join(" AND "));
|
|
1650
|
+
total = await table.countRows(conditions.join(" AND "));
|
|
1651
|
+
} else {
|
|
1652
|
+
total = await table.countRows();
|
|
1653
|
+
}
|
|
1654
|
+
if (args?.perPage !== void 0 && args?.page !== void 0) {
|
|
1655
|
+
const normalizedPerPage = storage.normalizePerPage(args.perPage, Number.MAX_SAFE_INTEGER);
|
|
1656
|
+
if (args.page < 0 || !Number.isInteger(args.page)) {
|
|
1657
|
+
throw new error.MastraError(
|
|
1658
|
+
{
|
|
1659
|
+
id: "LANCE_STORE_INVALID_PAGINATION_PARAMS",
|
|
1660
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1661
|
+
category: error.ErrorCategory.USER,
|
|
1662
|
+
details: { page: args.page, perPage: args.perPage }
|
|
1663
|
+
},
|
|
1664
|
+
new Error(`Invalid pagination parameters: page=${args.page}, perPage=${args.perPage}`)
|
|
1665
|
+
);
|
|
1666
|
+
}
|
|
1667
|
+
const offset = args.page * normalizedPerPage;
|
|
1668
|
+
query.limit(normalizedPerPage);
|
|
1669
|
+
query.offset(offset);
|
|
1024
1670
|
}
|
|
1025
1671
|
const records = await query.toArray();
|
|
1026
1672
|
return {
|
|
1027
|
-
runs: records.map((record) =>
|
|
1028
|
-
total: records.length
|
|
1673
|
+
runs: records.map((record) => parseWorkflowRun(record)),
|
|
1674
|
+
total: total || records.length
|
|
1029
1675
|
};
|
|
1030
1676
|
} catch (error$1) {
|
|
1031
1677
|
throw new error.MastraError(
|
|
1032
1678
|
{
|
|
1033
|
-
id: "
|
|
1679
|
+
id: "LANCE_STORE_LIST_WORKFLOW_RUNS_FAILED",
|
|
1034
1680
|
domain: error.ErrorDomain.STORAGE,
|
|
1035
1681
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1036
|
-
details: {
|
|
1682
|
+
details: { resourceId: args?.resourceId ?? "", workflowName: args?.workflowName ?? "" }
|
|
1037
1683
|
},
|
|
1038
1684
|
error$1
|
|
1039
1685
|
);
|
|
1040
1686
|
}
|
|
1041
1687
|
}
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
// src/storage/index.ts
|
|
1691
|
+
var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
1692
|
+
stores;
|
|
1693
|
+
lanceClient;
|
|
1694
|
+
/**
|
|
1695
|
+
* Creates a new instance of LanceStorage
|
|
1696
|
+
* @param id The unique identifier for this storage instance
|
|
1697
|
+
* @param name The name for this storage instance
|
|
1698
|
+
* @param uri The URI to connect to LanceDB
|
|
1699
|
+
* @param options connection options
|
|
1700
|
+
*
|
|
1701
|
+
* Usage:
|
|
1702
|
+
*
|
|
1703
|
+
* Connect to a local database
|
|
1704
|
+
* ```ts
|
|
1705
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db');
|
|
1706
|
+
* ```
|
|
1707
|
+
*
|
|
1708
|
+
* Connect to a LanceDB cloud database
|
|
1709
|
+
* ```ts
|
|
1710
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 'db://host:port');
|
|
1711
|
+
* ```
|
|
1712
|
+
*
|
|
1713
|
+
* Connect to a cloud database
|
|
1714
|
+
* ```ts
|
|
1715
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 's3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1716
|
+
* ```
|
|
1717
|
+
*/
|
|
1718
|
+
static async create(id, name, uri, options) {
|
|
1719
|
+
const instance = new _LanceStorage(id, name);
|
|
1720
|
+
try {
|
|
1721
|
+
instance.lanceClient = await lancedb.connect(uri, options);
|
|
1722
|
+
const operations = new StoreOperationsLance({ client: instance.lanceClient });
|
|
1723
|
+
instance.stores = {
|
|
1724
|
+
operations: new StoreOperationsLance({ client: instance.lanceClient }),
|
|
1725
|
+
workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
|
|
1726
|
+
scores: new StoreScoresLance({ client: instance.lanceClient }),
|
|
1727
|
+
memory: new StoreMemoryLance({ client: instance.lanceClient, operations })
|
|
1728
|
+
};
|
|
1729
|
+
return instance;
|
|
1730
|
+
} catch (e) {
|
|
1731
|
+
throw new error.MastraError(
|
|
1732
|
+
{
|
|
1733
|
+
id: "STORAGE_LANCE_STORAGE_CONNECT_FAILED",
|
|
1734
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1735
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1736
|
+
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
1737
|
+
details: { uri, optionsProvided: !!options }
|
|
1738
|
+
},
|
|
1739
|
+
e
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* @internal
|
|
1745
|
+
* Private constructor to enforce using the create factory method
|
|
1746
|
+
*/
|
|
1747
|
+
constructor(id, name) {
|
|
1748
|
+
super({ id, name });
|
|
1749
|
+
const operations = new StoreOperationsLance({ client: this.lanceClient });
|
|
1750
|
+
this.stores = {
|
|
1751
|
+
operations: new StoreOperationsLance({ client: this.lanceClient }),
|
|
1752
|
+
workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
|
|
1753
|
+
scores: new StoreScoresLance({ client: this.lanceClient }),
|
|
1754
|
+
memory: new StoreMemoryLance({ client: this.lanceClient, operations })
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
async createTable({
|
|
1758
|
+
tableName,
|
|
1759
|
+
schema
|
|
1760
|
+
}) {
|
|
1761
|
+
return this.stores.operations.createTable({ tableName, schema });
|
|
1762
|
+
}
|
|
1763
|
+
async dropTable({ tableName }) {
|
|
1764
|
+
return this.stores.operations.dropTable({ tableName });
|
|
1765
|
+
}
|
|
1766
|
+
async alterTable({
|
|
1767
|
+
tableName,
|
|
1768
|
+
schema,
|
|
1769
|
+
ifNotExists
|
|
1770
|
+
}) {
|
|
1771
|
+
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
1772
|
+
}
|
|
1773
|
+
async clearTable({ tableName }) {
|
|
1774
|
+
return this.stores.operations.clearTable({ tableName });
|
|
1775
|
+
}
|
|
1776
|
+
async insert({ tableName, record }) {
|
|
1777
|
+
return this.stores.operations.insert({ tableName, record });
|
|
1778
|
+
}
|
|
1779
|
+
async batchInsert({ tableName, records }) {
|
|
1780
|
+
return this.stores.operations.batchInsert({ tableName, records });
|
|
1781
|
+
}
|
|
1782
|
+
async load({ tableName, keys }) {
|
|
1783
|
+
return this.stores.operations.load({ tableName, keys });
|
|
1784
|
+
}
|
|
1785
|
+
async getThreadById({ threadId }) {
|
|
1786
|
+
return this.stores.memory.getThreadById({ threadId });
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
1790
|
+
* @param thread - The thread to save
|
|
1791
|
+
* @returns The saved thread
|
|
1792
|
+
*/
|
|
1793
|
+
async saveThread({ thread }) {
|
|
1794
|
+
return this.stores.memory.saveThread({ thread });
|
|
1795
|
+
}
|
|
1796
|
+
async updateThread({
|
|
1797
|
+
id,
|
|
1798
|
+
title,
|
|
1799
|
+
metadata
|
|
1800
|
+
}) {
|
|
1801
|
+
return this.stores.memory.updateThread({ id, title, metadata });
|
|
1802
|
+
}
|
|
1803
|
+
async deleteThread({ threadId }) {
|
|
1804
|
+
return this.stores.memory.deleteThread({ threadId });
|
|
1805
|
+
}
|
|
1806
|
+
get supports() {
|
|
1807
|
+
return {
|
|
1808
|
+
selectByIncludeResourceScope: true,
|
|
1809
|
+
resourceWorkingMemory: true,
|
|
1810
|
+
hasColumn: true,
|
|
1811
|
+
createTable: true,
|
|
1812
|
+
deleteMessages: false,
|
|
1813
|
+
listScoresBySpan: true
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
async getResourceById({ resourceId }) {
|
|
1817
|
+
return this.stores.memory.getResourceById({ resourceId });
|
|
1818
|
+
}
|
|
1819
|
+
async saveResource({ resource }) {
|
|
1820
|
+
return this.stores.memory.saveResource({ resource });
|
|
1821
|
+
}
|
|
1822
|
+
async updateResource({
|
|
1823
|
+
resourceId,
|
|
1824
|
+
workingMemory,
|
|
1825
|
+
metadata
|
|
1826
|
+
}) {
|
|
1827
|
+
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
1828
|
+
}
|
|
1042
1829
|
/**
|
|
1043
|
-
*
|
|
1044
|
-
* @param
|
|
1045
|
-
* @
|
|
1830
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
1831
|
+
* @param records - The sorted array of records to process
|
|
1832
|
+
* @param include - The array of include specifications with context parameters
|
|
1833
|
+
* @returns The processed array with context messages included
|
|
1046
1834
|
*/
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1835
|
+
processMessagesWithContext(records, include) {
|
|
1836
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
1837
|
+
if (messagesWithContext.length === 0) {
|
|
1838
|
+
return records;
|
|
1839
|
+
}
|
|
1840
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
1841
|
+
records.forEach((message, index) => {
|
|
1842
|
+
messageIndexMap.set(message.id, index);
|
|
1843
|
+
});
|
|
1844
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
1845
|
+
for (const item of messagesWithContext) {
|
|
1846
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
1847
|
+
if (messageIndex !== void 0) {
|
|
1848
|
+
if (item.withPreviousMessages) {
|
|
1849
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
1850
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
1851
|
+
additionalIndices.add(i);
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
if (item.withNextMessages) {
|
|
1855
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
1856
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
1857
|
+
additionalIndices.add(i);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1053
1860
|
}
|
|
1054
|
-
const query = table.query().where(whereClause);
|
|
1055
|
-
const records = await query.toArray();
|
|
1056
|
-
if (records.length === 0) return null;
|
|
1057
|
-
const record = records[0];
|
|
1058
|
-
return this.parseWorkflowRun(record);
|
|
1059
|
-
} catch (error$1) {
|
|
1060
|
-
throw new error.MastraError(
|
|
1061
|
-
{
|
|
1062
|
-
id: "LANCE_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
|
|
1063
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1064
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1065
|
-
details: { runId: args.runId, workflowName: args.workflowName ?? "" }
|
|
1066
|
-
},
|
|
1067
|
-
error$1
|
|
1068
|
-
);
|
|
1069
1861
|
}
|
|
1862
|
+
if (additionalIndices.size === 0) {
|
|
1863
|
+
return records;
|
|
1864
|
+
}
|
|
1865
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
1866
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
1867
|
+
records.forEach((record, index) => {
|
|
1868
|
+
if (originalMatchIds.has(record.id)) {
|
|
1869
|
+
allIndices.add(index);
|
|
1870
|
+
}
|
|
1871
|
+
});
|
|
1872
|
+
additionalIndices.forEach((index) => {
|
|
1873
|
+
allIndices.add(index);
|
|
1874
|
+
});
|
|
1875
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
1876
|
+
}
|
|
1877
|
+
async listMessagesById({ messageIds }) {
|
|
1878
|
+
return this.stores.memory.listMessagesById({ messageIds });
|
|
1879
|
+
}
|
|
1880
|
+
async saveMessages(args) {
|
|
1881
|
+
return this.stores.memory.saveMessages(args);
|
|
1882
|
+
}
|
|
1883
|
+
async updateMessages(_args) {
|
|
1884
|
+
return this.stores.memory.updateMessages(_args);
|
|
1885
|
+
}
|
|
1886
|
+
async listWorkflowRuns(args) {
|
|
1887
|
+
return this.stores.workflows.listWorkflowRuns(args);
|
|
1888
|
+
}
|
|
1889
|
+
async getWorkflowRunById(args) {
|
|
1890
|
+
return this.stores.workflows.getWorkflowRunById(args);
|
|
1891
|
+
}
|
|
1892
|
+
async updateWorkflowResults({
|
|
1893
|
+
workflowName,
|
|
1894
|
+
runId,
|
|
1895
|
+
stepId,
|
|
1896
|
+
result,
|
|
1897
|
+
requestContext
|
|
1898
|
+
}) {
|
|
1899
|
+
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
1900
|
+
}
|
|
1901
|
+
async updateWorkflowState({
|
|
1902
|
+
workflowName,
|
|
1903
|
+
runId,
|
|
1904
|
+
opts
|
|
1905
|
+
}) {
|
|
1906
|
+
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
1070
1907
|
}
|
|
1071
1908
|
async persistWorkflowSnapshot({
|
|
1072
1909
|
workflowName,
|
|
1073
1910
|
runId,
|
|
1911
|
+
resourceId,
|
|
1074
1912
|
snapshot
|
|
1075
1913
|
}) {
|
|
1076
|
-
|
|
1077
|
-
const table = await this.lanceClient.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1078
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1079
|
-
const records = await query.toArray();
|
|
1080
|
-
let createdAt;
|
|
1081
|
-
const now = Date.now();
|
|
1082
|
-
if (records.length > 0) {
|
|
1083
|
-
createdAt = records[0].createdAt ?? now;
|
|
1084
|
-
} else {
|
|
1085
|
-
createdAt = now;
|
|
1086
|
-
}
|
|
1087
|
-
const record = {
|
|
1088
|
-
workflow_name: workflowName,
|
|
1089
|
-
run_id: runId,
|
|
1090
|
-
snapshot: JSON.stringify(snapshot),
|
|
1091
|
-
createdAt,
|
|
1092
|
-
updatedAt: now
|
|
1093
|
-
};
|
|
1094
|
-
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1095
|
-
} catch (error$1) {
|
|
1096
|
-
throw new error.MastraError(
|
|
1097
|
-
{
|
|
1098
|
-
id: "LANCE_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
|
|
1099
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1100
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1101
|
-
details: { workflowName, runId }
|
|
1102
|
-
},
|
|
1103
|
-
error$1
|
|
1104
|
-
);
|
|
1105
|
-
}
|
|
1914
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
1106
1915
|
}
|
|
1107
1916
|
async loadWorkflowSnapshot({
|
|
1108
1917
|
workflowName,
|
|
1109
1918
|
runId
|
|
1110
1919
|
}) {
|
|
1111
|
-
|
|
1112
|
-
const table = await this.lanceClient.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1113
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1114
|
-
const records = await query.toArray();
|
|
1115
|
-
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
1116
|
-
} catch (error$1) {
|
|
1117
|
-
throw new error.MastraError(
|
|
1118
|
-
{
|
|
1119
|
-
id: "LANCE_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
|
|
1120
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1121
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1122
|
-
details: { workflowName, runId }
|
|
1123
|
-
},
|
|
1124
|
-
error$1
|
|
1125
|
-
);
|
|
1126
|
-
}
|
|
1920
|
+
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
1127
1921
|
}
|
|
1128
|
-
async
|
|
1129
|
-
|
|
1130
|
-
{
|
|
1131
|
-
id: "LANCE_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
1132
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1133
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1134
|
-
},
|
|
1135
|
-
"Method not implemented."
|
|
1136
|
-
);
|
|
1922
|
+
async getScoreById({ id: _id }) {
|
|
1923
|
+
return this.stores.scores.getScoreById({ id: _id });
|
|
1137
1924
|
}
|
|
1138
|
-
async
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
);
|
|
1925
|
+
async listScoresByScorerId({
|
|
1926
|
+
scorerId,
|
|
1927
|
+
source,
|
|
1928
|
+
entityId,
|
|
1929
|
+
entityType,
|
|
1930
|
+
pagination
|
|
1931
|
+
}) {
|
|
1932
|
+
return this.stores.scores.listScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
|
|
1147
1933
|
}
|
|
1148
|
-
async
|
|
1149
|
-
|
|
1150
|
-
{
|
|
1151
|
-
id: "LANCE_STORE_GET_MESSAGES_PAGINATED_FAILED",
|
|
1152
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1153
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1154
|
-
},
|
|
1155
|
-
"Method not implemented."
|
|
1156
|
-
);
|
|
1934
|
+
async saveScore(_score) {
|
|
1935
|
+
return this.stores.scores.saveScore(_score);
|
|
1157
1936
|
}
|
|
1158
|
-
async
|
|
1159
|
-
|
|
1160
|
-
|
|
1937
|
+
async listScoresByRunId({
|
|
1938
|
+
runId,
|
|
1939
|
+
pagination
|
|
1940
|
+
}) {
|
|
1941
|
+
return this.stores.scores.listScoresByRunId({ runId, pagination });
|
|
1942
|
+
}
|
|
1943
|
+
async listScoresByEntityId({
|
|
1944
|
+
entityId,
|
|
1945
|
+
entityType,
|
|
1946
|
+
pagination
|
|
1947
|
+
}) {
|
|
1948
|
+
return this.stores.scores.listScoresByEntityId({ entityId, entityType, pagination });
|
|
1949
|
+
}
|
|
1950
|
+
async listScoresBySpan({
|
|
1951
|
+
traceId,
|
|
1952
|
+
spanId,
|
|
1953
|
+
pagination
|
|
1954
|
+
}) {
|
|
1955
|
+
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
|
|
1161
1956
|
}
|
|
1162
1957
|
};
|
|
1163
1958
|
var LanceFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
@@ -1506,7 +2301,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
1506
2301
|
* ```
|
|
1507
2302
|
*/
|
|
1508
2303
|
static async create(uri, options) {
|
|
1509
|
-
const instance = new _LanceVectorStore();
|
|
2304
|
+
const instance = new _LanceVectorStore(options?.id || crypto.randomUUID());
|
|
1510
2305
|
try {
|
|
1511
2306
|
instance.lanceClient = await lancedb.connect(uri, options);
|
|
1512
2307
|
return instance;
|
|
@@ -1526,8 +2321,8 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
1526
2321
|
* @internal
|
|
1527
2322
|
* Private constructor to enforce using the create factory method
|
|
1528
2323
|
*/
|
|
1529
|
-
constructor() {
|
|
1530
|
-
super();
|
|
2324
|
+
constructor(id) {
|
|
2325
|
+
super({ id });
|
|
1531
2326
|
}
|
|
1532
2327
|
close() {
|
|
1533
2328
|
if (this.lanceClient) {
|
|
@@ -2050,7 +2845,44 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2050
2845
|
);
|
|
2051
2846
|
}
|
|
2052
2847
|
}
|
|
2053
|
-
async updateVector(
|
|
2848
|
+
async updateVector(params) {
|
|
2849
|
+
const { indexName, update } = params;
|
|
2850
|
+
if ("id" in params && "filter" in params && params.id && params.filter) {
|
|
2851
|
+
throw new error.MastraError({
|
|
2852
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2853
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2854
|
+
category: error.ErrorCategory.USER,
|
|
2855
|
+
text: "id and filter are mutually exclusive",
|
|
2856
|
+
details: { indexName }
|
|
2857
|
+
});
|
|
2858
|
+
}
|
|
2859
|
+
if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
|
|
2860
|
+
throw new error.MastraError({
|
|
2861
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2862
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2863
|
+
category: error.ErrorCategory.USER,
|
|
2864
|
+
text: "Either id or filter must be provided",
|
|
2865
|
+
details: { indexName }
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
|
|
2869
|
+
throw new error.MastraError({
|
|
2870
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2871
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2872
|
+
category: error.ErrorCategory.USER,
|
|
2873
|
+
text: "Cannot update with empty filter",
|
|
2874
|
+
details: { indexName }
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
if (!update.vector && !update.metadata) {
|
|
2878
|
+
throw new error.MastraError({
|
|
2879
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2880
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2881
|
+
category: error.ErrorCategory.USER,
|
|
2882
|
+
text: "No updates provided",
|
|
2883
|
+
details: { indexName }
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2054
2886
|
try {
|
|
2055
2887
|
if (!this.lanceClient) {
|
|
2056
2888
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
@@ -2058,21 +2890,6 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2058
2890
|
if (!indexName) {
|
|
2059
2891
|
throw new Error("indexName is required");
|
|
2060
2892
|
}
|
|
2061
|
-
if (!id) {
|
|
2062
|
-
throw new Error("id is required");
|
|
2063
|
-
}
|
|
2064
|
-
} catch (err) {
|
|
2065
|
-
throw new error.MastraError(
|
|
2066
|
-
{
|
|
2067
|
-
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED_INVALID_ARGS",
|
|
2068
|
-
domain: error.ErrorDomain.STORAGE,
|
|
2069
|
-
category: error.ErrorCategory.USER,
|
|
2070
|
-
details: { indexName, id }
|
|
2071
|
-
},
|
|
2072
|
-
err
|
|
2073
|
-
);
|
|
2074
|
-
}
|
|
2075
|
-
try {
|
|
2076
2893
|
const tables = await this.lanceClient.tableNames();
|
|
2077
2894
|
for (const tableName of tables) {
|
|
2078
2895
|
this.logger.debug("Checking table:" + tableName);
|
|
@@ -2082,39 +2899,66 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2082
2899
|
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
2083
2900
|
if (hasColumn) {
|
|
2084
2901
|
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
2085
|
-
|
|
2086
|
-
if (
|
|
2087
|
-
|
|
2902
|
+
let whereClause;
|
|
2903
|
+
if ("id" in params && params.id) {
|
|
2904
|
+
whereClause = `id = '${params.id}'`;
|
|
2905
|
+
} else if ("filter" in params && params.filter) {
|
|
2906
|
+
const translator = new LanceFilterTranslator();
|
|
2907
|
+
const processFilterKeys = (filter) => {
|
|
2908
|
+
const processedFilter = {};
|
|
2909
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
2910
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
2911
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
2912
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
2913
|
+
});
|
|
2914
|
+
} else {
|
|
2915
|
+
processedFilter[`metadata_${key}`] = value;
|
|
2916
|
+
}
|
|
2917
|
+
});
|
|
2918
|
+
return processedFilter;
|
|
2919
|
+
};
|
|
2920
|
+
const prefixedFilter = processFilterKeys(params.filter);
|
|
2921
|
+
whereClause = translator.translate(prefixedFilter) || "";
|
|
2922
|
+
if (!whereClause) {
|
|
2923
|
+
throw new Error("Failed to translate filter to SQL");
|
|
2924
|
+
}
|
|
2925
|
+
} else {
|
|
2926
|
+
throw new Error("Either id or filter must be provided");
|
|
2088
2927
|
}
|
|
2089
|
-
const
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2928
|
+
const existingRecords = await table.query().where(whereClause).select(schema.fields.map((field) => field.name)).toArray();
|
|
2929
|
+
if (existingRecords.length === 0) {
|
|
2930
|
+
this.logger.info(`No records found matching criteria in table ${tableName}`);
|
|
2931
|
+
return;
|
|
2932
|
+
}
|
|
2933
|
+
const updatedRecords = existingRecords.map((record) => {
|
|
2934
|
+
const rowData = {};
|
|
2935
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
2936
|
+
if (key !== "_distance") {
|
|
2937
|
+
if (key === indexName) {
|
|
2938
|
+
if (update.vector) {
|
|
2939
|
+
rowData[key] = update.vector;
|
|
2100
2940
|
} else {
|
|
2101
|
-
|
|
2941
|
+
if (Array.isArray(value)) {
|
|
2942
|
+
rowData[key] = [...value];
|
|
2943
|
+
} else if (typeof value === "object" && value !== null) {
|
|
2944
|
+
rowData[key] = Array.from(value);
|
|
2945
|
+
} else {
|
|
2946
|
+
rowData[key] = value;
|
|
2947
|
+
}
|
|
2102
2948
|
}
|
|
2949
|
+
} else {
|
|
2950
|
+
rowData[key] = value;
|
|
2103
2951
|
}
|
|
2104
|
-
} else {
|
|
2105
|
-
rowData[key] = value;
|
|
2106
2952
|
}
|
|
2953
|
+
});
|
|
2954
|
+
if (update.metadata) {
|
|
2955
|
+
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
2956
|
+
rowData[`metadata_${key}`] = value;
|
|
2957
|
+
});
|
|
2107
2958
|
}
|
|
2959
|
+
return rowData;
|
|
2108
2960
|
});
|
|
2109
|
-
|
|
2110
|
-
rowData[indexName] = update.vector;
|
|
2111
|
-
}
|
|
2112
|
-
if (update.metadata) {
|
|
2113
|
-
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
2114
|
-
rowData[`metadata_${key}`] = value;
|
|
2115
|
-
});
|
|
2116
|
-
}
|
|
2117
|
-
await table.add([rowData], { mode: "overwrite" });
|
|
2961
|
+
await table.add(updatedRecords, { mode: "overwrite" });
|
|
2118
2962
|
return;
|
|
2119
2963
|
}
|
|
2120
2964
|
} catch (err) {
|
|
@@ -2124,12 +2968,19 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2124
2968
|
}
|
|
2125
2969
|
throw new Error(`No table found with column/index '${indexName}'`);
|
|
2126
2970
|
} catch (error$1) {
|
|
2971
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
2127
2972
|
throw new error.MastraError(
|
|
2128
2973
|
{
|
|
2129
2974
|
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED",
|
|
2130
2975
|
domain: error.ErrorDomain.STORAGE,
|
|
2131
2976
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2132
|
-
details: {
|
|
2977
|
+
details: {
|
|
2978
|
+
indexName,
|
|
2979
|
+
..."id" in params && params.id && { id: params.id },
|
|
2980
|
+
..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) },
|
|
2981
|
+
hasVector: !!update.vector,
|
|
2982
|
+
hasMetadata: !!update.metadata
|
|
2983
|
+
}
|
|
2133
2984
|
},
|
|
2134
2985
|
error$1
|
|
2135
2986
|
);
|
|
@@ -2152,7 +3003,10 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2152
3003
|
id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED_INVALID_ARGS",
|
|
2153
3004
|
domain: error.ErrorDomain.STORAGE,
|
|
2154
3005
|
category: error.ErrorCategory.USER,
|
|
2155
|
-
details: {
|
|
3006
|
+
details: {
|
|
3007
|
+
indexName,
|
|
3008
|
+
...id && { id }
|
|
3009
|
+
}
|
|
2156
3010
|
},
|
|
2157
3011
|
err
|
|
2158
3012
|
);
|
|
@@ -2182,7 +3036,10 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2182
3036
|
id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED",
|
|
2183
3037
|
domain: error.ErrorDomain.STORAGE,
|
|
2184
3038
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2185
|
-
details: {
|
|
3039
|
+
details: {
|
|
3040
|
+
indexName,
|
|
3041
|
+
...id && { id }
|
|
3042
|
+
}
|
|
2186
3043
|
},
|
|
2187
3044
|
error$1
|
|
2188
3045
|
);
|
|
@@ -2213,7 +3070,112 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2213
3070
|
});
|
|
2214
3071
|
return result;
|
|
2215
3072
|
}
|
|
3073
|
+
async deleteVectors({ indexName, filter, ids }) {
|
|
3074
|
+
if (ids && filter) {
|
|
3075
|
+
throw new error.MastraError({
|
|
3076
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3077
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3078
|
+
category: error.ErrorCategory.USER,
|
|
3079
|
+
text: "ids and filter are mutually exclusive",
|
|
3080
|
+
details: { indexName }
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
if (!ids && !filter) {
|
|
3084
|
+
throw new error.MastraError({
|
|
3085
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3086
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3087
|
+
category: error.ErrorCategory.USER,
|
|
3088
|
+
text: "Either filter or ids must be provided",
|
|
3089
|
+
details: { indexName }
|
|
3090
|
+
});
|
|
3091
|
+
}
|
|
3092
|
+
if (ids && ids.length === 0) {
|
|
3093
|
+
throw new error.MastraError({
|
|
3094
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3095
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3096
|
+
category: error.ErrorCategory.USER,
|
|
3097
|
+
text: "Cannot delete with empty ids array",
|
|
3098
|
+
details: { indexName }
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
if (filter && Object.keys(filter).length === 0) {
|
|
3102
|
+
throw new error.MastraError({
|
|
3103
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3104
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3105
|
+
category: error.ErrorCategory.USER,
|
|
3106
|
+
text: "Cannot delete with empty filter",
|
|
3107
|
+
details: { indexName }
|
|
3108
|
+
});
|
|
3109
|
+
}
|
|
3110
|
+
try {
|
|
3111
|
+
if (!this.lanceClient) {
|
|
3112
|
+
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
3113
|
+
}
|
|
3114
|
+
if (!indexName) {
|
|
3115
|
+
throw new Error("indexName is required");
|
|
3116
|
+
}
|
|
3117
|
+
const tables = await this.lanceClient.tableNames();
|
|
3118
|
+
for (const tableName of tables) {
|
|
3119
|
+
this.logger.debug("Checking table:" + tableName);
|
|
3120
|
+
const table = await this.lanceClient.openTable(tableName);
|
|
3121
|
+
try {
|
|
3122
|
+
const schema = await table.schema();
|
|
3123
|
+
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3124
|
+
if (hasColumn) {
|
|
3125
|
+
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3126
|
+
if (ids) {
|
|
3127
|
+
const idsConditions = ids.map((id) => `id = '${id}'`).join(" OR ");
|
|
3128
|
+
await table.delete(idsConditions);
|
|
3129
|
+
} else if (filter) {
|
|
3130
|
+
const translator = new LanceFilterTranslator();
|
|
3131
|
+
const processFilterKeys = (filter2) => {
|
|
3132
|
+
const processedFilter = {};
|
|
3133
|
+
Object.entries(filter2).forEach(([key, value]) => {
|
|
3134
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3135
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
3136
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
3137
|
+
});
|
|
3138
|
+
} else {
|
|
3139
|
+
processedFilter[`metadata_${key}`] = value;
|
|
3140
|
+
}
|
|
3141
|
+
});
|
|
3142
|
+
return processedFilter;
|
|
3143
|
+
};
|
|
3144
|
+
const prefixedFilter = processFilterKeys(filter);
|
|
3145
|
+
const whereClause = translator.translate(prefixedFilter);
|
|
3146
|
+
if (!whereClause) {
|
|
3147
|
+
throw new Error("Failed to translate filter to SQL");
|
|
3148
|
+
}
|
|
3149
|
+
await table.delete(whereClause);
|
|
3150
|
+
}
|
|
3151
|
+
return;
|
|
3152
|
+
}
|
|
3153
|
+
} catch (err) {
|
|
3154
|
+
this.logger.error(`Error checking schema for table ${tableName}:` + err);
|
|
3155
|
+
continue;
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3159
|
+
} catch (error$1) {
|
|
3160
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
3161
|
+
throw new error.MastraError(
|
|
3162
|
+
{
|
|
3163
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_FAILED",
|
|
3164
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3165
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
3166
|
+
details: {
|
|
3167
|
+
indexName,
|
|
3168
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
3169
|
+
...ids && { idsCount: ids.length }
|
|
3170
|
+
}
|
|
3171
|
+
},
|
|
3172
|
+
error$1
|
|
3173
|
+
);
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
2216
3176
|
};
|
|
2217
3177
|
|
|
2218
3178
|
exports.LanceStorage = LanceStorage;
|
|
2219
3179
|
exports.LanceVectorStore = LanceVectorStore;
|
|
3180
|
+
//# sourceMappingURL=index.cjs.map
|
|
3181
|
+
//# sourceMappingURL=index.cjs.map
|