@mastra/lance 0.0.0-netlify-no-bundle-20251127120354 → 0.0.0-new-button-export-20251219130424
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 +266 -18
- package/dist/index.cjs +1131 -993
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1132 -994
- package/dist/index.js.map +1 -1
- package/dist/storage/{domains/operations → db}/index.d.ts +21 -2
- package/dist/storage/db/index.d.ts.map +1 -0
- package/dist/storage/db/utils.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +6 -7
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +14 -6
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +16 -14
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +41 -40
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +5 -6
- package/dist/storage/domains/operations/index.d.ts.map +0 -1
- package/dist/storage/domains/utils.d.ts.map +0 -1
- /package/dist/storage/{domains → db}/utils.d.ts +0 -0
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ var lancedb = require('@lancedb/lancedb');
|
|
|
4
4
|
var error = require('@mastra/core/error');
|
|
5
5
|
var storage = require('@mastra/core/storage');
|
|
6
6
|
var agent = require('@mastra/core/agent');
|
|
7
|
+
var base = require('@mastra/core/base');
|
|
7
8
|
var apacheArrow = require('apache-arrow');
|
|
8
9
|
var evals = require('@mastra/core/evals');
|
|
9
10
|
var vector = require('@mastra/core/vector');
|
|
@@ -91,7 +92,7 @@ async function getTableSchema({
|
|
|
91
92
|
} catch (validationError) {
|
|
92
93
|
throw new error.MastraError(
|
|
93
94
|
{
|
|
94
|
-
id: "
|
|
95
|
+
id: storage.createStorageErrorId("LANCE", "GET_TABLE_SCHEMA", "INVALID_ARGS"),
|
|
95
96
|
domain: error.ErrorDomain.STORAGE,
|
|
96
97
|
category: error.ErrorCategory.USER,
|
|
97
98
|
text: validationError.message,
|
|
@@ -114,7 +115,7 @@ async function getTableSchema({
|
|
|
114
115
|
} catch (error$1) {
|
|
115
116
|
throw new error.MastraError(
|
|
116
117
|
{
|
|
117
|
-
id: "
|
|
118
|
+
id: storage.createStorageErrorId("LANCE", "GET_TABLE_SCHEMA", "FAILED"),
|
|
118
119
|
domain: error.ErrorDomain.STORAGE,
|
|
119
120
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
120
121
|
details: { tableName }
|
|
@@ -124,1118 +125,1198 @@ async function getTableSchema({
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
// src/storage/
|
|
128
|
-
|
|
128
|
+
// src/storage/db/index.ts
|
|
129
|
+
function resolveLanceConfig(config) {
|
|
130
|
+
return config.client;
|
|
131
|
+
}
|
|
132
|
+
var LanceDB = class extends base.MastraBase {
|
|
129
133
|
client;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
super();
|
|
134
|
+
constructor({ client }) {
|
|
135
|
+
super({ name: "lance-db" });
|
|
133
136
|
this.client = client;
|
|
134
|
-
this.operations = operations;
|
|
135
137
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
getDefaultValue(type) {
|
|
139
|
+
switch (type) {
|
|
140
|
+
case "text":
|
|
141
|
+
return "''";
|
|
142
|
+
case "timestamp":
|
|
143
|
+
return "CURRENT_TIMESTAMP";
|
|
144
|
+
case "integer":
|
|
145
|
+
case "bigint":
|
|
146
|
+
return "0";
|
|
147
|
+
case "jsonb":
|
|
148
|
+
return "'{}'";
|
|
149
|
+
case "uuid":
|
|
150
|
+
return "''";
|
|
151
|
+
default:
|
|
152
|
+
return storage.getDefaultValue(type);
|
|
153
|
+
}
|
|
139
154
|
}
|
|
140
|
-
async
|
|
155
|
+
async hasColumn(tableName, columnName) {
|
|
156
|
+
const table = await this.client.openTable(tableName);
|
|
157
|
+
const schema = await table.schema();
|
|
158
|
+
return schema.fields.some((field) => field.name === columnName);
|
|
159
|
+
}
|
|
160
|
+
translateSchema(schema) {
|
|
161
|
+
const fields = Object.entries(schema).map(([name, column]) => {
|
|
162
|
+
let arrowType;
|
|
163
|
+
switch (column.type.toLowerCase()) {
|
|
164
|
+
case "text":
|
|
165
|
+
case "uuid":
|
|
166
|
+
arrowType = new apacheArrow.Utf8();
|
|
167
|
+
break;
|
|
168
|
+
case "int":
|
|
169
|
+
case "integer":
|
|
170
|
+
arrowType = new apacheArrow.Int32();
|
|
171
|
+
break;
|
|
172
|
+
case "bigint":
|
|
173
|
+
arrowType = new apacheArrow.Float64();
|
|
174
|
+
break;
|
|
175
|
+
case "float":
|
|
176
|
+
arrowType = new apacheArrow.Float32();
|
|
177
|
+
break;
|
|
178
|
+
case "jsonb":
|
|
179
|
+
case "json":
|
|
180
|
+
arrowType = new apacheArrow.Utf8();
|
|
181
|
+
break;
|
|
182
|
+
case "binary":
|
|
183
|
+
arrowType = new apacheArrow.Binary();
|
|
184
|
+
break;
|
|
185
|
+
case "timestamp":
|
|
186
|
+
arrowType = new apacheArrow.Float64();
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
arrowType = new apacheArrow.Utf8();
|
|
190
|
+
}
|
|
191
|
+
return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
|
|
192
|
+
});
|
|
193
|
+
return new apacheArrow.Schema(fields);
|
|
194
|
+
}
|
|
195
|
+
async createTable({
|
|
196
|
+
tableName,
|
|
197
|
+
schema
|
|
198
|
+
}) {
|
|
141
199
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
200
|
+
if (!this.client) {
|
|
201
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
202
|
+
}
|
|
203
|
+
if (!tableName) {
|
|
204
|
+
throw new Error("tableName is required for createTable.");
|
|
205
|
+
}
|
|
206
|
+
if (!schema) {
|
|
207
|
+
throw new Error("schema is required for createTable.");
|
|
145
208
|
}
|
|
146
|
-
return {
|
|
147
|
-
...thread,
|
|
148
|
-
createdAt: new Date(thread.createdAt),
|
|
149
|
-
updatedAt: new Date(thread.updatedAt)
|
|
150
|
-
};
|
|
151
209
|
} catch (error$1) {
|
|
152
210
|
throw new error.MastraError(
|
|
153
211
|
{
|
|
154
|
-
id: "
|
|
212
|
+
id: storage.createStorageErrorId("LANCE", "CREATE_TABLE", "INVALID_ARGS"),
|
|
155
213
|
domain: error.ErrorDomain.STORAGE,
|
|
156
|
-
category: error.ErrorCategory.
|
|
214
|
+
category: error.ErrorCategory.USER,
|
|
215
|
+
details: { tableName }
|
|
157
216
|
},
|
|
158
217
|
error$1
|
|
159
218
|
);
|
|
160
219
|
}
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
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
|
|
166
|
-
*/
|
|
167
|
-
async saveThread({ thread }) {
|
|
168
220
|
try {
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
await table.add([record], { mode: "append" });
|
|
172
|
-
return thread;
|
|
221
|
+
const arrowSchema = this.translateSchema(schema);
|
|
222
|
+
await this.client.createEmptyTable(tableName, arrowSchema);
|
|
173
223
|
} catch (error$1) {
|
|
224
|
+
if (error$1.message?.includes("already exists")) {
|
|
225
|
+
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
174
228
|
throw new error.MastraError(
|
|
175
229
|
{
|
|
176
|
-
id: "
|
|
230
|
+
id: storage.createStorageErrorId("LANCE", "CREATE_TABLE", "FAILED"),
|
|
177
231
|
domain: error.ErrorDomain.STORAGE,
|
|
178
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
232
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
233
|
+
details: { tableName }
|
|
179
234
|
},
|
|
180
235
|
error$1
|
|
181
236
|
);
|
|
182
237
|
}
|
|
183
238
|
}
|
|
184
|
-
async
|
|
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 }) {
|
|
239
|
+
async dropTable({ tableName }) {
|
|
236
240
|
try {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
241
|
+
if (!this.client) {
|
|
242
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
243
|
+
}
|
|
244
|
+
if (!tableName) {
|
|
245
|
+
throw new Error("tableName is required for dropTable.");
|
|
246
|
+
}
|
|
247
|
+
} catch (validationError) {
|
|
242
248
|
throw new error.MastraError(
|
|
243
249
|
{
|
|
244
|
-
id: "
|
|
250
|
+
id: storage.createStorageErrorId("LANCE", "DROP_TABLE", "INVALID_ARGS"),
|
|
245
251
|
domain: error.ErrorDomain.STORAGE,
|
|
246
|
-
category: error.ErrorCategory.
|
|
252
|
+
category: error.ErrorCategory.USER,
|
|
253
|
+
text: validationError.message,
|
|
254
|
+
details: { tableName }
|
|
247
255
|
},
|
|
248
|
-
|
|
256
|
+
validationError
|
|
249
257
|
);
|
|
250
258
|
}
|
|
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
259
|
try {
|
|
269
|
-
|
|
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() };
|
|
260
|
+
await this.client.dropTable(tableName);
|
|
281
261
|
} catch (error$1) {
|
|
262
|
+
if (error$1.toString().includes("was not found") || error$1.message?.includes("Table not found")) {
|
|
263
|
+
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
282
266
|
throw new error.MastraError(
|
|
283
267
|
{
|
|
284
|
-
id: "
|
|
268
|
+
id: storage.createStorageErrorId("LANCE", "DROP_TABLE", "FAILED"),
|
|
285
269
|
domain: error.ErrorDomain.STORAGE,
|
|
286
270
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
287
|
-
details: {
|
|
288
|
-
messageIds: JSON.stringify(messageIds)
|
|
289
|
-
}
|
|
271
|
+
details: { tableName }
|
|
290
272
|
},
|
|
291
273
|
error$1
|
|
292
274
|
);
|
|
293
275
|
}
|
|
294
276
|
}
|
|
295
|
-
async
|
|
296
|
-
|
|
297
|
-
|
|
277
|
+
async alterTable({
|
|
278
|
+
tableName,
|
|
279
|
+
schema,
|
|
280
|
+
ifNotExists
|
|
281
|
+
}) {
|
|
282
|
+
try {
|
|
283
|
+
if (!this.client) {
|
|
284
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
285
|
+
}
|
|
286
|
+
if (!tableName) {
|
|
287
|
+
throw new Error("tableName is required for alterTable.");
|
|
288
|
+
}
|
|
289
|
+
if (!schema) {
|
|
290
|
+
throw new Error("schema is required for alterTable.");
|
|
291
|
+
}
|
|
292
|
+
if (!ifNotExists || ifNotExists.length === 0) {
|
|
293
|
+
this.logger.debug("No columns specified to add in alterTable, skipping.");
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
} catch (validationError) {
|
|
298
297
|
throw new error.MastraError(
|
|
299
298
|
{
|
|
300
|
-
id: "
|
|
299
|
+
id: storage.createStorageErrorId("LANCE", "ALTER_TABLE", "INVALID_ARGS"),
|
|
301
300
|
domain: error.ErrorDomain.STORAGE,
|
|
302
|
-
category: error.ErrorCategory.
|
|
303
|
-
|
|
301
|
+
category: error.ErrorCategory.USER,
|
|
302
|
+
text: validationError.message,
|
|
303
|
+
details: { tableName }
|
|
304
304
|
},
|
|
305
|
-
|
|
305
|
+
validationError
|
|
306
306
|
);
|
|
307
307
|
}
|
|
308
|
-
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
309
|
-
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
310
308
|
try {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
const
|
|
323
|
-
|
|
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)) {
|
|
309
|
+
const table = await this.client.openTable(tableName);
|
|
310
|
+
const currentSchema = await table.schema();
|
|
311
|
+
const existingFields = new Set(currentSchema.fields.map((f) => f.name));
|
|
312
|
+
const typeMap = {
|
|
313
|
+
text: "string",
|
|
314
|
+
integer: "int",
|
|
315
|
+
bigint: "bigint",
|
|
316
|
+
timestamp: "timestamp",
|
|
317
|
+
jsonb: "string",
|
|
318
|
+
uuid: "string"
|
|
319
|
+
};
|
|
320
|
+
const columnsToAdd = ifNotExists.filter((col) => schema[col] && !existingFields.has(col)).map((col) => {
|
|
321
|
+
const colDef = schema[col];
|
|
354
322
|
return {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
page,
|
|
358
|
-
perPage: perPageForResponse,
|
|
359
|
-
hasMore: false
|
|
323
|
+
name: col,
|
|
324
|
+
valueSql: colDef?.nullable ? `cast(NULL as ${typeMap[colDef.type ?? "text"]})` : `cast(${this.getDefaultValue(colDef?.type ?? "text")} as ${typeMap[colDef?.type ?? "text"]})`
|
|
360
325
|
};
|
|
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
326
|
});
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return {
|
|
399
|
-
messages: finalMessages,
|
|
400
|
-
total,
|
|
401
|
-
page,
|
|
402
|
-
perPage: perPageForResponse,
|
|
403
|
-
hasMore
|
|
404
|
-
};
|
|
327
|
+
if (columnsToAdd.length > 0) {
|
|
328
|
+
await table.addColumns(columnsToAdd);
|
|
329
|
+
this.logger?.info?.(`Added columns [${columnsToAdd.map((c) => c.name).join(", ")}] to table ${tableName}`);
|
|
330
|
+
}
|
|
405
331
|
} catch (error$1) {
|
|
406
|
-
|
|
332
|
+
throw new error.MastraError(
|
|
407
333
|
{
|
|
408
|
-
id: "
|
|
334
|
+
id: storage.createStorageErrorId("LANCE", "ALTER_TABLE", "FAILED"),
|
|
409
335
|
domain: error.ErrorDomain.STORAGE,
|
|
410
336
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
411
|
-
details: {
|
|
412
|
-
threadId,
|
|
413
|
-
resourceId: resourceId ?? ""
|
|
414
|
-
}
|
|
337
|
+
details: { tableName }
|
|
415
338
|
},
|
|
416
339
|
error$1
|
|
417
340
|
);
|
|
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
341
|
}
|
|
428
342
|
}
|
|
429
|
-
async
|
|
343
|
+
async clearTable({ tableName }) {
|
|
430
344
|
try {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
return { messages: [] };
|
|
434
|
-
}
|
|
435
|
-
const threadId = messages[0]?.threadId;
|
|
436
|
-
if (!threadId) {
|
|
437
|
-
throw new Error("Thread ID is required");
|
|
345
|
+
if (!this.client) {
|
|
346
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
438
347
|
}
|
|
439
|
-
|
|
440
|
-
|
|
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
|
-
}
|
|
348
|
+
if (!tableName) {
|
|
349
|
+
throw new Error("tableName is required for clearTable.");
|
|
452
350
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
await
|
|
468
|
-
const list = new agent.MessageList().add(messages, "memory");
|
|
469
|
-
return { messages: list.get.all.db() };
|
|
351
|
+
} catch (validationError) {
|
|
352
|
+
throw new error.MastraError(
|
|
353
|
+
{
|
|
354
|
+
id: storage.createStorageErrorId("LANCE", "CLEAR_TABLE", "INVALID_ARGS"),
|
|
355
|
+
domain: error.ErrorDomain.STORAGE,
|
|
356
|
+
category: error.ErrorCategory.USER,
|
|
357
|
+
text: validationError.message,
|
|
358
|
+
details: { tableName }
|
|
359
|
+
},
|
|
360
|
+
validationError
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
try {
|
|
364
|
+
const table = await this.client.openTable(tableName);
|
|
365
|
+
await table.delete("1=1");
|
|
470
366
|
} catch (error$1) {
|
|
471
367
|
throw new error.MastraError(
|
|
472
368
|
{
|
|
473
|
-
id: "
|
|
369
|
+
id: storage.createStorageErrorId("LANCE", "CLEAR_TABLE", "FAILED"),
|
|
474
370
|
domain: error.ErrorDomain.STORAGE,
|
|
475
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
371
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
372
|
+
details: { tableName }
|
|
476
373
|
},
|
|
477
374
|
error$1
|
|
478
375
|
);
|
|
479
376
|
}
|
|
480
377
|
}
|
|
481
|
-
async
|
|
378
|
+
async insert({ tableName, record }) {
|
|
482
379
|
try {
|
|
483
|
-
|
|
484
|
-
|
|
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
|
-
);
|
|
380
|
+
if (!this.client) {
|
|
381
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
495
382
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}
|
|
511
|
-
|
|
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)
|
|
383
|
+
if (!tableName) {
|
|
384
|
+
throw new Error("tableName is required for insert.");
|
|
385
|
+
}
|
|
386
|
+
if (!record || Object.keys(record).length === 0) {
|
|
387
|
+
throw new Error("record is required and cannot be empty for insert.");
|
|
388
|
+
}
|
|
389
|
+
} catch (validationError) {
|
|
390
|
+
throw new error.MastraError(
|
|
391
|
+
{
|
|
392
|
+
id: storage.createStorageErrorId("LANCE", "INSERT", "INVALID_ARGS"),
|
|
393
|
+
domain: error.ErrorDomain.STORAGE,
|
|
394
|
+
category: error.ErrorCategory.USER,
|
|
395
|
+
text: validationError.message,
|
|
396
|
+
details: { tableName }
|
|
397
|
+
},
|
|
398
|
+
validationError
|
|
517
399
|
);
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
const table = await this.client.openTable(tableName);
|
|
403
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
404
|
+
const processedRecord = { ...record };
|
|
405
|
+
for (const key in processedRecord) {
|
|
406
|
+
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
407
|
+
this.logger.debug("Converting object to JSON string: ", processedRecord[key]);
|
|
408
|
+
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([processedRecord]);
|
|
525
412
|
} catch (error$1) {
|
|
526
413
|
throw new error.MastraError(
|
|
527
414
|
{
|
|
528
|
-
id: "
|
|
415
|
+
id: storage.createStorageErrorId("LANCE", "INSERT", "FAILED"),
|
|
529
416
|
domain: error.ErrorDomain.STORAGE,
|
|
530
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
417
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
418
|
+
details: { tableName }
|
|
531
419
|
},
|
|
532
420
|
error$1
|
|
533
421
|
);
|
|
534
422
|
}
|
|
535
423
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
}
|
|
424
|
+
async batchInsert({ tableName, records }) {
|
|
425
|
+
try {
|
|
426
|
+
if (!this.client) {
|
|
427
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
567
428
|
}
|
|
568
|
-
|
|
569
|
-
|
|
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);
|
|
429
|
+
if (!tableName) {
|
|
430
|
+
throw new Error("tableName is required for batchInsert.");
|
|
577
431
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
})
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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
|
-
};
|
|
602
|
-
}
|
|
603
|
-
async updateMessages(args) {
|
|
604
|
-
const { messages } = args;
|
|
605
|
-
this.logger.debug("Updating messages", { count: messages.length });
|
|
606
|
-
if (!messages.length) {
|
|
607
|
-
return [];
|
|
432
|
+
if (!records || records.length === 0) {
|
|
433
|
+
throw new Error("records array is required and cannot be empty for batchInsert.");
|
|
434
|
+
}
|
|
435
|
+
} catch (validationError) {
|
|
436
|
+
throw new error.MastraError(
|
|
437
|
+
{
|
|
438
|
+
id: storage.createStorageErrorId("LANCE", "BATCH_INSERT", "INVALID_ARGS"),
|
|
439
|
+
domain: error.ErrorDomain.STORAGE,
|
|
440
|
+
category: error.ErrorCategory.USER,
|
|
441
|
+
text: validationError.message,
|
|
442
|
+
details: { tableName }
|
|
443
|
+
},
|
|
444
|
+
validationError
|
|
445
|
+
);
|
|
608
446
|
}
|
|
609
|
-
const updatedMessages = [];
|
|
610
|
-
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
611
447
|
try {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
continue;
|
|
618
|
-
|
|
619
|
-
|
|
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;
|
|
448
|
+
const table = await this.client.openTable(tableName);
|
|
449
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
450
|
+
const processedRecords = records.map((record) => {
|
|
451
|
+
const processedRecord = { ...record };
|
|
452
|
+
for (const key in processedRecord) {
|
|
453
|
+
if (processedRecord[key] == null) continue;
|
|
454
|
+
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
455
|
+
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
644
456
|
}
|
|
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
457
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
tableName: storage.TABLE_THREADS,
|
|
656
|
-
record: { id: threadId, updatedAt: Date.now() }
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
return updatedMessages;
|
|
458
|
+
return processedRecord;
|
|
459
|
+
});
|
|
460
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(processedRecords);
|
|
660
461
|
} catch (error$1) {
|
|
661
462
|
throw new error.MastraError(
|
|
662
463
|
{
|
|
663
|
-
id: "
|
|
464
|
+
id: storage.createStorageErrorId("LANCE", "BATCH_INSERT", "FAILED"),
|
|
664
465
|
domain: error.ErrorDomain.STORAGE,
|
|
665
466
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
666
|
-
details: {
|
|
467
|
+
details: { tableName }
|
|
667
468
|
},
|
|
668
469
|
error$1
|
|
669
470
|
);
|
|
670
471
|
}
|
|
671
472
|
}
|
|
672
|
-
async
|
|
473
|
+
async load({ tableName, keys }) {
|
|
673
474
|
try {
|
|
674
|
-
|
|
675
|
-
|
|
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();
|
|
695
|
-
}
|
|
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();
|
|
475
|
+
if (!this.client) {
|
|
476
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
711
477
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
workingMemory = void 0;
|
|
715
|
-
} else if (workingMemory === "") {
|
|
716
|
-
workingMemory = "";
|
|
717
|
-
} else if (typeof workingMemory === "object") {
|
|
718
|
-
workingMemory = JSON.stringify(workingMemory);
|
|
478
|
+
if (!tableName) {
|
|
479
|
+
throw new Error("tableName is required for load.");
|
|
719
480
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
metadata = void 0;
|
|
723
|
-
} else if (typeof metadata === "string") {
|
|
724
|
-
try {
|
|
725
|
-
metadata = JSON.parse(metadata);
|
|
726
|
-
} catch {
|
|
727
|
-
metadata = metadata;
|
|
728
|
-
}
|
|
481
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
482
|
+
throw new Error("keys are required and cannot be empty for load.");
|
|
729
483
|
}
|
|
730
|
-
|
|
731
|
-
...resource,
|
|
732
|
-
createdAt,
|
|
733
|
-
updatedAt,
|
|
734
|
-
workingMemory,
|
|
735
|
-
metadata
|
|
736
|
-
};
|
|
737
|
-
} catch (error$1) {
|
|
484
|
+
} catch (validationError) {
|
|
738
485
|
throw new error.MastraError(
|
|
739
486
|
{
|
|
740
|
-
id: "
|
|
487
|
+
id: storage.createStorageErrorId("LANCE", "LOAD", "INVALID_ARGS"),
|
|
741
488
|
domain: error.ErrorDomain.STORAGE,
|
|
742
|
-
category: error.ErrorCategory.
|
|
489
|
+
category: error.ErrorCategory.USER,
|
|
490
|
+
text: validationError.message,
|
|
491
|
+
details: { tableName }
|
|
743
492
|
},
|
|
744
|
-
|
|
493
|
+
validationError
|
|
745
494
|
);
|
|
746
495
|
}
|
|
747
|
-
}
|
|
748
|
-
async saveResource({ resource }) {
|
|
749
496
|
try {
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
497
|
+
const table = await this.client.openTable(tableName);
|
|
498
|
+
const tableSchema = await getTableSchema({ tableName, client: this.client });
|
|
499
|
+
const query = table.query();
|
|
500
|
+
if (Object.keys(keys).length > 0) {
|
|
501
|
+
validateKeyTypes(keys, tableSchema);
|
|
502
|
+
const filterConditions = Object.entries(keys).map(([key, value]) => {
|
|
503
|
+
const isCamelCase = /^[a-z][a-zA-Z]*$/.test(key) && /[A-Z]/.test(key);
|
|
504
|
+
const quotedKey = isCamelCase ? `\`${key}\`` : key;
|
|
505
|
+
if (typeof value === "string") {
|
|
506
|
+
return `${quotedKey} = '${value}'`;
|
|
507
|
+
} else if (value === null) {
|
|
508
|
+
return `${quotedKey} IS NULL`;
|
|
509
|
+
} else {
|
|
510
|
+
return `${quotedKey} = ${value}`;
|
|
511
|
+
}
|
|
512
|
+
}).join(" AND ");
|
|
513
|
+
this.logger.debug("where clause generated: " + filterConditions);
|
|
514
|
+
query.where(filterConditions);
|
|
515
|
+
}
|
|
516
|
+
const result = await query.limit(1).toArray();
|
|
517
|
+
if (result.length === 0) {
|
|
518
|
+
this.logger.debug("No record found");
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
return processResultWithTypeConversion(result[0], tableSchema);
|
|
761
522
|
} catch (error$1) {
|
|
523
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
762
524
|
throw new error.MastraError(
|
|
763
525
|
{
|
|
764
|
-
id: "
|
|
526
|
+
id: storage.createStorageErrorId("LANCE", "LOAD", "FAILED"),
|
|
765
527
|
domain: error.ErrorDomain.STORAGE,
|
|
766
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
528
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
529
|
+
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
767
530
|
},
|
|
768
531
|
error$1
|
|
769
532
|
);
|
|
770
533
|
}
|
|
771
534
|
}
|
|
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
535
|
};
|
|
829
|
-
|
|
536
|
+
|
|
537
|
+
// src/storage/domains/memory/index.ts
|
|
538
|
+
var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
830
539
|
client;
|
|
831
|
-
|
|
540
|
+
#db;
|
|
541
|
+
constructor(config) {
|
|
832
542
|
super();
|
|
543
|
+
const client = resolveLanceConfig(config);
|
|
833
544
|
this.client = client;
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
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
|
-
}
|
|
857
|
-
translateSchema(schema) {
|
|
858
|
-
const fields = Object.entries(schema).map(([name, column]) => {
|
|
859
|
-
let arrowType;
|
|
860
|
-
switch (column.type.toLowerCase()) {
|
|
861
|
-
case "text":
|
|
862
|
-
case "uuid":
|
|
863
|
-
arrowType = new apacheArrow.Utf8();
|
|
864
|
-
break;
|
|
865
|
-
case "int":
|
|
866
|
-
case "integer":
|
|
867
|
-
arrowType = new apacheArrow.Int32();
|
|
868
|
-
break;
|
|
869
|
-
case "bigint":
|
|
870
|
-
arrowType = new apacheArrow.Float64();
|
|
871
|
-
break;
|
|
872
|
-
case "float":
|
|
873
|
-
arrowType = new apacheArrow.Float32();
|
|
874
|
-
break;
|
|
875
|
-
case "jsonb":
|
|
876
|
-
case "json":
|
|
877
|
-
arrowType = new apacheArrow.Utf8();
|
|
878
|
-
break;
|
|
879
|
-
case "binary":
|
|
880
|
-
arrowType = new apacheArrow.Binary();
|
|
881
|
-
break;
|
|
882
|
-
case "timestamp":
|
|
883
|
-
arrowType = new apacheArrow.Float64();
|
|
884
|
-
break;
|
|
885
|
-
default:
|
|
886
|
-
arrowType = new apacheArrow.Utf8();
|
|
887
|
-
}
|
|
888
|
-
return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
|
|
545
|
+
this.#db = new LanceDB({ client });
|
|
546
|
+
}
|
|
547
|
+
async init() {
|
|
548
|
+
await this.#db.createTable({ tableName: storage.TABLE_THREADS, schema: storage.TABLE_SCHEMAS[storage.TABLE_THREADS] });
|
|
549
|
+
await this.#db.createTable({ tableName: storage.TABLE_MESSAGES, schema: storage.TABLE_SCHEMAS[storage.TABLE_MESSAGES] });
|
|
550
|
+
await this.#db.createTable({ tableName: storage.TABLE_RESOURCES, schema: storage.TABLE_SCHEMAS[storage.TABLE_RESOURCES] });
|
|
551
|
+
await this.#db.alterTable({
|
|
552
|
+
tableName: storage.TABLE_MESSAGES,
|
|
553
|
+
schema: storage.TABLE_SCHEMAS[storage.TABLE_MESSAGES],
|
|
554
|
+
ifNotExists: ["resourceId"]
|
|
889
555
|
});
|
|
890
|
-
return new apacheArrow.Schema(fields);
|
|
891
556
|
}
|
|
892
|
-
async
|
|
893
|
-
tableName
|
|
894
|
-
|
|
895
|
-
|
|
557
|
+
async dangerouslyClearAll() {
|
|
558
|
+
await this.#db.clearTable({ tableName: storage.TABLE_THREADS });
|
|
559
|
+
await this.#db.clearTable({ tableName: storage.TABLE_MESSAGES });
|
|
560
|
+
await this.#db.clearTable({ tableName: storage.TABLE_RESOURCES });
|
|
561
|
+
}
|
|
562
|
+
async deleteMessages(messageIds) {
|
|
563
|
+
if (!messageIds || messageIds.length === 0) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
this.logger.debug("Deleting messages", { count: messageIds.length });
|
|
896
567
|
try {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
568
|
+
const threadIds = /* @__PURE__ */ new Set();
|
|
569
|
+
for (const messageId of messageIds) {
|
|
570
|
+
const message = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id: messageId } });
|
|
571
|
+
if (message?.thread_id) {
|
|
572
|
+
threadIds.add(message.thread_id);
|
|
573
|
+
}
|
|
902
574
|
}
|
|
903
|
-
|
|
904
|
-
|
|
575
|
+
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
576
|
+
const idConditions = messageIds.map((id) => `id = '${this.escapeSql(id)}'`).join(" OR ");
|
|
577
|
+
await messagesTable.delete(idConditions);
|
|
578
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
579
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
580
|
+
for (const threadId of threadIds) {
|
|
581
|
+
const thread = await this.getThreadById({ threadId });
|
|
582
|
+
if (thread) {
|
|
583
|
+
const record = {
|
|
584
|
+
id: threadId,
|
|
585
|
+
resourceId: thread.resourceId,
|
|
586
|
+
title: thread.title,
|
|
587
|
+
metadata: JSON.stringify(thread.metadata),
|
|
588
|
+
createdAt: new Date(thread.createdAt).getTime(),
|
|
589
|
+
updatedAt: now
|
|
590
|
+
};
|
|
591
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
592
|
+
}
|
|
905
593
|
}
|
|
906
594
|
} catch (error$1) {
|
|
907
595
|
throw new error.MastraError(
|
|
908
596
|
{
|
|
909
|
-
id: "
|
|
597
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_MESSAGES", "FAILED"),
|
|
910
598
|
domain: error.ErrorDomain.STORAGE,
|
|
911
|
-
category: error.ErrorCategory.
|
|
912
|
-
details: {
|
|
599
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
600
|
+
details: { count: messageIds.length }
|
|
913
601
|
},
|
|
914
602
|
error$1
|
|
915
603
|
);
|
|
916
604
|
}
|
|
605
|
+
}
|
|
606
|
+
// Utility to escape single quotes in SQL strings
|
|
607
|
+
escapeSql(str) {
|
|
608
|
+
return str.replace(/'/g, "''");
|
|
609
|
+
}
|
|
610
|
+
async getThreadById({ threadId }) {
|
|
917
611
|
try {
|
|
918
|
-
const
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
if (error$1.message?.includes("already exists")) {
|
|
922
|
-
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
923
|
-
return;
|
|
612
|
+
const thread = await this.#db.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
613
|
+
if (!thread) {
|
|
614
|
+
return null;
|
|
924
615
|
}
|
|
616
|
+
return {
|
|
617
|
+
...thread,
|
|
618
|
+
createdAt: new Date(thread.createdAt),
|
|
619
|
+
updatedAt: new Date(thread.updatedAt)
|
|
620
|
+
};
|
|
621
|
+
} catch (error$1) {
|
|
925
622
|
throw new error.MastraError(
|
|
926
623
|
{
|
|
927
|
-
id: "
|
|
624
|
+
id: storage.createStorageErrorId("LANCE", "GET_THREAD_BY_ID", "FAILED"),
|
|
928
625
|
domain: error.ErrorDomain.STORAGE,
|
|
929
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
930
|
-
details: { tableName }
|
|
626
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
931
627
|
},
|
|
932
628
|
error$1
|
|
933
629
|
);
|
|
934
630
|
}
|
|
935
631
|
}
|
|
936
|
-
|
|
632
|
+
/**
|
|
633
|
+
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
634
|
+
* @param thread - The thread to save
|
|
635
|
+
* @returns The saved thread
|
|
636
|
+
*/
|
|
637
|
+
async saveThread({ thread }) {
|
|
937
638
|
try {
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}
|
|
944
|
-
} catch (validationError) {
|
|
639
|
+
const record = { ...thread, metadata: JSON.stringify(thread.metadata) };
|
|
640
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
641
|
+
await table.add([record], { mode: "append" });
|
|
642
|
+
return thread;
|
|
643
|
+
} catch (error$1) {
|
|
945
644
|
throw new error.MastraError(
|
|
946
645
|
{
|
|
947
|
-
id: "
|
|
646
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_THREAD", "FAILED"),
|
|
948
647
|
domain: error.ErrorDomain.STORAGE,
|
|
949
|
-
category: error.ErrorCategory.
|
|
950
|
-
text: validationError.message,
|
|
951
|
-
details: { tableName }
|
|
648
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
952
649
|
},
|
|
953
|
-
|
|
650
|
+
error$1
|
|
954
651
|
);
|
|
955
652
|
}
|
|
653
|
+
}
|
|
654
|
+
async updateThread({
|
|
655
|
+
id,
|
|
656
|
+
title,
|
|
657
|
+
metadata
|
|
658
|
+
}) {
|
|
659
|
+
const maxRetries = 5;
|
|
660
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
661
|
+
try {
|
|
662
|
+
const current = await this.getThreadById({ threadId: id });
|
|
663
|
+
if (!current) {
|
|
664
|
+
throw new Error(`Thread with id ${id} not found`);
|
|
665
|
+
}
|
|
666
|
+
const mergedMetadata = { ...current.metadata, ...metadata };
|
|
667
|
+
const record = {
|
|
668
|
+
id,
|
|
669
|
+
title,
|
|
670
|
+
metadata: JSON.stringify(mergedMetadata),
|
|
671
|
+
updatedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
672
|
+
};
|
|
673
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
674
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
675
|
+
const updatedThread = await this.getThreadById({ threadId: id });
|
|
676
|
+
if (!updatedThread) {
|
|
677
|
+
throw new Error(`Failed to retrieve updated thread ${id}`);
|
|
678
|
+
}
|
|
679
|
+
return updatedThread;
|
|
680
|
+
} catch (error$1) {
|
|
681
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
682
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
683
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
throw new error.MastraError(
|
|
687
|
+
{
|
|
688
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_THREAD", "FAILED"),
|
|
689
|
+
domain: error.ErrorDomain.STORAGE,
|
|
690
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
691
|
+
},
|
|
692
|
+
error$1
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
throw new error.MastraError(
|
|
697
|
+
{
|
|
698
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_THREAD", "FAILED"),
|
|
699
|
+
domain: error.ErrorDomain.STORAGE,
|
|
700
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
701
|
+
},
|
|
702
|
+
new Error("All retries exhausted")
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
async deleteThread({ threadId }) {
|
|
956
706
|
try {
|
|
957
|
-
await this.client.
|
|
707
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
708
|
+
await table.delete(`id = '${threadId}'`);
|
|
709
|
+
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
710
|
+
await messagesTable.delete(`thread_id = '${threadId}'`);
|
|
958
711
|
} 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
|
-
}
|
|
963
712
|
throw new error.MastraError(
|
|
964
713
|
{
|
|
965
|
-
id: "
|
|
714
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_THREAD", "FAILED"),
|
|
966
715
|
domain: error.ErrorDomain.STORAGE,
|
|
967
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
968
|
-
details: { tableName }
|
|
716
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
969
717
|
},
|
|
970
718
|
error$1
|
|
971
719
|
);
|
|
972
720
|
}
|
|
973
721
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
this.logger.debug("No columns specified to add in alterTable, skipping.");
|
|
991
|
-
return;
|
|
992
|
-
}
|
|
993
|
-
} catch (validationError) {
|
|
994
|
-
throw new error.MastraError(
|
|
995
|
-
{
|
|
996
|
-
id: "STORAGE_LANCE_STORAGE_ALTER_TABLE_INVALID_ARGS",
|
|
997
|
-
domain: error.ErrorDomain.STORAGE,
|
|
998
|
-
category: error.ErrorCategory.USER,
|
|
999
|
-
text: validationError.message,
|
|
1000
|
-
details: { tableName }
|
|
1001
|
-
},
|
|
1002
|
-
validationError
|
|
1003
|
-
);
|
|
1004
|
-
}
|
|
722
|
+
normalizeMessage(message) {
|
|
723
|
+
const { thread_id, ...rest } = message;
|
|
724
|
+
return {
|
|
725
|
+
...rest,
|
|
726
|
+
threadId: thread_id,
|
|
727
|
+
content: typeof message.content === "string" ? (() => {
|
|
728
|
+
try {
|
|
729
|
+
return JSON.parse(message.content);
|
|
730
|
+
} catch {
|
|
731
|
+
return message.content;
|
|
732
|
+
}
|
|
733
|
+
})() : message.content
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
async listMessagesById({ messageIds }) {
|
|
737
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
1005
738
|
try {
|
|
1006
|
-
const table = await this.client.openTable(
|
|
1007
|
-
const
|
|
1008
|
-
const
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
const colDef = schema[col];
|
|
1019
|
-
return {
|
|
1020
|
-
name: col,
|
|
1021
|
-
valueSql: colDef?.nullable ? `cast(NULL as ${typeMap[colDef.type ?? "text"]})` : `cast(${this.getDefaultValue(colDef?.type ?? "text")} as ${typeMap[colDef?.type ?? "text"]})`
|
|
1022
|
-
};
|
|
1023
|
-
});
|
|
1024
|
-
if (columnsToAdd.length > 0) {
|
|
1025
|
-
await table.addColumns(columnsToAdd);
|
|
1026
|
-
this.logger?.info?.(`Added columns [${columnsToAdd.map((c) => c.name).join(", ")}] to table ${tableName}`);
|
|
1027
|
-
}
|
|
739
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
740
|
+
const quotedIds = messageIds.map((id) => `'${id}'`).join(", ");
|
|
741
|
+
const allRecords = await table.query().where(`id IN (${quotedIds})`).toArray();
|
|
742
|
+
const messages = processResultWithTypeConversion(
|
|
743
|
+
allRecords,
|
|
744
|
+
await getTableSchema({ tableName: storage.TABLE_MESSAGES, client: this.client })
|
|
745
|
+
);
|
|
746
|
+
const list = new agent.MessageList().add(
|
|
747
|
+
messages.map(this.normalizeMessage),
|
|
748
|
+
"memory"
|
|
749
|
+
);
|
|
750
|
+
return { messages: list.get.all.db() };
|
|
1028
751
|
} catch (error$1) {
|
|
1029
752
|
throw new error.MastraError(
|
|
1030
753
|
{
|
|
1031
|
-
id: "
|
|
754
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES_BY_ID", "FAILED"),
|
|
1032
755
|
domain: error.ErrorDomain.STORAGE,
|
|
1033
756
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1034
|
-
details: {
|
|
757
|
+
details: {
|
|
758
|
+
messageIds: JSON.stringify(messageIds)
|
|
759
|
+
}
|
|
1035
760
|
},
|
|
1036
761
|
error$1
|
|
1037
762
|
);
|
|
1038
763
|
}
|
|
1039
764
|
}
|
|
1040
|
-
async
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
}
|
|
1045
|
-
if (!tableName) {
|
|
1046
|
-
throw new Error("tableName is required for clearTable.");
|
|
1047
|
-
}
|
|
1048
|
-
} catch (validationError) {
|
|
765
|
+
async listMessages(args) {
|
|
766
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
767
|
+
const threadIds = Array.isArray(threadId) ? threadId : [threadId];
|
|
768
|
+
if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
|
|
1049
769
|
throw new error.MastraError(
|
|
1050
770
|
{
|
|
1051
|
-
id: "
|
|
771
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "INVALID_THREAD_ID"),
|
|
1052
772
|
domain: error.ErrorDomain.STORAGE,
|
|
1053
|
-
category: error.ErrorCategory.
|
|
1054
|
-
|
|
1055
|
-
details: { tableName }
|
|
773
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
774
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
1056
775
|
},
|
|
1057
|
-
|
|
776
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
1058
777
|
);
|
|
1059
778
|
}
|
|
779
|
+
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
780
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
1060
781
|
try {
|
|
1061
|
-
|
|
1062
|
-
|
|
782
|
+
if (page < 0) {
|
|
783
|
+
throw new error.MastraError(
|
|
784
|
+
{
|
|
785
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "INVALID_PAGE"),
|
|
786
|
+
domain: error.ErrorDomain.STORAGE,
|
|
787
|
+
category: error.ErrorCategory.USER,
|
|
788
|
+
details: { page }
|
|
789
|
+
},
|
|
790
|
+
new Error("page must be >= 0")
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
794
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
795
|
+
const threadCondition = threadIds.length === 1 ? `thread_id = '${this.escapeSql(threadIds[0])}'` : `thread_id IN (${threadIds.map((t) => `'${this.escapeSql(t)}'`).join(", ")})`;
|
|
796
|
+
const conditions = [threadCondition];
|
|
797
|
+
if (resourceId) {
|
|
798
|
+
conditions.push(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
799
|
+
}
|
|
800
|
+
if (filter?.dateRange?.start) {
|
|
801
|
+
const startTime = filter.dateRange.start instanceof Date ? filter.dateRange.start.getTime() : new Date(filter.dateRange.start).getTime();
|
|
802
|
+
conditions.push(`\`createdAt\` >= ${startTime}`);
|
|
803
|
+
}
|
|
804
|
+
if (filter?.dateRange?.end) {
|
|
805
|
+
const endTime = filter.dateRange.end instanceof Date ? filter.dateRange.end.getTime() : new Date(filter.dateRange.end).getTime();
|
|
806
|
+
conditions.push(`\`createdAt\` <= ${endTime}`);
|
|
807
|
+
}
|
|
808
|
+
const whereClause = conditions.join(" AND ");
|
|
809
|
+
const total = await table.countRows(whereClause);
|
|
810
|
+
const query = table.query().where(whereClause);
|
|
811
|
+
let allRecords = await query.toArray();
|
|
812
|
+
allRecords.sort((a, b) => {
|
|
813
|
+
const aValue = field === "createdAt" ? a.createdAt : a[field];
|
|
814
|
+
const bValue = field === "createdAt" ? b.createdAt : b[field];
|
|
815
|
+
if (aValue == null && bValue == null) return 0;
|
|
816
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
817
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
818
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
819
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
820
|
+
}
|
|
821
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
822
|
+
});
|
|
823
|
+
const paginatedRecords = allRecords.slice(offset, offset + perPage);
|
|
824
|
+
const messages = paginatedRecords.map((row) => this.normalizeMessage(row));
|
|
825
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
826
|
+
return {
|
|
827
|
+
messages: [],
|
|
828
|
+
total: 0,
|
|
829
|
+
page,
|
|
830
|
+
perPage: perPageForResponse,
|
|
831
|
+
hasMore: false
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
835
|
+
if (include && include.length > 0) {
|
|
836
|
+
const threadIds2 = [...new Set(include.map((item) => item.threadId || threadId))];
|
|
837
|
+
const allThreadMessages = [];
|
|
838
|
+
for (const tid of threadIds2) {
|
|
839
|
+
const threadQuery = table.query().where(`thread_id = '${tid}'`);
|
|
840
|
+
let threadRecords = await threadQuery.toArray();
|
|
841
|
+
allThreadMessages.push(...threadRecords);
|
|
842
|
+
}
|
|
843
|
+
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
844
|
+
const contextMessages = this.processMessagesWithContext(allThreadMessages, include);
|
|
845
|
+
const includedMessages = contextMessages.map((row) => this.normalizeMessage(row));
|
|
846
|
+
for (const includeMsg of includedMessages) {
|
|
847
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
848
|
+
messages.push(includeMsg);
|
|
849
|
+
messageIds.add(includeMsg.id);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
854
|
+
let finalMessages = list.get.all.db();
|
|
855
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
856
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
857
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
858
|
+
if (aValue == null && bValue == null) return 0;
|
|
859
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
860
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
861
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
862
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
863
|
+
}
|
|
864
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
865
|
+
});
|
|
866
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
867
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
868
|
+
const fetchedAll = perPageInput === false || allThreadMessagesReturned;
|
|
869
|
+
const hasMore = !fetchedAll && offset + perPage < total;
|
|
870
|
+
return {
|
|
871
|
+
messages: finalMessages,
|
|
872
|
+
total,
|
|
873
|
+
page,
|
|
874
|
+
perPage: perPageForResponse,
|
|
875
|
+
hasMore
|
|
876
|
+
};
|
|
1063
877
|
} catch (error$1) {
|
|
1064
|
-
|
|
878
|
+
const mastraError = new error.MastraError(
|
|
1065
879
|
{
|
|
1066
|
-
id: "
|
|
880
|
+
id: storage.createStorageErrorId("LANCE", "LIST_MESSAGES", "FAILED"),
|
|
1067
881
|
domain: error.ErrorDomain.STORAGE,
|
|
1068
882
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1069
|
-
details: {
|
|
883
|
+
details: {
|
|
884
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
885
|
+
resourceId: resourceId ?? ""
|
|
886
|
+
}
|
|
1070
887
|
},
|
|
1071
888
|
error$1
|
|
1072
889
|
);
|
|
890
|
+
this.logger?.error?.(mastraError.toString());
|
|
891
|
+
this.logger?.trackException?.(mastraError);
|
|
892
|
+
return {
|
|
893
|
+
messages: [],
|
|
894
|
+
total: 0,
|
|
895
|
+
page,
|
|
896
|
+
perPage: perPageForResponse,
|
|
897
|
+
hasMore: false
|
|
898
|
+
};
|
|
1073
899
|
}
|
|
1074
900
|
}
|
|
1075
|
-
async
|
|
901
|
+
async saveMessages(args) {
|
|
1076
902
|
try {
|
|
1077
|
-
|
|
1078
|
-
|
|
903
|
+
const { messages } = args;
|
|
904
|
+
if (messages.length === 0) {
|
|
905
|
+
return { messages: [] };
|
|
1079
906
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
907
|
+
const threadId = messages[0]?.threadId;
|
|
908
|
+
if (!threadId) {
|
|
909
|
+
throw new Error("Thread ID is required");
|
|
1082
910
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
911
|
+
for (const message of messages) {
|
|
912
|
+
if (!message.id) {
|
|
913
|
+
throw new Error("Message ID is required");
|
|
914
|
+
}
|
|
915
|
+
if (!message.threadId) {
|
|
916
|
+
throw new Error("Thread ID is required for all messages");
|
|
917
|
+
}
|
|
918
|
+
if (message.resourceId === null || message.resourceId === void 0) {
|
|
919
|
+
throw new Error("Resource ID cannot be null or undefined");
|
|
920
|
+
}
|
|
921
|
+
if (!message.content) {
|
|
922
|
+
throw new Error("Message content is required");
|
|
923
|
+
}
|
|
1085
924
|
}
|
|
1086
|
-
|
|
925
|
+
const transformedMessages = messages.map((message) => {
|
|
926
|
+
const { threadId: threadId2, type, ...rest } = message;
|
|
927
|
+
return {
|
|
928
|
+
...rest,
|
|
929
|
+
thread_id: threadId2,
|
|
930
|
+
type: type ?? "v2",
|
|
931
|
+
content: JSON.stringify(message.content)
|
|
932
|
+
};
|
|
933
|
+
});
|
|
934
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
935
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
936
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
937
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
938
|
+
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
939
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
940
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
941
|
+
return { messages: list.get.all.db() };
|
|
942
|
+
} catch (error$1) {
|
|
1087
943
|
throw new error.MastraError(
|
|
1088
944
|
{
|
|
1089
|
-
id: "
|
|
945
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_MESSAGES", "FAILED"),
|
|
1090
946
|
domain: error.ErrorDomain.STORAGE,
|
|
1091
|
-
category: error.ErrorCategory.
|
|
1092
|
-
text: validationError.message,
|
|
1093
|
-
details: { tableName }
|
|
947
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1094
948
|
},
|
|
1095
|
-
|
|
949
|
+
error$1
|
|
1096
950
|
);
|
|
1097
951
|
}
|
|
952
|
+
}
|
|
953
|
+
async listThreadsByResourceId(args) {
|
|
1098
954
|
try {
|
|
1099
|
-
const
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
955
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
956
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
957
|
+
if (page < 0) {
|
|
958
|
+
throw new error.MastraError(
|
|
959
|
+
{
|
|
960
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
961
|
+
domain: error.ErrorDomain.STORAGE,
|
|
962
|
+
category: error.ErrorCategory.USER,
|
|
963
|
+
details: { page }
|
|
964
|
+
},
|
|
965
|
+
new Error("page must be >= 0")
|
|
966
|
+
);
|
|
1107
967
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
968
|
+
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
969
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
970
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
971
|
+
const total = await table.countRows(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
972
|
+
const query = table.query().where(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
973
|
+
const records = await query.toArray();
|
|
974
|
+
records.sort((a, b) => {
|
|
975
|
+
const aValue = ["createdAt", "updatedAt"].includes(field) ? new Date(a[field]).getTime() : a[field];
|
|
976
|
+
const bValue = ["createdAt", "updatedAt"].includes(field) ? new Date(b[field]).getTime() : b[field];
|
|
977
|
+
if (aValue == null && bValue == null) return 0;
|
|
978
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
979
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
980
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
981
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
982
|
+
}
|
|
983
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
984
|
+
});
|
|
985
|
+
const paginatedRecords = records.slice(offset, offset + perPage);
|
|
986
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
987
|
+
const threads = paginatedRecords.map(
|
|
988
|
+
(record) => processResultWithTypeConversion(record, schema)
|
|
989
|
+
);
|
|
990
|
+
return {
|
|
991
|
+
threads,
|
|
992
|
+
total,
|
|
993
|
+
page,
|
|
994
|
+
perPage: perPageForResponse,
|
|
995
|
+
hasMore: offset + perPage < total
|
|
996
|
+
};
|
|
1110
997
|
} catch (error$1) {
|
|
1111
998
|
throw new error.MastraError(
|
|
1112
999
|
{
|
|
1113
|
-
id: "
|
|
1000
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
|
|
1114
1001
|
domain: error.ErrorDomain.STORAGE,
|
|
1115
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1116
|
-
details: { tableName }
|
|
1002
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1117
1003
|
},
|
|
1118
1004
|
error$1
|
|
1119
1005
|
);
|
|
1120
1006
|
}
|
|
1121
1007
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1008
|
+
/**
|
|
1009
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
1010
|
+
* @param records - The sorted array of records to process
|
|
1011
|
+
* @param include - The array of include specifications with context parameters
|
|
1012
|
+
* @returns The processed array with context messages included
|
|
1013
|
+
*/
|
|
1014
|
+
processMessagesWithContext(records, include) {
|
|
1015
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
1016
|
+
if (messagesWithContext.length === 0) {
|
|
1017
|
+
return records;
|
|
1018
|
+
}
|
|
1019
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
1020
|
+
records.forEach((message, index) => {
|
|
1021
|
+
messageIndexMap.set(message.id, index);
|
|
1022
|
+
});
|
|
1023
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
1024
|
+
for (const item of messagesWithContext) {
|
|
1025
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
1026
|
+
if (messageIndex !== void 0) {
|
|
1027
|
+
if (item.withPreviousMessages) {
|
|
1028
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
1029
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
1030
|
+
additionalIndices.add(i);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
if (item.withNextMessages) {
|
|
1034
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
1035
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
1036
|
+
additionalIndices.add(i);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1129
1039
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1040
|
+
}
|
|
1041
|
+
if (additionalIndices.size === 0) {
|
|
1042
|
+
return records;
|
|
1043
|
+
}
|
|
1044
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
1045
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
1046
|
+
records.forEach((record, index) => {
|
|
1047
|
+
if (originalMatchIds.has(record.id)) {
|
|
1048
|
+
allIndices.add(index);
|
|
1132
1049
|
}
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1050
|
+
});
|
|
1051
|
+
additionalIndices.forEach((index) => {
|
|
1052
|
+
allIndices.add(index);
|
|
1053
|
+
});
|
|
1054
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Parse message data from LanceDB record format to MastraDBMessage format
|
|
1058
|
+
*/
|
|
1059
|
+
parseMessageData(data) {
|
|
1060
|
+
const { thread_id, ...rest } = data;
|
|
1061
|
+
return {
|
|
1062
|
+
...rest,
|
|
1063
|
+
threadId: thread_id,
|
|
1064
|
+
content: typeof data.content === "string" ? (() => {
|
|
1065
|
+
try {
|
|
1066
|
+
return JSON.parse(data.content);
|
|
1067
|
+
} catch {
|
|
1068
|
+
return data.content;
|
|
1069
|
+
}
|
|
1070
|
+
})() : data.content,
|
|
1071
|
+
createdAt: new Date(data.createdAt),
|
|
1072
|
+
updatedAt: new Date(data.updatedAt)
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
async updateMessages(args) {
|
|
1076
|
+
const { messages } = args;
|
|
1077
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
1078
|
+
if (!messages.length) {
|
|
1079
|
+
return [];
|
|
1144
1080
|
}
|
|
1081
|
+
const updatedMessages = [];
|
|
1082
|
+
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
1145
1083
|
try {
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1084
|
+
for (const updateData of messages) {
|
|
1085
|
+
const { id, ...updates } = updateData;
|
|
1086
|
+
const existingMessage = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
1087
|
+
if (!existingMessage) {
|
|
1088
|
+
this.logger.warn("Message not found for update", { id });
|
|
1089
|
+
continue;
|
|
1090
|
+
}
|
|
1091
|
+
const existingMsg = this.parseMessageData(existingMessage);
|
|
1092
|
+
const originalThreadId = existingMsg.threadId;
|
|
1093
|
+
affectedThreadIds.add(originalThreadId);
|
|
1094
|
+
const updatePayload = {};
|
|
1095
|
+
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
1096
|
+
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
1097
|
+
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
1098
|
+
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
1099
|
+
updatePayload.thread_id = updates.threadId;
|
|
1100
|
+
affectedThreadIds.add(updates.threadId);
|
|
1101
|
+
}
|
|
1102
|
+
if (updates.content) {
|
|
1103
|
+
const existingContent = existingMsg.content;
|
|
1104
|
+
let newContent = { ...existingContent };
|
|
1105
|
+
if (updates.content.metadata !== void 0) {
|
|
1106
|
+
newContent.metadata = {
|
|
1107
|
+
...existingContent.metadata || {},
|
|
1108
|
+
...updates.content.metadata || {}
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
if (updates.content.content !== void 0) {
|
|
1112
|
+
newContent.content = updates.content.content;
|
|
1154
1113
|
}
|
|
1114
|
+
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
1115
|
+
newContent.parts = updates.content.parts;
|
|
1116
|
+
}
|
|
1117
|
+
updatePayload.content = JSON.stringify(newContent);
|
|
1155
1118
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1119
|
+
await this.#db.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
1120
|
+
const updatedMessage = await this.#db.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
1121
|
+
if (updatedMessage) {
|
|
1122
|
+
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
for (const threadId of affectedThreadIds) {
|
|
1126
|
+
await this.#db.insert({
|
|
1127
|
+
tableName: storage.TABLE_THREADS,
|
|
1128
|
+
record: { id: threadId, updatedAt: Date.now() }
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
return updatedMessages;
|
|
1159
1132
|
} catch (error$1) {
|
|
1160
1133
|
throw new error.MastraError(
|
|
1161
1134
|
{
|
|
1162
|
-
id: "
|
|
1135
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_MESSAGES", "FAILED"),
|
|
1163
1136
|
domain: error.ErrorDomain.STORAGE,
|
|
1164
1137
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1165
|
-
details: {
|
|
1138
|
+
details: { count: messages.length }
|
|
1166
1139
|
},
|
|
1167
1140
|
error$1
|
|
1168
1141
|
);
|
|
1169
1142
|
}
|
|
1170
1143
|
}
|
|
1171
|
-
async
|
|
1144
|
+
async getResourceById({ resourceId }) {
|
|
1172
1145
|
try {
|
|
1173
|
-
|
|
1174
|
-
|
|
1146
|
+
const resource = await this.#db.load({ tableName: storage.TABLE_RESOURCES, keys: { id: resourceId } });
|
|
1147
|
+
if (!resource) {
|
|
1148
|
+
return null;
|
|
1175
1149
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1150
|
+
let createdAt;
|
|
1151
|
+
let updatedAt;
|
|
1152
|
+
try {
|
|
1153
|
+
if (resource.createdAt instanceof Date) {
|
|
1154
|
+
createdAt = resource.createdAt;
|
|
1155
|
+
} else if (typeof resource.createdAt === "string") {
|
|
1156
|
+
createdAt = new Date(resource.createdAt);
|
|
1157
|
+
} else if (typeof resource.createdAt === "number") {
|
|
1158
|
+
createdAt = new Date(resource.createdAt);
|
|
1159
|
+
} else {
|
|
1160
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1161
|
+
}
|
|
1162
|
+
if (isNaN(createdAt.getTime())) {
|
|
1163
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1164
|
+
}
|
|
1165
|
+
} catch {
|
|
1166
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1178
1167
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1168
|
+
try {
|
|
1169
|
+
if (resource.updatedAt instanceof Date) {
|
|
1170
|
+
updatedAt = resource.updatedAt;
|
|
1171
|
+
} else if (typeof resource.updatedAt === "string") {
|
|
1172
|
+
updatedAt = new Date(resource.updatedAt);
|
|
1173
|
+
} else if (typeof resource.updatedAt === "number") {
|
|
1174
|
+
updatedAt = new Date(resource.updatedAt);
|
|
1175
|
+
} else {
|
|
1176
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1177
|
+
}
|
|
1178
|
+
if (isNaN(updatedAt.getTime())) {
|
|
1179
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1180
|
+
}
|
|
1181
|
+
} catch {
|
|
1182
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1181
1183
|
}
|
|
1182
|
-
|
|
1184
|
+
let workingMemory = resource.workingMemory;
|
|
1185
|
+
if (workingMemory === null || workingMemory === void 0) {
|
|
1186
|
+
workingMemory = void 0;
|
|
1187
|
+
} else if (workingMemory === "") {
|
|
1188
|
+
workingMemory = "";
|
|
1189
|
+
} else if (typeof workingMemory === "object") {
|
|
1190
|
+
workingMemory = JSON.stringify(workingMemory);
|
|
1191
|
+
}
|
|
1192
|
+
let metadata = resource.metadata;
|
|
1193
|
+
if (metadata === "" || metadata === null || metadata === void 0) {
|
|
1194
|
+
metadata = void 0;
|
|
1195
|
+
} else if (typeof metadata === "string") {
|
|
1196
|
+
try {
|
|
1197
|
+
metadata = JSON.parse(metadata);
|
|
1198
|
+
} catch {
|
|
1199
|
+
metadata = metadata;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return {
|
|
1203
|
+
...resource,
|
|
1204
|
+
createdAt,
|
|
1205
|
+
updatedAt,
|
|
1206
|
+
workingMemory,
|
|
1207
|
+
metadata
|
|
1208
|
+
};
|
|
1209
|
+
} catch (error$1) {
|
|
1183
1210
|
throw new error.MastraError(
|
|
1184
1211
|
{
|
|
1185
|
-
id: "
|
|
1212
|
+
id: storage.createStorageErrorId("LANCE", "GET_RESOURCE_BY_ID", "FAILED"),
|
|
1186
1213
|
domain: error.ErrorDomain.STORAGE,
|
|
1187
|
-
category: error.ErrorCategory.
|
|
1188
|
-
text: validationError.message,
|
|
1189
|
-
details: { tableName }
|
|
1214
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1190
1215
|
},
|
|
1191
|
-
|
|
1216
|
+
error$1
|
|
1192
1217
|
);
|
|
1193
1218
|
}
|
|
1219
|
+
}
|
|
1220
|
+
async saveResource({ resource }) {
|
|
1194
1221
|
try {
|
|
1195
|
-
const
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
return `${quotedKey} IS NULL`;
|
|
1207
|
-
} else {
|
|
1208
|
-
return `${quotedKey} = ${value}`;
|
|
1209
|
-
}
|
|
1210
|
-
}).join(" AND ");
|
|
1211
|
-
this.logger.debug("where clause generated: " + filterConditions);
|
|
1212
|
-
query.where(filterConditions);
|
|
1213
|
-
}
|
|
1214
|
-
const result = await query.limit(1).toArray();
|
|
1215
|
-
if (result.length === 0) {
|
|
1216
|
-
this.logger.debug("No record found");
|
|
1217
|
-
return null;
|
|
1218
|
-
}
|
|
1219
|
-
return processResultWithTypeConversion(result[0], tableSchema);
|
|
1222
|
+
const record = {
|
|
1223
|
+
...resource,
|
|
1224
|
+
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
1225
|
+
createdAt: resource.createdAt.getTime(),
|
|
1226
|
+
// Store as timestamp (milliseconds)
|
|
1227
|
+
updatedAt: resource.updatedAt.getTime()
|
|
1228
|
+
// Store as timestamp (milliseconds)
|
|
1229
|
+
};
|
|
1230
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
1231
|
+
await table.add([record], { mode: "append" });
|
|
1232
|
+
return resource;
|
|
1220
1233
|
} catch (error$1) {
|
|
1221
|
-
if (error$1 instanceof error.MastraError) throw error$1;
|
|
1222
1234
|
throw new error.MastraError(
|
|
1223
1235
|
{
|
|
1224
|
-
id: "
|
|
1236
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_RESOURCE", "FAILED"),
|
|
1225
1237
|
domain: error.ErrorDomain.STORAGE,
|
|
1226
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1227
|
-
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
1238
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1228
1239
|
},
|
|
1229
1240
|
error$1
|
|
1230
1241
|
);
|
|
1231
1242
|
}
|
|
1232
1243
|
}
|
|
1244
|
+
async updateResource({
|
|
1245
|
+
resourceId,
|
|
1246
|
+
workingMemory,
|
|
1247
|
+
metadata
|
|
1248
|
+
}) {
|
|
1249
|
+
const maxRetries = 3;
|
|
1250
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1251
|
+
try {
|
|
1252
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
1253
|
+
if (!existingResource) {
|
|
1254
|
+
const newResource = {
|
|
1255
|
+
id: resourceId,
|
|
1256
|
+
workingMemory,
|
|
1257
|
+
metadata: metadata || {},
|
|
1258
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1259
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1260
|
+
};
|
|
1261
|
+
return this.saveResource({ resource: newResource });
|
|
1262
|
+
}
|
|
1263
|
+
const updatedResource = {
|
|
1264
|
+
...existingResource,
|
|
1265
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
1266
|
+
metadata: {
|
|
1267
|
+
...existingResource.metadata,
|
|
1268
|
+
...metadata
|
|
1269
|
+
},
|
|
1270
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1271
|
+
};
|
|
1272
|
+
const record = {
|
|
1273
|
+
id: resourceId,
|
|
1274
|
+
workingMemory: updatedResource.workingMemory || "",
|
|
1275
|
+
metadata: updatedResource.metadata ? JSON.stringify(updatedResource.metadata) : "",
|
|
1276
|
+
updatedAt: updatedResource.updatedAt.getTime()
|
|
1277
|
+
// Store as timestamp (milliseconds)
|
|
1278
|
+
};
|
|
1279
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
1280
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1281
|
+
return updatedResource;
|
|
1282
|
+
} catch (error$1) {
|
|
1283
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
1284
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
1285
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1286
|
+
continue;
|
|
1287
|
+
}
|
|
1288
|
+
throw new error.MastraError(
|
|
1289
|
+
{
|
|
1290
|
+
id: storage.createStorageErrorId("LANCE", "UPDATE_RESOURCE", "FAILED"),
|
|
1291
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1292
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1293
|
+
},
|
|
1294
|
+
error$1
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
throw new Error("Unexpected end of retry loop");
|
|
1299
|
+
}
|
|
1233
1300
|
};
|
|
1234
1301
|
var StoreScoresLance = class extends storage.ScoresStorage {
|
|
1235
1302
|
client;
|
|
1236
|
-
|
|
1303
|
+
#db;
|
|
1304
|
+
constructor(config) {
|
|
1237
1305
|
super();
|
|
1306
|
+
const client = resolveLanceConfig(config);
|
|
1238
1307
|
this.client = client;
|
|
1308
|
+
this.#db = new LanceDB({ client });
|
|
1309
|
+
}
|
|
1310
|
+
async init() {
|
|
1311
|
+
await this.#db.createTable({ tableName: storage.TABLE_SCORERS, schema: storage.SCORERS_SCHEMA });
|
|
1312
|
+
await this.#db.alterTable({
|
|
1313
|
+
tableName: storage.TABLE_SCORERS,
|
|
1314
|
+
schema: storage.SCORERS_SCHEMA,
|
|
1315
|
+
ifNotExists: ["spanId", "requestContext"]
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
async dangerouslyClearAll() {
|
|
1319
|
+
await this.#db.clearTable({ tableName: storage.TABLE_SCORERS });
|
|
1239
1320
|
}
|
|
1240
1321
|
async saveScore(score) {
|
|
1241
1322
|
let validatedScore;
|
|
@@ -1244,39 +1325,47 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1244
1325
|
} catch (error$1) {
|
|
1245
1326
|
throw new error.MastraError(
|
|
1246
1327
|
{
|
|
1247
|
-
id: "
|
|
1328
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_SCORE", "VALIDATION_FAILED"),
|
|
1248
1329
|
text: "Failed to save score in LanceStorage",
|
|
1249
1330
|
domain: error.ErrorDomain.STORAGE,
|
|
1250
|
-
category: error.ErrorCategory.
|
|
1331
|
+
category: error.ErrorCategory.USER,
|
|
1332
|
+
details: {
|
|
1333
|
+
scorer: score.scorer?.id ?? "unknown",
|
|
1334
|
+
entityId: score.entityId ?? "unknown",
|
|
1335
|
+
entityType: score.entityType ?? "unknown",
|
|
1336
|
+
traceId: score.traceId ?? "",
|
|
1337
|
+
spanId: score.spanId ?? ""
|
|
1338
|
+
}
|
|
1251
1339
|
},
|
|
1252
1340
|
error$1
|
|
1253
1341
|
);
|
|
1254
1342
|
}
|
|
1343
|
+
const id = crypto.randomUUID();
|
|
1344
|
+
const now = /* @__PURE__ */ new Date();
|
|
1255
1345
|
try {
|
|
1256
|
-
const id = crypto.randomUUID();
|
|
1257
1346
|
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1258
1347
|
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1259
1348
|
const allowedFields = new Set(schema.fields.map((f) => f.name));
|
|
1260
1349
|
const filteredScore = {};
|
|
1261
|
-
Object.keys(validatedScore)
|
|
1350
|
+
for (const key of Object.keys(validatedScore)) {
|
|
1262
1351
|
if (allowedFields.has(key)) {
|
|
1263
|
-
filteredScore[key] =
|
|
1352
|
+
filteredScore[key] = validatedScore[key];
|
|
1264
1353
|
}
|
|
1265
|
-
}
|
|
1354
|
+
}
|
|
1266
1355
|
for (const key in filteredScore) {
|
|
1267
1356
|
if (filteredScore[key] !== null && typeof filteredScore[key] === "object" && !(filteredScore[key] instanceof Date)) {
|
|
1268
1357
|
filteredScore[key] = JSON.stringify(filteredScore[key]);
|
|
1269
1358
|
}
|
|
1270
1359
|
}
|
|
1271
|
-
filteredScore.createdAt = /* @__PURE__ */ new Date();
|
|
1272
|
-
filteredScore.updatedAt = /* @__PURE__ */ new Date();
|
|
1273
1360
|
filteredScore.id = id;
|
|
1361
|
+
filteredScore.createdAt = now;
|
|
1362
|
+
filteredScore.updatedAt = now;
|
|
1274
1363
|
await table.add([filteredScore], { mode: "append" });
|
|
1275
|
-
return { score };
|
|
1364
|
+
return { score: { ...validatedScore, id, createdAt: now, updatedAt: now } };
|
|
1276
1365
|
} catch (error$1) {
|
|
1277
1366
|
throw new error.MastraError(
|
|
1278
1367
|
{
|
|
1279
|
-
id: "
|
|
1368
|
+
id: storage.createStorageErrorId("LANCE", "SAVE_SCORE", "FAILED"),
|
|
1280
1369
|
text: "Failed to save score in LanceStorage",
|
|
1281
1370
|
domain: error.ErrorDomain.STORAGE,
|
|
1282
1371
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1296,7 +1385,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1296
1385
|
} catch (error$1) {
|
|
1297
1386
|
throw new error.MastraError(
|
|
1298
1387
|
{
|
|
1299
|
-
id: "
|
|
1388
|
+
id: storage.createStorageErrorId("LANCE", "GET_SCORE_BY_ID", "FAILED"),
|
|
1300
1389
|
text: "Failed to get score by id in LanceStorage",
|
|
1301
1390
|
domain: error.ErrorDomain.STORAGE,
|
|
1302
1391
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1306,15 +1395,21 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1306
1395
|
);
|
|
1307
1396
|
}
|
|
1308
1397
|
}
|
|
1398
|
+
/**
|
|
1399
|
+
* LanceDB-specific score row transformation.
|
|
1400
|
+
*
|
|
1401
|
+
* Note: This implementation does NOT use coreTransformScoreRow because:
|
|
1402
|
+
* 1. LanceDB stores schema information in the table itself (requires async fetch)
|
|
1403
|
+
* 2. Uses processResultWithTypeConversion utility for LanceDB-specific type handling
|
|
1404
|
+
*/
|
|
1309
1405
|
async transformScoreRow(row) {
|
|
1310
1406
|
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1311
1407
|
const transformed = processResultWithTypeConversion(row, schema);
|
|
1312
|
-
|
|
1408
|
+
return {
|
|
1313
1409
|
...transformed,
|
|
1314
1410
|
createdAt: row.createdAt,
|
|
1315
1411
|
updatedAt: row.updatedAt
|
|
1316
1412
|
};
|
|
1317
|
-
return result;
|
|
1318
1413
|
}
|
|
1319
1414
|
async listScoresByScorerId({
|
|
1320
1415
|
scorerId,
|
|
@@ -1369,7 +1464,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1369
1464
|
} catch (error$1) {
|
|
1370
1465
|
throw new error.MastraError(
|
|
1371
1466
|
{
|
|
1372
|
-
id: "
|
|
1467
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
|
|
1373
1468
|
text: "Failed to get scores by scorerId in LanceStorage",
|
|
1374
1469
|
domain: error.ErrorDomain.STORAGE,
|
|
1375
1470
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1410,7 +1505,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1410
1505
|
} catch (error$1) {
|
|
1411
1506
|
throw new error.MastraError(
|
|
1412
1507
|
{
|
|
1413
|
-
id: "
|
|
1508
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_RUN_ID", "FAILED"),
|
|
1414
1509
|
text: "Failed to get scores by runId in LanceStorage",
|
|
1415
1510
|
domain: error.ErrorDomain.STORAGE,
|
|
1416
1511
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1452,7 +1547,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1452
1547
|
} catch (error$1) {
|
|
1453
1548
|
throw new error.MastraError(
|
|
1454
1549
|
{
|
|
1455
|
-
id: "
|
|
1550
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
|
|
1456
1551
|
text: "Failed to get scores by entityId and entityType in LanceStorage",
|
|
1457
1552
|
domain: error.ErrorDomain.STORAGE,
|
|
1458
1553
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1494,7 +1589,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1494
1589
|
} catch (error$1) {
|
|
1495
1590
|
throw new error.MastraError(
|
|
1496
1591
|
{
|
|
1497
|
-
id: "
|
|
1592
|
+
id: storage.createStorageErrorId("LANCE", "LIST_SCORES_BY_SPAN", "FAILED"),
|
|
1498
1593
|
text: "Failed to get scores by traceId and spanId in LanceStorage",
|
|
1499
1594
|
domain: error.ErrorDomain.STORAGE,
|
|
1500
1595
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
@@ -1505,6 +1600,9 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1505
1600
|
}
|
|
1506
1601
|
}
|
|
1507
1602
|
};
|
|
1603
|
+
function escapeSql(str) {
|
|
1604
|
+
return str.replace(/'/g, "''");
|
|
1605
|
+
}
|
|
1508
1606
|
function parseWorkflowRun(row) {
|
|
1509
1607
|
let parsedSnapshot = row.snapshot;
|
|
1510
1608
|
if (typeof parsedSnapshot === "string") {
|
|
@@ -1525,42 +1623,88 @@ function parseWorkflowRun(row) {
|
|
|
1525
1623
|
}
|
|
1526
1624
|
var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
1527
1625
|
client;
|
|
1528
|
-
|
|
1626
|
+
#db;
|
|
1627
|
+
constructor(config) {
|
|
1529
1628
|
super();
|
|
1629
|
+
const client = resolveLanceConfig(config);
|
|
1530
1630
|
this.client = client;
|
|
1631
|
+
this.#db = new LanceDB({ client });
|
|
1632
|
+
}
|
|
1633
|
+
async init() {
|
|
1634
|
+
const schema = storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT];
|
|
1635
|
+
await this.#db.createTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT, schema });
|
|
1636
|
+
await this.#db.alterTable({
|
|
1637
|
+
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
1638
|
+
schema,
|
|
1639
|
+
ifNotExists: ["resourceId"]
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
async dangerouslyClearAll() {
|
|
1643
|
+
await this.#db.clearTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT });
|
|
1531
1644
|
}
|
|
1532
|
-
updateWorkflowResults({
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1645
|
+
async updateWorkflowResults({
|
|
1646
|
+
workflowName,
|
|
1647
|
+
runId,
|
|
1648
|
+
stepId,
|
|
1649
|
+
result,
|
|
1650
|
+
requestContext
|
|
1538
1651
|
}) {
|
|
1539
|
-
|
|
1652
|
+
let snapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
|
|
1653
|
+
if (!snapshot) {
|
|
1654
|
+
snapshot = {
|
|
1655
|
+
context: {},
|
|
1656
|
+
activePaths: [],
|
|
1657
|
+
timestamp: Date.now(),
|
|
1658
|
+
suspendedPaths: {},
|
|
1659
|
+
activeStepsPath: {},
|
|
1660
|
+
resumeLabels: {},
|
|
1661
|
+
serializedStepGraph: [],
|
|
1662
|
+
status: "pending",
|
|
1663
|
+
value: {},
|
|
1664
|
+
waitingPaths: {},
|
|
1665
|
+
runId,
|
|
1666
|
+
requestContext: {}
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
snapshot.context[stepId] = result;
|
|
1670
|
+
snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
|
|
1671
|
+
await this.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
1672
|
+
return snapshot.context;
|
|
1540
1673
|
}
|
|
1541
|
-
updateWorkflowState({
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1674
|
+
async updateWorkflowState({
|
|
1675
|
+
workflowName,
|
|
1676
|
+
runId,
|
|
1677
|
+
opts
|
|
1545
1678
|
}) {
|
|
1546
|
-
|
|
1679
|
+
const snapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
|
|
1680
|
+
if (!snapshot) {
|
|
1681
|
+
return void 0;
|
|
1682
|
+
}
|
|
1683
|
+
if (!snapshot.context) {
|
|
1684
|
+
throw new Error(`Snapshot not found for runId ${runId}`);
|
|
1685
|
+
}
|
|
1686
|
+
const updatedSnapshot = { ...snapshot, ...opts };
|
|
1687
|
+
await this.persistWorkflowSnapshot({ workflowName, runId, snapshot: updatedSnapshot });
|
|
1688
|
+
return updatedSnapshot;
|
|
1547
1689
|
}
|
|
1548
1690
|
async persistWorkflowSnapshot({
|
|
1549
1691
|
workflowName,
|
|
1550
1692
|
runId,
|
|
1551
1693
|
resourceId,
|
|
1552
|
-
snapshot
|
|
1694
|
+
snapshot,
|
|
1695
|
+
createdAt,
|
|
1696
|
+
updatedAt
|
|
1553
1697
|
}) {
|
|
1554
1698
|
try {
|
|
1555
1699
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1556
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1700
|
+
const query = table.query().where(`workflow_name = '${escapeSql(workflowName)}' AND run_id = '${escapeSql(runId)}'`);
|
|
1557
1701
|
const records = await query.toArray();
|
|
1558
|
-
let
|
|
1559
|
-
const now = Date.now();
|
|
1702
|
+
let createdAtValue;
|
|
1703
|
+
const now = createdAt?.getTime() ?? Date.now();
|
|
1560
1704
|
if (records.length > 0) {
|
|
1561
|
-
|
|
1705
|
+
createdAtValue = records[0].createdAt ?? now;
|
|
1562
1706
|
} else {
|
|
1563
|
-
|
|
1707
|
+
createdAtValue = now;
|
|
1564
1708
|
}
|
|
1565
1709
|
const { status, value, ...rest } = snapshot;
|
|
1566
1710
|
const record = {
|
|
@@ -1569,14 +1713,14 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1569
1713
|
resourceId,
|
|
1570
1714
|
snapshot: JSON.stringify({ status, value, ...rest }),
|
|
1571
1715
|
// this is to ensure status is always just before value, for when querying the db by status
|
|
1572
|
-
createdAt,
|
|
1573
|
-
updatedAt: now
|
|
1716
|
+
createdAt: createdAtValue,
|
|
1717
|
+
updatedAt: updatedAt ?? now
|
|
1574
1718
|
};
|
|
1575
1719
|
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1576
1720
|
} catch (error$1) {
|
|
1577
1721
|
throw new error.MastraError(
|
|
1578
1722
|
{
|
|
1579
|
-
id: "
|
|
1723
|
+
id: storage.createStorageErrorId("LANCE", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1580
1724
|
domain: error.ErrorDomain.STORAGE,
|
|
1581
1725
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1582
1726
|
details: { workflowName, runId }
|
|
@@ -1591,13 +1735,13 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1591
1735
|
}) {
|
|
1592
1736
|
try {
|
|
1593
1737
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1594
|
-
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1738
|
+
const query = table.query().where(`workflow_name = '${escapeSql(workflowName)}' AND run_id = '${escapeSql(runId)}'`);
|
|
1595
1739
|
const records = await query.toArray();
|
|
1596
1740
|
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
1597
1741
|
} catch (error$1) {
|
|
1598
1742
|
throw new error.MastraError(
|
|
1599
1743
|
{
|
|
1600
|
-
id: "
|
|
1744
|
+
id: storage.createStorageErrorId("LANCE", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
1601
1745
|
domain: error.ErrorDomain.STORAGE,
|
|
1602
1746
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1603
1747
|
details: { workflowName, runId }
|
|
@@ -1609,9 +1753,9 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1609
1753
|
async getWorkflowRunById(args) {
|
|
1610
1754
|
try {
|
|
1611
1755
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1612
|
-
let whereClause = `run_id = '${args.runId}'`;
|
|
1756
|
+
let whereClause = `run_id = '${escapeSql(args.runId)}'`;
|
|
1613
1757
|
if (args.workflowName) {
|
|
1614
|
-
whereClause += ` AND workflow_name = '${args.workflowName}'`;
|
|
1758
|
+
whereClause += ` AND workflow_name = '${escapeSql(args.workflowName)}'`;
|
|
1615
1759
|
}
|
|
1616
1760
|
const query = table.query().where(whereClause);
|
|
1617
1761
|
const records = await query.toArray();
|
|
@@ -1621,7 +1765,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1621
1765
|
} catch (error$1) {
|
|
1622
1766
|
throw new error.MastraError(
|
|
1623
1767
|
{
|
|
1624
|
-
id: "
|
|
1768
|
+
id: storage.createStorageErrorId("LANCE", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1625
1769
|
domain: error.ErrorDomain.STORAGE,
|
|
1626
1770
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1627
1771
|
details: { runId: args.runId, workflowName: args.workflowName ?? "" }
|
|
@@ -1630,20 +1774,37 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1630
1774
|
);
|
|
1631
1775
|
}
|
|
1632
1776
|
}
|
|
1777
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
1778
|
+
try {
|
|
1779
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1780
|
+
const whereClause = `run_id = '${escapeSql(runId)}' AND workflow_name = '${escapeSql(workflowName)}'`;
|
|
1781
|
+
await table.delete(whereClause);
|
|
1782
|
+
} catch (error$1) {
|
|
1783
|
+
throw new error.MastraError(
|
|
1784
|
+
{
|
|
1785
|
+
id: storage.createStorageErrorId("LANCE", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
1786
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1787
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1788
|
+
details: { runId, workflowName }
|
|
1789
|
+
},
|
|
1790
|
+
error$1
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1633
1794
|
async listWorkflowRuns(args) {
|
|
1634
1795
|
try {
|
|
1635
1796
|
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1636
1797
|
let query = table.query();
|
|
1637
1798
|
const conditions = [];
|
|
1638
1799
|
if (args?.workflowName) {
|
|
1639
|
-
conditions.push(`workflow_name = '${args.workflowName
|
|
1800
|
+
conditions.push(`workflow_name = '${escapeSql(args.workflowName)}'`);
|
|
1640
1801
|
}
|
|
1641
1802
|
if (args?.status) {
|
|
1642
1803
|
const escapedStatus = args.status.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
1643
1804
|
conditions.push(`\`snapshot\` LIKE '%"status":"${escapedStatus}","value"%'`);
|
|
1644
1805
|
}
|
|
1645
1806
|
if (args?.resourceId) {
|
|
1646
|
-
conditions.push(`\`resourceId\` = '${args.resourceId}'`);
|
|
1807
|
+
conditions.push(`\`resourceId\` = '${escapeSql(args.resourceId)}'`);
|
|
1647
1808
|
}
|
|
1648
1809
|
if (args?.fromDate instanceof Date) {
|
|
1649
1810
|
conditions.push(`\`createdAt\` >= ${args.fromDate.getTime()}`);
|
|
@@ -1663,7 +1824,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1663
1824
|
if (args.page < 0 || !Number.isInteger(args.page)) {
|
|
1664
1825
|
throw new error.MastraError(
|
|
1665
1826
|
{
|
|
1666
|
-
id: "
|
|
1827
|
+
id: storage.createStorageErrorId("LANCE", "LIST_WORKFLOW_RUNS", "INVALID_PAGINATION"),
|
|
1667
1828
|
domain: error.ErrorDomain.STORAGE,
|
|
1668
1829
|
category: error.ErrorCategory.USER,
|
|
1669
1830
|
details: { page: args.page, perPage: args.perPage }
|
|
@@ -1683,7 +1844,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1683
1844
|
} catch (error$1) {
|
|
1684
1845
|
throw new error.MastraError(
|
|
1685
1846
|
{
|
|
1686
|
-
id: "
|
|
1847
|
+
id: storage.createStorageErrorId("LANCE", "LIST_WORKFLOW_RUNS", "FAILED"),
|
|
1687
1848
|
domain: error.ErrorDomain.STORAGE,
|
|
1688
1849
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1689
1850
|
details: { resourceId: args?.resourceId ?? "", workflowName: args?.workflowName ?? "" }
|
|
@@ -1703,7 +1864,8 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1703
1864
|
* @param id The unique identifier for this storage instance
|
|
1704
1865
|
* @param name The name for this storage instance
|
|
1705
1866
|
* @param uri The URI to connect to LanceDB
|
|
1706
|
-
* @param
|
|
1867
|
+
* @param connectionOptions connection options for LanceDB
|
|
1868
|
+
* @param storageOptions storage options including disableInit
|
|
1707
1869
|
*
|
|
1708
1870
|
* Usage:
|
|
1709
1871
|
*
|
|
@@ -1721,27 +1883,30 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1721
1883
|
* ```ts
|
|
1722
1884
|
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 's3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1723
1885
|
* ```
|
|
1886
|
+
*
|
|
1887
|
+
* Disable auto-init for runtime (after CI/CD has run migrations)
|
|
1888
|
+
* ```ts
|
|
1889
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db', undefined, { disableInit: true });
|
|
1890
|
+
* ```
|
|
1724
1891
|
*/
|
|
1725
|
-
static async create(id, name, uri,
|
|
1726
|
-
const instance = new _LanceStorage(id, name);
|
|
1892
|
+
static async create(id, name, uri, connectionOptions, storageOptions) {
|
|
1893
|
+
const instance = new _LanceStorage(id, name, storageOptions?.disableInit);
|
|
1727
1894
|
try {
|
|
1728
|
-
instance.lanceClient = await lancedb.connect(uri,
|
|
1729
|
-
const operations = new StoreOperationsLance({ client: instance.lanceClient });
|
|
1895
|
+
instance.lanceClient = await lancedb.connect(uri, connectionOptions);
|
|
1730
1896
|
instance.stores = {
|
|
1731
|
-
operations: new StoreOperationsLance({ client: instance.lanceClient }),
|
|
1732
1897
|
workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
|
|
1733
1898
|
scores: new StoreScoresLance({ client: instance.lanceClient }),
|
|
1734
|
-
memory: new StoreMemoryLance({ client: instance.lanceClient
|
|
1899
|
+
memory: new StoreMemoryLance({ client: instance.lanceClient })
|
|
1735
1900
|
};
|
|
1736
1901
|
return instance;
|
|
1737
1902
|
} catch (e) {
|
|
1738
1903
|
throw new error.MastraError(
|
|
1739
1904
|
{
|
|
1740
|
-
id: "
|
|
1905
|
+
id: storage.createStorageErrorId("LANCE", "CONNECT", "FAILED"),
|
|
1741
1906
|
domain: error.ErrorDomain.STORAGE,
|
|
1742
1907
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1743
1908
|
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
1744
|
-
details: { uri, optionsProvided: !!
|
|
1909
|
+
details: { uri, optionsProvided: !!connectionOptions }
|
|
1745
1910
|
},
|
|
1746
1911
|
e
|
|
1747
1912
|
);
|
|
@@ -1749,45 +1914,12 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1749
1914
|
}
|
|
1750
1915
|
/**
|
|
1751
1916
|
* @internal
|
|
1752
|
-
* Private constructor to enforce using the create factory method
|
|
1917
|
+
* Private constructor to enforce using the create factory method.
|
|
1918
|
+
* Note: stores is initialized in create() after the lanceClient is connected.
|
|
1753
1919
|
*/
|
|
1754
|
-
constructor(id, name) {
|
|
1755
|
-
super({ id, name });
|
|
1756
|
-
|
|
1757
|
-
this.stores = {
|
|
1758
|
-
operations: new StoreOperationsLance({ client: this.lanceClient }),
|
|
1759
|
-
workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
|
|
1760
|
-
scores: new StoreScoresLance({ client: this.lanceClient }),
|
|
1761
|
-
memory: new StoreMemoryLance({ client: this.lanceClient, operations })
|
|
1762
|
-
};
|
|
1763
|
-
}
|
|
1764
|
-
async createTable({
|
|
1765
|
-
tableName,
|
|
1766
|
-
schema
|
|
1767
|
-
}) {
|
|
1768
|
-
return this.stores.operations.createTable({ tableName, schema });
|
|
1769
|
-
}
|
|
1770
|
-
async dropTable({ tableName }) {
|
|
1771
|
-
return this.stores.operations.dropTable({ tableName });
|
|
1772
|
-
}
|
|
1773
|
-
async alterTable({
|
|
1774
|
-
tableName,
|
|
1775
|
-
schema,
|
|
1776
|
-
ifNotExists
|
|
1777
|
-
}) {
|
|
1778
|
-
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
1779
|
-
}
|
|
1780
|
-
async clearTable({ tableName }) {
|
|
1781
|
-
return this.stores.operations.clearTable({ tableName });
|
|
1782
|
-
}
|
|
1783
|
-
async insert({ tableName, record }) {
|
|
1784
|
-
return this.stores.operations.insert({ tableName, record });
|
|
1785
|
-
}
|
|
1786
|
-
async batchInsert({ tableName, records }) {
|
|
1787
|
-
return this.stores.operations.batchInsert({ tableName, records });
|
|
1788
|
-
}
|
|
1789
|
-
async load({ tableName, keys }) {
|
|
1790
|
-
return this.stores.operations.load({ tableName, keys });
|
|
1920
|
+
constructor(id, name, disableInit) {
|
|
1921
|
+
super({ id, name, disableInit });
|
|
1922
|
+
this.stores = {};
|
|
1791
1923
|
}
|
|
1792
1924
|
async getThreadById({ threadId }) {
|
|
1793
1925
|
return this.stores.memory.getThreadById({ threadId });
|
|
@@ -1810,13 +1942,16 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1810
1942
|
async deleteThread({ threadId }) {
|
|
1811
1943
|
return this.stores.memory.deleteThread({ threadId });
|
|
1812
1944
|
}
|
|
1945
|
+
async deleteMessages(messageIds) {
|
|
1946
|
+
return this.stores.memory.deleteMessages(messageIds);
|
|
1947
|
+
}
|
|
1813
1948
|
get supports() {
|
|
1814
1949
|
return {
|
|
1815
1950
|
selectByIncludeResourceScope: true,
|
|
1816
1951
|
resourceWorkingMemory: true,
|
|
1817
1952
|
hasColumn: true,
|
|
1818
1953
|
createTable: true,
|
|
1819
|
-
deleteMessages:
|
|
1954
|
+
deleteMessages: true,
|
|
1820
1955
|
listScoresBySpan: true
|
|
1821
1956
|
};
|
|
1822
1957
|
}
|
|
@@ -1896,6 +2031,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1896
2031
|
async getWorkflowRunById(args) {
|
|
1897
2032
|
return this.stores.workflows.getWorkflowRunById(args);
|
|
1898
2033
|
}
|
|
2034
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
2035
|
+
return this.stores.workflows.deleteWorkflowRunById({ runId, workflowName });
|
|
2036
|
+
}
|
|
1899
2037
|
async updateWorkflowResults({
|
|
1900
2038
|
workflowName,
|
|
1901
2039
|
runId,
|
|
@@ -1938,8 +2076,8 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1938
2076
|
}) {
|
|
1939
2077
|
return this.stores.scores.listScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
|
|
1940
2078
|
}
|
|
1941
|
-
async saveScore(
|
|
1942
|
-
return this.stores.scores.saveScore(
|
|
2079
|
+
async saveScore(score) {
|
|
2080
|
+
return this.stores.scores.saveScore(score);
|
|
1943
2081
|
}
|
|
1944
2082
|
async listScoresByRunId({
|
|
1945
2083
|
runId,
|
|
@@ -2315,7 +2453,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2315
2453
|
} catch (e) {
|
|
2316
2454
|
throw new error.MastraError(
|
|
2317
2455
|
{
|
|
2318
|
-
id: "
|
|
2456
|
+
id: storage.createVectorErrorId("LANCE", "CONNECT", "FAILED"),
|
|
2319
2457
|
domain: error.ErrorDomain.STORAGE,
|
|
2320
2458
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2321
2459
|
details: { uri }
|
|
@@ -2358,7 +2496,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2358
2496
|
} catch (error$1) {
|
|
2359
2497
|
throw new error.MastraError(
|
|
2360
2498
|
{
|
|
2361
|
-
id: "
|
|
2499
|
+
id: storage.createVectorErrorId("LANCE", "QUERY", "INVALID_ARGS"),
|
|
2362
2500
|
domain: error.ErrorDomain.STORAGE,
|
|
2363
2501
|
category: error.ErrorCategory.USER,
|
|
2364
2502
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2406,7 +2544,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2406
2544
|
} catch (error$1) {
|
|
2407
2545
|
throw new error.MastraError(
|
|
2408
2546
|
{
|
|
2409
|
-
id: "
|
|
2547
|
+
id: storage.createVectorErrorId("LANCE", "QUERY", "FAILED"),
|
|
2410
2548
|
domain: error.ErrorDomain.STORAGE,
|
|
2411
2549
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2412
2550
|
details: { tableName, includeVector, columnsCount: columns?.length, includeAllColumns }
|
|
@@ -2458,7 +2596,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2458
2596
|
} catch (error$1) {
|
|
2459
2597
|
throw new error.MastraError(
|
|
2460
2598
|
{
|
|
2461
|
-
id: "
|
|
2599
|
+
id: storage.createVectorErrorId("LANCE", "UPSERT", "INVALID_ARGS"),
|
|
2462
2600
|
domain: error.ErrorDomain.STORAGE,
|
|
2463
2601
|
category: error.ErrorCategory.USER,
|
|
2464
2602
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2494,7 +2632,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2494
2632
|
} catch (error$1) {
|
|
2495
2633
|
throw new error.MastraError(
|
|
2496
2634
|
{
|
|
2497
|
-
id: "
|
|
2635
|
+
id: storage.createVectorErrorId("LANCE", "UPSERT", "FAILED"),
|
|
2498
2636
|
domain: error.ErrorDomain.STORAGE,
|
|
2499
2637
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2500
2638
|
details: { tableName, vectorCount: vectors.length, metadataCount: metadata.length, idsCount: ids.length }
|
|
@@ -2521,7 +2659,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2521
2659
|
async createTable(tableName, data, options) {
|
|
2522
2660
|
if (!this.lanceClient) {
|
|
2523
2661
|
throw new error.MastraError({
|
|
2524
|
-
id: "
|
|
2662
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_TABLE", "INVALID_ARGS"),
|
|
2525
2663
|
domain: error.ErrorDomain.STORAGE,
|
|
2526
2664
|
category: error.ErrorCategory.USER,
|
|
2527
2665
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2536,7 +2674,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2536
2674
|
} catch (error$1) {
|
|
2537
2675
|
throw new error.MastraError(
|
|
2538
2676
|
{
|
|
2539
|
-
id: "
|
|
2677
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_TABLE", "FAILED"),
|
|
2540
2678
|
domain: error.ErrorDomain.STORAGE,
|
|
2541
2679
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2542
2680
|
details: { tableName }
|
|
@@ -2548,7 +2686,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2548
2686
|
async listTables() {
|
|
2549
2687
|
if (!this.lanceClient) {
|
|
2550
2688
|
throw new error.MastraError({
|
|
2551
|
-
id: "
|
|
2689
|
+
id: storage.createVectorErrorId("LANCE", "LIST_TABLES", "INVALID_ARGS"),
|
|
2552
2690
|
domain: error.ErrorDomain.STORAGE,
|
|
2553
2691
|
category: error.ErrorCategory.USER,
|
|
2554
2692
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2560,7 +2698,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2560
2698
|
} catch (error$1) {
|
|
2561
2699
|
throw new error.MastraError(
|
|
2562
2700
|
{
|
|
2563
|
-
id: "
|
|
2701
|
+
id: storage.createVectorErrorId("LANCE", "LIST_TABLES", "FAILED"),
|
|
2564
2702
|
domain: error.ErrorDomain.STORAGE,
|
|
2565
2703
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2566
2704
|
},
|
|
@@ -2571,7 +2709,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2571
2709
|
async getTableSchema(tableName) {
|
|
2572
2710
|
if (!this.lanceClient) {
|
|
2573
2711
|
throw new error.MastraError({
|
|
2574
|
-
id: "
|
|
2712
|
+
id: storage.createVectorErrorId("LANCE", "GET_TABLE_SCHEMA", "INVALID_ARGS"),
|
|
2575
2713
|
domain: error.ErrorDomain.STORAGE,
|
|
2576
2714
|
category: error.ErrorCategory.USER,
|
|
2577
2715
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2584,7 +2722,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2584
2722
|
} catch (error$1) {
|
|
2585
2723
|
throw new error.MastraError(
|
|
2586
2724
|
{
|
|
2587
|
-
id: "
|
|
2725
|
+
id: storage.createVectorErrorId("LANCE", "GET_TABLE_SCHEMA", "FAILED"),
|
|
2588
2726
|
domain: error.ErrorDomain.STORAGE,
|
|
2589
2727
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2590
2728
|
details: { tableName }
|
|
@@ -2619,7 +2757,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2619
2757
|
} catch (err) {
|
|
2620
2758
|
throw new error.MastraError(
|
|
2621
2759
|
{
|
|
2622
|
-
id: "
|
|
2760
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "INVALID_ARGS"),
|
|
2623
2761
|
domain: error.ErrorDomain.STORAGE,
|
|
2624
2762
|
category: error.ErrorCategory.USER,
|
|
2625
2763
|
details: { tableName: tableName || "", indexName, dimension, metric }
|
|
@@ -2664,7 +2802,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2664
2802
|
} catch (error$1) {
|
|
2665
2803
|
throw new error.MastraError(
|
|
2666
2804
|
{
|
|
2667
|
-
id: "
|
|
2805
|
+
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "FAILED"),
|
|
2668
2806
|
domain: error.ErrorDomain.STORAGE,
|
|
2669
2807
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2670
2808
|
details: { tableName: tableName || "", indexName, dimension }
|
|
@@ -2676,7 +2814,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2676
2814
|
async listIndexes() {
|
|
2677
2815
|
if (!this.lanceClient) {
|
|
2678
2816
|
throw new error.MastraError({
|
|
2679
|
-
id: "
|
|
2817
|
+
id: storage.createVectorErrorId("LANCE", "LIST_INDEXES", "INVALID_ARGS"),
|
|
2680
2818
|
domain: error.ErrorDomain.STORAGE,
|
|
2681
2819
|
category: error.ErrorCategory.USER,
|
|
2682
2820
|
text: "LanceDB client not initialized. Use LanceVectorStore.create() to create an instance",
|
|
@@ -2695,7 +2833,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2695
2833
|
} catch (error$1) {
|
|
2696
2834
|
throw new error.MastraError(
|
|
2697
2835
|
{
|
|
2698
|
-
id: "
|
|
2836
|
+
id: storage.createVectorErrorId("LANCE", "LIST_INDEXES", "FAILED"),
|
|
2699
2837
|
domain: error.ErrorDomain.STORAGE,
|
|
2700
2838
|
category: error.ErrorCategory.THIRD_PARTY
|
|
2701
2839
|
},
|
|
@@ -2714,7 +2852,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2714
2852
|
} catch (err) {
|
|
2715
2853
|
throw new error.MastraError(
|
|
2716
2854
|
{
|
|
2717
|
-
id: "
|
|
2855
|
+
id: storage.createVectorErrorId("LANCE", "DESCRIBE_INDEX", "INVALID_ARGS"),
|
|
2718
2856
|
domain: error.ErrorDomain.STORAGE,
|
|
2719
2857
|
category: error.ErrorCategory.USER,
|
|
2720
2858
|
details: { indexName }
|
|
@@ -2749,7 +2887,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2749
2887
|
} catch (error$1) {
|
|
2750
2888
|
throw new error.MastraError(
|
|
2751
2889
|
{
|
|
2752
|
-
id: "
|
|
2890
|
+
id: storage.createVectorErrorId("LANCE", "DESCRIBE_INDEX", "FAILED"),
|
|
2753
2891
|
domain: error.ErrorDomain.STORAGE,
|
|
2754
2892
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2755
2893
|
details: { indexName }
|
|
@@ -2769,7 +2907,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2769
2907
|
} catch (err) {
|
|
2770
2908
|
throw new error.MastraError(
|
|
2771
2909
|
{
|
|
2772
|
-
id: "
|
|
2910
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_INDEX", "INVALID_ARGS"),
|
|
2773
2911
|
domain: error.ErrorDomain.STORAGE,
|
|
2774
2912
|
category: error.ErrorCategory.USER,
|
|
2775
2913
|
details: { indexName }
|
|
@@ -2792,7 +2930,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2792
2930
|
} catch (error$1) {
|
|
2793
2931
|
throw new error.MastraError(
|
|
2794
2932
|
{
|
|
2795
|
-
id: "
|
|
2933
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_INDEX", "FAILED"),
|
|
2796
2934
|
domain: error.ErrorDomain.STORAGE,
|
|
2797
2935
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2798
2936
|
details: { indexName }
|
|
@@ -2807,7 +2945,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2807
2945
|
async deleteAllTables() {
|
|
2808
2946
|
if (!this.lanceClient) {
|
|
2809
2947
|
throw new error.MastraError({
|
|
2810
|
-
id: "
|
|
2948
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_ALL_TABLES", "INVALID_ARGS"),
|
|
2811
2949
|
domain: error.ErrorDomain.STORAGE,
|
|
2812
2950
|
category: error.ErrorCategory.USER,
|
|
2813
2951
|
details: { methodName: "deleteAllTables" },
|
|
@@ -2819,7 +2957,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2819
2957
|
} catch (error$1) {
|
|
2820
2958
|
throw new error.MastraError(
|
|
2821
2959
|
{
|
|
2822
|
-
id: "
|
|
2960
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_ALL_TABLES", "FAILED"),
|
|
2823
2961
|
domain: error.ErrorDomain.STORAGE,
|
|
2824
2962
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2825
2963
|
details: { methodName: "deleteAllTables" }
|
|
@@ -2831,7 +2969,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2831
2969
|
async deleteTable(tableName) {
|
|
2832
2970
|
if (!this.lanceClient) {
|
|
2833
2971
|
throw new error.MastraError({
|
|
2834
|
-
id: "
|
|
2972
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_TABLE", "INVALID_ARGS"),
|
|
2835
2973
|
domain: error.ErrorDomain.STORAGE,
|
|
2836
2974
|
category: error.ErrorCategory.USER,
|
|
2837
2975
|
details: { tableName },
|
|
@@ -2843,7 +2981,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2843
2981
|
} catch (error$1) {
|
|
2844
2982
|
throw new error.MastraError(
|
|
2845
2983
|
{
|
|
2846
|
-
id: "
|
|
2984
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_TABLE", "FAILED"),
|
|
2847
2985
|
domain: error.ErrorDomain.STORAGE,
|
|
2848
2986
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2849
2987
|
details: { tableName }
|
|
@@ -2856,7 +2994,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2856
2994
|
const { indexName, update } = params;
|
|
2857
2995
|
if ("id" in params && "filter" in params && params.id && params.filter) {
|
|
2858
2996
|
throw new error.MastraError({
|
|
2859
|
-
id: "
|
|
2997
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "MUTUALLY_EXCLUSIVE"),
|
|
2860
2998
|
domain: error.ErrorDomain.STORAGE,
|
|
2861
2999
|
category: error.ErrorCategory.USER,
|
|
2862
3000
|
text: "id and filter are mutually exclusive",
|
|
@@ -2865,7 +3003,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2865
3003
|
}
|
|
2866
3004
|
if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
|
|
2867
3005
|
throw new error.MastraError({
|
|
2868
|
-
id: "
|
|
3006
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "NO_TARGET"),
|
|
2869
3007
|
domain: error.ErrorDomain.STORAGE,
|
|
2870
3008
|
category: error.ErrorCategory.USER,
|
|
2871
3009
|
text: "Either id or filter must be provided",
|
|
@@ -2874,7 +3012,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2874
3012
|
}
|
|
2875
3013
|
if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
|
|
2876
3014
|
throw new error.MastraError({
|
|
2877
|
-
id: "
|
|
3015
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "EMPTY_FILTER"),
|
|
2878
3016
|
domain: error.ErrorDomain.STORAGE,
|
|
2879
3017
|
category: error.ErrorCategory.USER,
|
|
2880
3018
|
text: "Cannot update with empty filter",
|
|
@@ -2883,7 +3021,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2883
3021
|
}
|
|
2884
3022
|
if (!update.vector && !update.metadata) {
|
|
2885
3023
|
throw new error.MastraError({
|
|
2886
|
-
id: "
|
|
3024
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "NO_PAYLOAD"),
|
|
2887
3025
|
domain: error.ErrorDomain.STORAGE,
|
|
2888
3026
|
category: error.ErrorCategory.USER,
|
|
2889
3027
|
text: "No updates provided",
|
|
@@ -2978,7 +3116,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2978
3116
|
if (error$1 instanceof error.MastraError) throw error$1;
|
|
2979
3117
|
throw new error.MastraError(
|
|
2980
3118
|
{
|
|
2981
|
-
id: "
|
|
3119
|
+
id: storage.createVectorErrorId("LANCE", "UPDATE_VECTOR", "FAILED"),
|
|
2982
3120
|
domain: error.ErrorDomain.STORAGE,
|
|
2983
3121
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2984
3122
|
details: {
|
|
@@ -3007,7 +3145,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3007
3145
|
} catch (err) {
|
|
3008
3146
|
throw new error.MastraError(
|
|
3009
3147
|
{
|
|
3010
|
-
id: "
|
|
3148
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTOR", "INVALID_ARGS"),
|
|
3011
3149
|
domain: error.ErrorDomain.STORAGE,
|
|
3012
3150
|
category: error.ErrorCategory.USER,
|
|
3013
3151
|
details: {
|
|
@@ -3040,7 +3178,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3040
3178
|
} catch (error$1) {
|
|
3041
3179
|
throw new error.MastraError(
|
|
3042
3180
|
{
|
|
3043
|
-
id: "
|
|
3181
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTOR", "FAILED"),
|
|
3044
3182
|
domain: error.ErrorDomain.STORAGE,
|
|
3045
3183
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3046
3184
|
details: {
|
|
@@ -3080,7 +3218,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3080
3218
|
async deleteVectors({ indexName, filter, ids }) {
|
|
3081
3219
|
if (ids && filter) {
|
|
3082
3220
|
throw new error.MastraError({
|
|
3083
|
-
id: "
|
|
3221
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "MUTUALLY_EXCLUSIVE"),
|
|
3084
3222
|
domain: error.ErrorDomain.STORAGE,
|
|
3085
3223
|
category: error.ErrorCategory.USER,
|
|
3086
3224
|
text: "ids and filter are mutually exclusive",
|
|
@@ -3089,7 +3227,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3089
3227
|
}
|
|
3090
3228
|
if (!ids && !filter) {
|
|
3091
3229
|
throw new error.MastraError({
|
|
3092
|
-
id: "
|
|
3230
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "NO_TARGET"),
|
|
3093
3231
|
domain: error.ErrorDomain.STORAGE,
|
|
3094
3232
|
category: error.ErrorCategory.USER,
|
|
3095
3233
|
text: "Either filter or ids must be provided",
|
|
@@ -3098,7 +3236,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3098
3236
|
}
|
|
3099
3237
|
if (ids && ids.length === 0) {
|
|
3100
3238
|
throw new error.MastraError({
|
|
3101
|
-
id: "
|
|
3239
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "EMPTY_IDS"),
|
|
3102
3240
|
domain: error.ErrorDomain.STORAGE,
|
|
3103
3241
|
category: error.ErrorCategory.USER,
|
|
3104
3242
|
text: "Cannot delete with empty ids array",
|
|
@@ -3107,7 +3245,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3107
3245
|
}
|
|
3108
3246
|
if (filter && Object.keys(filter).length === 0) {
|
|
3109
3247
|
throw new error.MastraError({
|
|
3110
|
-
id: "
|
|
3248
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "EMPTY_FILTER"),
|
|
3111
3249
|
domain: error.ErrorDomain.STORAGE,
|
|
3112
3250
|
category: error.ErrorCategory.USER,
|
|
3113
3251
|
text: "Cannot delete with empty filter",
|
|
@@ -3167,7 +3305,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
3167
3305
|
if (error$1 instanceof error.MastraError) throw error$1;
|
|
3168
3306
|
throw new error.MastraError(
|
|
3169
3307
|
{
|
|
3170
|
-
id: "
|
|
3308
|
+
id: storage.createVectorErrorId("LANCE", "DELETE_VECTORS", "FAILED"),
|
|
3171
3309
|
domain: error.ErrorDomain.STORAGE,
|
|
3172
3310
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
3173
3311
|
details: {
|