@mastra/lance 0.1.3-alpha.0 → 0.1.3-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +26 -0
- package/dist/_tsup-dts-rollup.d.cts +18 -4
- package/dist/_tsup-dts-rollup.d.ts +18 -4
- package/dist/index.cjs +802 -160
- package/dist/index.js +769 -127
- package/package.json +5 -5
- package/src/storage/index.test.ts +72 -2
- package/src/storage/index.ts +486 -68
- package/src/vector/filter.test.ts +3 -3
- package/src/vector/filter.ts +24 -4
- package/src/vector/index.test.ts +3 -3
- package/src/vector/index.ts +320 -79
package/src/storage/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { connect } from '@lancedb/lancedb';
|
|
|
2
2
|
import type { Connection, ConnectionOptions, SchemaLike, FieldLike } from '@lancedb/lancedb';
|
|
3
3
|
import type { MastraMessageContentV2 } from '@mastra/core/agent';
|
|
4
4
|
import { MessageList } from '@mastra/core/agent';
|
|
5
|
+
import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
|
|
5
6
|
import type { MastraMessageV1, MastraMessageV2, StorageThreadType, TraceType } from '@mastra/core/memory';
|
|
6
7
|
import {
|
|
7
8
|
MastraStorage,
|
|
@@ -57,10 +58,30 @@ export class LanceStorage extends MastraStorage {
|
|
|
57
58
|
instance.lanceClient = await connect(uri, options);
|
|
58
59
|
return instance;
|
|
59
60
|
} catch (e: any) {
|
|
60
|
-
throw new
|
|
61
|
+
throw new MastraError(
|
|
62
|
+
{
|
|
63
|
+
id: 'STORAGE_LANCE_STORAGE_CONNECT_FAILED',
|
|
64
|
+
domain: ErrorDomain.STORAGE,
|
|
65
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
66
|
+
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
67
|
+
details: { uri, optionsProvided: !!options },
|
|
68
|
+
},
|
|
69
|
+
e,
|
|
70
|
+
);
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
|
|
74
|
+
private getPrimaryKeys(tableName: TABLE_NAMES): string[] {
|
|
75
|
+
let primaryId: string[] = ['id'];
|
|
76
|
+
if (tableName === TABLE_WORKFLOW_SNAPSHOT) {
|
|
77
|
+
primaryId = ['workflow_name', 'run_id'];
|
|
78
|
+
} else if (tableName === TABLE_EVALS) {
|
|
79
|
+
primaryId = ['agent_name', 'metric_name', 'run_id'];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return primaryId;
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
/**
|
|
65
86
|
* @internal
|
|
66
87
|
* Private constructor to enforce using the create factory method
|
|
@@ -76,11 +97,41 @@ export class LanceStorage extends MastraStorage {
|
|
|
76
97
|
tableName: TABLE_NAMES;
|
|
77
98
|
schema: Record<string, StorageColumn>;
|
|
78
99
|
}): Promise<void> {
|
|
100
|
+
try {
|
|
101
|
+
if (!this.lanceClient) {
|
|
102
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
103
|
+
}
|
|
104
|
+
if (!tableName) {
|
|
105
|
+
throw new Error('tableName is required for createTable.');
|
|
106
|
+
}
|
|
107
|
+
if (!schema) {
|
|
108
|
+
throw new Error('schema is required for createTable.');
|
|
109
|
+
}
|
|
110
|
+
} catch (error) {
|
|
111
|
+
throw new MastraError(
|
|
112
|
+
{
|
|
113
|
+
id: 'STORAGE_LANCE_STORAGE_CREATE_TABLE_INVALID_ARGS',
|
|
114
|
+
domain: ErrorDomain.STORAGE,
|
|
115
|
+
category: ErrorCategory.USER,
|
|
116
|
+
details: { tableName },
|
|
117
|
+
},
|
|
118
|
+
error,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
79
122
|
try {
|
|
80
123
|
const arrowSchema = this.translateSchema(schema);
|
|
81
124
|
await this.lanceClient.createEmptyTable(tableName, arrowSchema);
|
|
82
125
|
} catch (error: any) {
|
|
83
|
-
throw new
|
|
126
|
+
throw new MastraError(
|
|
127
|
+
{
|
|
128
|
+
id: 'STORAGE_LANCE_STORAGE_CREATE_TABLE_FAILED',
|
|
129
|
+
domain: ErrorDomain.STORAGE,
|
|
130
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
131
|
+
details: { tableName },
|
|
132
|
+
},
|
|
133
|
+
error,
|
|
134
|
+
);
|
|
84
135
|
}
|
|
85
136
|
}
|
|
86
137
|
|
|
@@ -130,15 +181,42 @@ export class LanceStorage extends MastraStorage {
|
|
|
130
181
|
* @param tableName Name of the table to drop
|
|
131
182
|
*/
|
|
132
183
|
async dropTable(tableName: TABLE_NAMES): Promise<void> {
|
|
184
|
+
try {
|
|
185
|
+
if (!this.lanceClient) {
|
|
186
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
187
|
+
}
|
|
188
|
+
if (!tableName) {
|
|
189
|
+
throw new Error('tableName is required for dropTable.');
|
|
190
|
+
}
|
|
191
|
+
} catch (validationError: any) {
|
|
192
|
+
throw new MastraError(
|
|
193
|
+
{
|
|
194
|
+
id: 'STORAGE_LANCE_STORAGE_DROP_TABLE_INVALID_ARGS',
|
|
195
|
+
domain: ErrorDomain.STORAGE,
|
|
196
|
+
category: ErrorCategory.USER,
|
|
197
|
+
text: validationError.message,
|
|
198
|
+
details: { tableName },
|
|
199
|
+
},
|
|
200
|
+
validationError,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
133
204
|
try {
|
|
134
205
|
await this.lanceClient.dropTable(tableName);
|
|
135
206
|
} catch (error: any) {
|
|
136
|
-
|
|
137
|
-
if (error.toString().includes('was not found')) {
|
|
207
|
+
if (error.toString().includes('was not found') || error.message?.includes('Table not found')) {
|
|
138
208
|
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
139
209
|
return;
|
|
140
210
|
}
|
|
141
|
-
throw new
|
|
211
|
+
throw new MastraError(
|
|
212
|
+
{
|
|
213
|
+
id: 'STORAGE_LANCE_STORAGE_DROP_TABLE_FAILED',
|
|
214
|
+
domain: ErrorDomain.STORAGE,
|
|
215
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
216
|
+
details: { tableName },
|
|
217
|
+
},
|
|
218
|
+
error,
|
|
219
|
+
);
|
|
142
220
|
}
|
|
143
221
|
}
|
|
144
222
|
|
|
@@ -148,6 +226,26 @@ export class LanceStorage extends MastraStorage {
|
|
|
148
226
|
* @returns Table schema
|
|
149
227
|
*/
|
|
150
228
|
async getTableSchema(tableName: TABLE_NAMES): Promise<SchemaLike> {
|
|
229
|
+
try {
|
|
230
|
+
if (!this.lanceClient) {
|
|
231
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
232
|
+
}
|
|
233
|
+
if (!tableName) {
|
|
234
|
+
throw new Error('tableName is required for getTableSchema.');
|
|
235
|
+
}
|
|
236
|
+
} catch (validationError: any) {
|
|
237
|
+
throw new MastraError(
|
|
238
|
+
{
|
|
239
|
+
id: 'STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_INVALID_ARGS',
|
|
240
|
+
domain: ErrorDomain.STORAGE,
|
|
241
|
+
category: ErrorCategory.USER,
|
|
242
|
+
text: validationError.message,
|
|
243
|
+
details: { tableName },
|
|
244
|
+
},
|
|
245
|
+
validationError,
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
151
249
|
try {
|
|
152
250
|
const table = await this.lanceClient.openTable(tableName);
|
|
153
251
|
const rawSchema = await table.schema();
|
|
@@ -162,7 +260,15 @@ export class LanceStorage extends MastraStorage {
|
|
|
162
260
|
},
|
|
163
261
|
};
|
|
164
262
|
} catch (error: any) {
|
|
165
|
-
throw new
|
|
263
|
+
throw new MastraError(
|
|
264
|
+
{
|
|
265
|
+
id: 'STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_FAILED',
|
|
266
|
+
domain: ErrorDomain.STORAGE,
|
|
267
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
268
|
+
details: { tableName },
|
|
269
|
+
},
|
|
270
|
+
error,
|
|
271
|
+
);
|
|
166
272
|
}
|
|
167
273
|
}
|
|
168
274
|
|
|
@@ -199,43 +305,114 @@ export class LanceStorage extends MastraStorage {
|
|
|
199
305
|
schema: Record<string, StorageColumn>;
|
|
200
306
|
ifNotExists: string[];
|
|
201
307
|
}): Promise<void> {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
308
|
+
try {
|
|
309
|
+
if (!this.lanceClient) {
|
|
310
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
311
|
+
}
|
|
312
|
+
if (!tableName) {
|
|
313
|
+
throw new Error('tableName is required for alterTable.');
|
|
314
|
+
}
|
|
315
|
+
if (!schema) {
|
|
316
|
+
throw new Error('schema is required for alterTable.');
|
|
317
|
+
}
|
|
318
|
+
if (!ifNotExists || ifNotExists.length === 0) {
|
|
319
|
+
this.logger.debug('No columns specified to add in alterTable, skipping.');
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
} catch (validationError: any) {
|
|
323
|
+
throw new MastraError(
|
|
324
|
+
{
|
|
325
|
+
id: 'STORAGE_LANCE_STORAGE_ALTER_TABLE_INVALID_ARGS',
|
|
326
|
+
domain: ErrorDomain.STORAGE,
|
|
327
|
+
category: ErrorCategory.USER,
|
|
328
|
+
text: validationError.message,
|
|
329
|
+
details: { tableName },
|
|
330
|
+
},
|
|
331
|
+
validationError,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
214
334
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
.map(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
335
|
+
try {
|
|
336
|
+
const table = await this.lanceClient.openTable(tableName);
|
|
337
|
+
const currentSchema = await table.schema();
|
|
338
|
+
const existingFields = new Set(currentSchema.fields.map((f: any) => f.name));
|
|
339
|
+
|
|
340
|
+
const typeMap: Record<string, string> = {
|
|
341
|
+
text: 'string',
|
|
342
|
+
integer: 'int',
|
|
343
|
+
bigint: 'bigint',
|
|
344
|
+
timestamp: 'timestamp',
|
|
345
|
+
jsonb: 'string',
|
|
346
|
+
uuid: 'string',
|
|
347
|
+
};
|
|
227
348
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
349
|
+
// Find columns to add
|
|
350
|
+
const columnsToAdd = ifNotExists
|
|
351
|
+
.filter(col => schema[col] && !existingFields.has(col))
|
|
352
|
+
.map(col => {
|
|
353
|
+
const colDef = schema[col];
|
|
354
|
+
return {
|
|
355
|
+
name: col,
|
|
356
|
+
valueSql: colDef?.nullable
|
|
357
|
+
? `cast(NULL as ${typeMap[colDef.type ?? 'text']})`
|
|
358
|
+
: `cast(${this.getDefaultValue(colDef?.type ?? 'text')} as ${typeMap[colDef?.type ?? 'text']})`,
|
|
359
|
+
};
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
if (columnsToAdd.length > 0) {
|
|
363
|
+
await table.addColumns(columnsToAdd);
|
|
364
|
+
this.logger?.info?.(`Added columns [${columnsToAdd.map(c => c.name).join(', ')}] to table ${tableName}`);
|
|
365
|
+
}
|
|
366
|
+
} catch (error: any) {
|
|
367
|
+
throw new MastraError(
|
|
368
|
+
{
|
|
369
|
+
id: 'STORAGE_LANCE_STORAGE_ALTER_TABLE_FAILED',
|
|
370
|
+
domain: ErrorDomain.STORAGE,
|
|
371
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
372
|
+
details: { tableName },
|
|
373
|
+
},
|
|
374
|
+
error,
|
|
375
|
+
);
|
|
231
376
|
}
|
|
232
377
|
}
|
|
233
378
|
|
|
234
379
|
async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
|
|
235
|
-
|
|
380
|
+
try {
|
|
381
|
+
if (!this.lanceClient) {
|
|
382
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
383
|
+
}
|
|
384
|
+
if (!tableName) {
|
|
385
|
+
throw new Error('tableName is required for clearTable.');
|
|
386
|
+
}
|
|
387
|
+
} catch (validationError: any) {
|
|
388
|
+
throw new MastraError(
|
|
389
|
+
{
|
|
390
|
+
id: 'STORAGE_LANCE_STORAGE_CLEAR_TABLE_INVALID_ARGS',
|
|
391
|
+
domain: ErrorDomain.STORAGE,
|
|
392
|
+
category: ErrorCategory.USER,
|
|
393
|
+
text: validationError.message,
|
|
394
|
+
details: { tableName },
|
|
395
|
+
},
|
|
396
|
+
validationError,
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
const table = await this.lanceClient.openTable(tableName);
|
|
236
402
|
|
|
237
|
-
|
|
238
|
-
|
|
403
|
+
// delete function always takes a predicate as an argument, so we use '1=1' to delete all records because it is always true.
|
|
404
|
+
await table.delete('1=1');
|
|
405
|
+
} catch (error: any) {
|
|
406
|
+
throw new MastraError(
|
|
407
|
+
{
|
|
408
|
+
id: 'STORAGE_LANCE_STORAGE_CLEAR_TABLE_FAILED',
|
|
409
|
+
domain: ErrorDomain.STORAGE,
|
|
410
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
411
|
+
details: { tableName },
|
|
412
|
+
},
|
|
413
|
+
error,
|
|
414
|
+
);
|
|
415
|
+
}
|
|
239
416
|
}
|
|
240
417
|
|
|
241
418
|
/**
|
|
@@ -244,9 +421,34 @@ export class LanceStorage extends MastraStorage {
|
|
|
244
421
|
* @param record The record to insert.
|
|
245
422
|
*/
|
|
246
423
|
async insert({ tableName, record }: { tableName: string; record: Record<string, any> }): Promise<void> {
|
|
424
|
+
try {
|
|
425
|
+
if (!this.lanceClient) {
|
|
426
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
427
|
+
}
|
|
428
|
+
if (!tableName) {
|
|
429
|
+
throw new Error('tableName is required for insert.');
|
|
430
|
+
}
|
|
431
|
+
if (!record || Object.keys(record).length === 0) {
|
|
432
|
+
throw new Error('record is required and cannot be empty for insert.');
|
|
433
|
+
}
|
|
434
|
+
} catch (validationError: any) {
|
|
435
|
+
throw new MastraError(
|
|
436
|
+
{
|
|
437
|
+
id: 'STORAGE_LANCE_STORAGE_INSERT_INVALID_ARGS',
|
|
438
|
+
domain: ErrorDomain.STORAGE,
|
|
439
|
+
category: ErrorCategory.USER,
|
|
440
|
+
text: validationError.message,
|
|
441
|
+
details: { tableName },
|
|
442
|
+
},
|
|
443
|
+
validationError,
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
247
447
|
try {
|
|
248
448
|
const table = await this.lanceClient.openTable(tableName);
|
|
249
449
|
|
|
450
|
+
const primaryId = this.getPrimaryKeys(tableName as TABLE_NAMES);
|
|
451
|
+
|
|
250
452
|
const processedRecord = { ...record };
|
|
251
453
|
|
|
252
454
|
for (const key in processedRecord) {
|
|
@@ -260,9 +462,17 @@ export class LanceStorage extends MastraStorage {
|
|
|
260
462
|
}
|
|
261
463
|
}
|
|
262
464
|
|
|
263
|
-
await table.
|
|
465
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([processedRecord]);
|
|
264
466
|
} catch (error: any) {
|
|
265
|
-
throw new
|
|
467
|
+
throw new MastraError(
|
|
468
|
+
{
|
|
469
|
+
id: 'STORAGE_LANCE_STORAGE_INSERT_FAILED',
|
|
470
|
+
domain: ErrorDomain.STORAGE,
|
|
471
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
472
|
+
details: { tableName },
|
|
473
|
+
},
|
|
474
|
+
error,
|
|
475
|
+
);
|
|
266
476
|
}
|
|
267
477
|
}
|
|
268
478
|
|
|
@@ -272,9 +482,34 @@ export class LanceStorage extends MastraStorage {
|
|
|
272
482
|
* @param records The records to insert.
|
|
273
483
|
*/
|
|
274
484
|
async batchInsert({ tableName, records }: { tableName: string; records: Record<string, any>[] }): Promise<void> {
|
|
485
|
+
try {
|
|
486
|
+
if (!this.lanceClient) {
|
|
487
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
488
|
+
}
|
|
489
|
+
if (!tableName) {
|
|
490
|
+
throw new Error('tableName is required for batchInsert.');
|
|
491
|
+
}
|
|
492
|
+
if (!records || records.length === 0) {
|
|
493
|
+
throw new Error('records array is required and cannot be empty for batchInsert.');
|
|
494
|
+
}
|
|
495
|
+
} catch (validationError: any) {
|
|
496
|
+
throw new MastraError(
|
|
497
|
+
{
|
|
498
|
+
id: 'STORAGE_LANCE_STORAGE_BATCH_INSERT_INVALID_ARGS',
|
|
499
|
+
domain: ErrorDomain.STORAGE,
|
|
500
|
+
category: ErrorCategory.USER,
|
|
501
|
+
text: validationError.message,
|
|
502
|
+
details: { tableName },
|
|
503
|
+
},
|
|
504
|
+
validationError,
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
|
|
275
508
|
try {
|
|
276
509
|
const table = await this.lanceClient.openTable(tableName);
|
|
277
510
|
|
|
511
|
+
const primaryId = this.getPrimaryKeys(tableName as TABLE_NAMES);
|
|
512
|
+
|
|
278
513
|
const processedRecords = records.map(record => {
|
|
279
514
|
const processedRecord = { ...record };
|
|
280
515
|
|
|
@@ -295,9 +530,17 @@ export class LanceStorage extends MastraStorage {
|
|
|
295
530
|
return processedRecord;
|
|
296
531
|
});
|
|
297
532
|
|
|
298
|
-
await table.
|
|
533
|
+
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(processedRecords);
|
|
299
534
|
} catch (error: any) {
|
|
300
|
-
throw new
|
|
535
|
+
throw new MastraError(
|
|
536
|
+
{
|
|
537
|
+
id: 'STORAGE_LANCE_STORAGE_BATCH_INSERT_FAILED',
|
|
538
|
+
domain: ErrorDomain.STORAGE,
|
|
539
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
540
|
+
details: { tableName },
|
|
541
|
+
},
|
|
542
|
+
error,
|
|
543
|
+
);
|
|
301
544
|
}
|
|
302
545
|
}
|
|
303
546
|
|
|
@@ -309,6 +552,29 @@ export class LanceStorage extends MastraStorage {
|
|
|
309
552
|
* @returns The loaded record with proper type conversions, or null if not found
|
|
310
553
|
*/
|
|
311
554
|
async load({ tableName, keys }: { tableName: TABLE_NAMES; keys: Record<string, any> }): Promise<any> {
|
|
555
|
+
try {
|
|
556
|
+
if (!this.lanceClient) {
|
|
557
|
+
throw new Error('LanceDB client not initialized. Call LanceStorage.create() first.');
|
|
558
|
+
}
|
|
559
|
+
if (!tableName) {
|
|
560
|
+
throw new Error('tableName is required for load.');
|
|
561
|
+
}
|
|
562
|
+
if (!keys || Object.keys(keys).length === 0) {
|
|
563
|
+
throw new Error('keys are required and cannot be empty for load.');
|
|
564
|
+
}
|
|
565
|
+
} catch (validationError: any) {
|
|
566
|
+
throw new MastraError(
|
|
567
|
+
{
|
|
568
|
+
id: 'STORAGE_LANCE_STORAGE_LOAD_INVALID_ARGS',
|
|
569
|
+
domain: ErrorDomain.STORAGE,
|
|
570
|
+
category: ErrorCategory.USER,
|
|
571
|
+
text: validationError.message,
|
|
572
|
+
details: { tableName },
|
|
573
|
+
},
|
|
574
|
+
validationError,
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
312
578
|
try {
|
|
313
579
|
const table = await this.lanceClient.openTable(tableName);
|
|
314
580
|
const tableSchema = await this.getTableSchema(tableName);
|
|
@@ -351,7 +617,17 @@ export class LanceStorage extends MastraStorage {
|
|
|
351
617
|
// Process the result with type conversions
|
|
352
618
|
return this.processResultWithTypeConversion(result[0], tableSchema);
|
|
353
619
|
} catch (error: any) {
|
|
354
|
-
|
|
620
|
+
// If it's already a MastraError (e.g. from validateKeyTypes if we change it later), rethrow
|
|
621
|
+
if (error instanceof MastraError) throw error;
|
|
622
|
+
throw new MastraError(
|
|
623
|
+
{
|
|
624
|
+
id: 'STORAGE_LANCE_STORAGE_LOAD_FAILED',
|
|
625
|
+
domain: ErrorDomain.STORAGE,
|
|
626
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
627
|
+
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? '' },
|
|
628
|
+
},
|
|
629
|
+
error,
|
|
630
|
+
);
|
|
355
631
|
}
|
|
356
632
|
}
|
|
357
633
|
|
|
@@ -457,7 +733,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
457
733
|
try {
|
|
458
734
|
return this.load({ tableName: TABLE_THREADS, keys: { id: threadId } });
|
|
459
735
|
} catch (error: any) {
|
|
460
|
-
throw new
|
|
736
|
+
throw new MastraError(
|
|
737
|
+
{
|
|
738
|
+
id: 'LANCE_STORE_GET_THREAD_BY_ID_FAILED',
|
|
739
|
+
domain: ErrorDomain.STORAGE,
|
|
740
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
741
|
+
},
|
|
742
|
+
error,
|
|
743
|
+
);
|
|
461
744
|
}
|
|
462
745
|
}
|
|
463
746
|
|
|
@@ -473,7 +756,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
473
756
|
await this.getTableSchema(TABLE_THREADS),
|
|
474
757
|
) as StorageThreadType[];
|
|
475
758
|
} catch (error: any) {
|
|
476
|
-
throw new
|
|
759
|
+
throw new MastraError(
|
|
760
|
+
{
|
|
761
|
+
id: 'LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED',
|
|
762
|
+
domain: ErrorDomain.STORAGE,
|
|
763
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
764
|
+
},
|
|
765
|
+
error,
|
|
766
|
+
);
|
|
477
767
|
}
|
|
478
768
|
}
|
|
479
769
|
|
|
@@ -490,7 +780,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
490
780
|
|
|
491
781
|
return thread;
|
|
492
782
|
} catch (error: any) {
|
|
493
|
-
throw new
|
|
783
|
+
throw new MastraError(
|
|
784
|
+
{
|
|
785
|
+
id: 'LANCE_STORE_SAVE_THREAD_FAILED',
|
|
786
|
+
domain: ErrorDomain.STORAGE,
|
|
787
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
788
|
+
},
|
|
789
|
+
error,
|
|
790
|
+
);
|
|
494
791
|
}
|
|
495
792
|
}
|
|
496
793
|
|
|
@@ -506,7 +803,7 @@ export class LanceStorage extends MastraStorage {
|
|
|
506
803
|
try {
|
|
507
804
|
const record = { id, title, metadata: JSON.stringify(metadata) };
|
|
508
805
|
const table = await this.lanceClient.openTable(TABLE_THREADS);
|
|
509
|
-
await table.
|
|
806
|
+
await table.mergeInsert('id').whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
510
807
|
|
|
511
808
|
const query = table.query().where(`id = '${id}'`);
|
|
512
809
|
|
|
@@ -516,7 +813,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
516
813
|
await this.getTableSchema(TABLE_THREADS),
|
|
517
814
|
) as StorageThreadType;
|
|
518
815
|
} catch (error: any) {
|
|
519
|
-
throw new
|
|
816
|
+
throw new MastraError(
|
|
817
|
+
{
|
|
818
|
+
id: 'LANCE_STORE_UPDATE_THREAD_FAILED',
|
|
819
|
+
domain: ErrorDomain.STORAGE,
|
|
820
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
821
|
+
},
|
|
822
|
+
error,
|
|
823
|
+
);
|
|
520
824
|
}
|
|
521
825
|
}
|
|
522
826
|
|
|
@@ -525,7 +829,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
525
829
|
const table = await this.lanceClient.openTable(TABLE_THREADS);
|
|
526
830
|
await table.delete(`id = '${threadId}'`);
|
|
527
831
|
} catch (error: any) {
|
|
528
|
-
throw new
|
|
832
|
+
throw new MastraError(
|
|
833
|
+
{
|
|
834
|
+
id: 'LANCE_STORE_DELETE_THREAD_FAILED',
|
|
835
|
+
domain: ErrorDomain.STORAGE,
|
|
836
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
837
|
+
},
|
|
838
|
+
error,
|
|
839
|
+
);
|
|
529
840
|
}
|
|
530
841
|
}
|
|
531
842
|
|
|
@@ -618,7 +929,7 @@ export class LanceStorage extends MastraStorage {
|
|
|
618
929
|
if (threadConfig) {
|
|
619
930
|
throw new Error('ThreadConfig is not supported by LanceDB storage');
|
|
620
931
|
}
|
|
621
|
-
|
|
932
|
+
const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
|
|
622
933
|
const table = await this.lanceClient.openTable(TABLE_MESSAGES);
|
|
623
934
|
let query = table.query().where(`\`threadId\` = '${threadId}'`);
|
|
624
935
|
|
|
@@ -653,8 +964,8 @@ export class LanceStorage extends MastraStorage {
|
|
|
653
964
|
}
|
|
654
965
|
|
|
655
966
|
// If we're fetching the last N messages, take only the last N after sorting
|
|
656
|
-
if (
|
|
657
|
-
records = records.slice(-
|
|
967
|
+
if (limit !== Number.MAX_SAFE_INTEGER) {
|
|
968
|
+
records = records.slice(-limit);
|
|
658
969
|
}
|
|
659
970
|
|
|
660
971
|
const messages = this.processResultWithTypeConversion(records, await this.getTableSchema(TABLE_MESSAGES));
|
|
@@ -675,7 +986,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
675
986
|
if (format === 'v2') return list.get.all.v2();
|
|
676
987
|
return list.get.all.v1();
|
|
677
988
|
} catch (error: any) {
|
|
678
|
-
throw new
|
|
989
|
+
throw new MastraError(
|
|
990
|
+
{
|
|
991
|
+
id: 'LANCE_STORE_GET_MESSAGES_FAILED',
|
|
992
|
+
domain: ErrorDomain.STORAGE,
|
|
993
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
994
|
+
},
|
|
995
|
+
error,
|
|
996
|
+
);
|
|
679
997
|
}
|
|
680
998
|
}
|
|
681
999
|
|
|
@@ -702,12 +1020,20 @@ export class LanceStorage extends MastraStorage {
|
|
|
702
1020
|
}));
|
|
703
1021
|
|
|
704
1022
|
const table = await this.lanceClient.openTable(TABLE_MESSAGES);
|
|
705
|
-
await table.
|
|
1023
|
+
await table.mergeInsert('id').whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
1024
|
+
|
|
706
1025
|
const list = new MessageList().add(messages, 'memory');
|
|
707
1026
|
if (format === `v2`) return list.get.all.v2();
|
|
708
1027
|
return list.get.all.v1();
|
|
709
1028
|
} catch (error: any) {
|
|
710
|
-
throw new
|
|
1029
|
+
throw new MastraError(
|
|
1030
|
+
{
|
|
1031
|
+
id: 'LANCE_STORE_SAVE_MESSAGES_FAILED',
|
|
1032
|
+
domain: ErrorDomain.STORAGE,
|
|
1033
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1034
|
+
},
|
|
1035
|
+
error,
|
|
1036
|
+
);
|
|
711
1037
|
}
|
|
712
1038
|
}
|
|
713
1039
|
|
|
@@ -726,7 +1052,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
726
1052
|
|
|
727
1053
|
return trace;
|
|
728
1054
|
} catch (error: any) {
|
|
729
|
-
throw new
|
|
1055
|
+
throw new MastraError(
|
|
1056
|
+
{
|
|
1057
|
+
id: 'LANCE_STORE_SAVE_TRACE_FAILED',
|
|
1058
|
+
domain: ErrorDomain.STORAGE,
|
|
1059
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1060
|
+
},
|
|
1061
|
+
error,
|
|
1062
|
+
);
|
|
730
1063
|
}
|
|
731
1064
|
}
|
|
732
1065
|
|
|
@@ -737,7 +1070,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
737
1070
|
const records = await query.toArray();
|
|
738
1071
|
return this.processResultWithTypeConversion(records[0], await this.getTableSchema(TABLE_TRACES)) as TraceType;
|
|
739
1072
|
} catch (error: any) {
|
|
740
|
-
throw new
|
|
1073
|
+
throw new MastraError(
|
|
1074
|
+
{
|
|
1075
|
+
id: 'LANCE_STORE_GET_TRACE_BY_ID_FAILED',
|
|
1076
|
+
domain: ErrorDomain.STORAGE,
|
|
1077
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1078
|
+
},
|
|
1079
|
+
error,
|
|
1080
|
+
);
|
|
741
1081
|
}
|
|
742
1082
|
}
|
|
743
1083
|
|
|
@@ -796,7 +1136,15 @@ export class LanceStorage extends MastraStorage {
|
|
|
796
1136
|
};
|
|
797
1137
|
}) as TraceType[];
|
|
798
1138
|
} catch (error: any) {
|
|
799
|
-
throw new
|
|
1139
|
+
throw new MastraError(
|
|
1140
|
+
{
|
|
1141
|
+
id: 'LANCE_STORE_GET_TRACES_FAILED',
|
|
1142
|
+
domain: ErrorDomain.STORAGE,
|
|
1143
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1144
|
+
details: { name: name ?? '', scope: scope ?? '' },
|
|
1145
|
+
},
|
|
1146
|
+
error,
|
|
1147
|
+
);
|
|
800
1148
|
}
|
|
801
1149
|
}
|
|
802
1150
|
|
|
@@ -819,7 +1167,14 @@ export class LanceStorage extends MastraStorage {
|
|
|
819
1167
|
await table.add(transformedEvals, { mode: 'append' });
|
|
820
1168
|
return evals;
|
|
821
1169
|
} catch (error: any) {
|
|
822
|
-
throw new
|
|
1170
|
+
throw new MastraError(
|
|
1171
|
+
{
|
|
1172
|
+
id: 'LANCE_STORE_SAVE_EVALS_FAILED',
|
|
1173
|
+
domain: ErrorDomain.STORAGE,
|
|
1174
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1175
|
+
},
|
|
1176
|
+
error,
|
|
1177
|
+
);
|
|
823
1178
|
}
|
|
824
1179
|
}
|
|
825
1180
|
|
|
@@ -847,7 +1202,15 @@ export class LanceStorage extends MastraStorage {
|
|
|
847
1202
|
};
|
|
848
1203
|
}) as EvalRow[];
|
|
849
1204
|
} catch (error: any) {
|
|
850
|
-
throw new
|
|
1205
|
+
throw new MastraError(
|
|
1206
|
+
{
|
|
1207
|
+
id: 'LANCE_STORE_GET_EVALS_BY_AGENT_NAME_FAILED',
|
|
1208
|
+
domain: ErrorDomain.STORAGE,
|
|
1209
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1210
|
+
details: { agentName },
|
|
1211
|
+
},
|
|
1212
|
+
error,
|
|
1213
|
+
);
|
|
851
1214
|
}
|
|
852
1215
|
}
|
|
853
1216
|
|
|
@@ -910,7 +1273,15 @@ export class LanceStorage extends MastraStorage {
|
|
|
910
1273
|
total: records.length,
|
|
911
1274
|
};
|
|
912
1275
|
} catch (error: any) {
|
|
913
|
-
throw new
|
|
1276
|
+
throw new MastraError(
|
|
1277
|
+
{
|
|
1278
|
+
id: 'LANCE_STORE_GET_WORKFLOW_RUNS_FAILED',
|
|
1279
|
+
domain: ErrorDomain.STORAGE,
|
|
1280
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1281
|
+
details: { namespace: args?.namespace ?? '', workflowName: args?.workflowName ?? '' },
|
|
1282
|
+
},
|
|
1283
|
+
error,
|
|
1284
|
+
);
|
|
914
1285
|
}
|
|
915
1286
|
}
|
|
916
1287
|
|
|
@@ -938,7 +1309,15 @@ export class LanceStorage extends MastraStorage {
|
|
|
938
1309
|
const record = records[0];
|
|
939
1310
|
return this.parseWorkflowRun(record);
|
|
940
1311
|
} catch (error: any) {
|
|
941
|
-
throw new
|
|
1312
|
+
throw new MastraError(
|
|
1313
|
+
{
|
|
1314
|
+
id: 'LANCE_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED',
|
|
1315
|
+
domain: ErrorDomain.STORAGE,
|
|
1316
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1317
|
+
details: { runId: args.runId, workflowName: args.workflowName ?? '' },
|
|
1318
|
+
},
|
|
1319
|
+
error,
|
|
1320
|
+
);
|
|
942
1321
|
}
|
|
943
1322
|
}
|
|
944
1323
|
|
|
@@ -959,11 +1338,9 @@ export class LanceStorage extends MastraStorage {
|
|
|
959
1338
|
const records = await query.toArray();
|
|
960
1339
|
let createdAt: number;
|
|
961
1340
|
const now = Date.now();
|
|
962
|
-
let mode: 'append' | 'overwrite' = 'append';
|
|
963
1341
|
|
|
964
1342
|
if (records.length > 0) {
|
|
965
1343
|
createdAt = records[0].createdAt ?? now;
|
|
966
|
-
mode = 'overwrite';
|
|
967
1344
|
} else {
|
|
968
1345
|
createdAt = now;
|
|
969
1346
|
}
|
|
@@ -976,9 +1353,21 @@ export class LanceStorage extends MastraStorage {
|
|
|
976
1353
|
updatedAt: now,
|
|
977
1354
|
};
|
|
978
1355
|
|
|
979
|
-
await table
|
|
1356
|
+
await table
|
|
1357
|
+
.mergeInsert(['workflow_name', 'run_id'])
|
|
1358
|
+
.whenMatchedUpdateAll()
|
|
1359
|
+
.whenNotMatchedInsertAll()
|
|
1360
|
+
.execute([record]);
|
|
980
1361
|
} catch (error: any) {
|
|
981
|
-
throw new
|
|
1362
|
+
throw new MastraError(
|
|
1363
|
+
{
|
|
1364
|
+
id: 'LANCE_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED',
|
|
1365
|
+
domain: ErrorDomain.STORAGE,
|
|
1366
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1367
|
+
details: { workflowName, runId },
|
|
1368
|
+
},
|
|
1369
|
+
error,
|
|
1370
|
+
);
|
|
982
1371
|
}
|
|
983
1372
|
}
|
|
984
1373
|
async loadWorkflowSnapshot({
|
|
@@ -994,12 +1383,27 @@ export class LanceStorage extends MastraStorage {
|
|
|
994
1383
|
const records = await query.toArray();
|
|
995
1384
|
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
996
1385
|
} catch (error: any) {
|
|
997
|
-
throw new
|
|
1386
|
+
throw new MastraError(
|
|
1387
|
+
{
|
|
1388
|
+
id: 'LANCE_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED',
|
|
1389
|
+
domain: ErrorDomain.STORAGE,
|
|
1390
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1391
|
+
details: { workflowName, runId },
|
|
1392
|
+
},
|
|
1393
|
+
error,
|
|
1394
|
+
);
|
|
998
1395
|
}
|
|
999
1396
|
}
|
|
1000
1397
|
|
|
1001
1398
|
async getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & { traces: Trace[] }> {
|
|
1002
|
-
throw new
|
|
1399
|
+
throw new MastraError(
|
|
1400
|
+
{
|
|
1401
|
+
id: 'LANCE_STORE_GET_TRACES_PAGINATED_FAILED',
|
|
1402
|
+
domain: ErrorDomain.STORAGE,
|
|
1403
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1404
|
+
},
|
|
1405
|
+
'Method not implemented.',
|
|
1406
|
+
);
|
|
1003
1407
|
}
|
|
1004
1408
|
|
|
1005
1409
|
async getThreadsByResourceIdPaginated(_args: {
|
|
@@ -1007,13 +1411,27 @@ export class LanceStorage extends MastraStorage {
|
|
|
1007
1411
|
page?: number;
|
|
1008
1412
|
perPage?: number;
|
|
1009
1413
|
}): Promise<PaginationInfo & { threads: StorageThreadType[] }> {
|
|
1010
|
-
throw new
|
|
1414
|
+
throw new MastraError(
|
|
1415
|
+
{
|
|
1416
|
+
id: 'LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED',
|
|
1417
|
+
domain: ErrorDomain.STORAGE,
|
|
1418
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1419
|
+
},
|
|
1420
|
+
'Method not implemented.',
|
|
1421
|
+
);
|
|
1011
1422
|
}
|
|
1012
1423
|
|
|
1013
1424
|
async getMessagesPaginated(
|
|
1014
1425
|
_args: StorageGetMessagesArg,
|
|
1015
1426
|
): Promise<PaginationInfo & { messages: MastraMessageV1[] | MastraMessageV2[] }> {
|
|
1016
|
-
throw new
|
|
1427
|
+
throw new MastraError(
|
|
1428
|
+
{
|
|
1429
|
+
id: 'LANCE_STORE_GET_MESSAGES_PAGINATED_FAILED',
|
|
1430
|
+
domain: ErrorDomain.STORAGE,
|
|
1431
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1432
|
+
},
|
|
1433
|
+
'Method not implemented.',
|
|
1434
|
+
);
|
|
1017
1435
|
}
|
|
1018
1436
|
|
|
1019
1437
|
async updateMessages(_args: {
|