@mastra/lance 0.2.10 → 0.2.11-alpha.0

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.
@@ -1,494 +0,0 @@
1
- import { connect } from '@lancedb/lancedb';
2
- import type { Connection, ConnectionOptions } from '@lancedb/lancedb';
3
- import type { MastraMessageContentV2 } from '@mastra/core/agent';
4
- import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
5
- import type { MastraMessageV1, MastraMessageV2, StorageThreadType, TraceType } from '@mastra/core/memory';
6
- import type { ScoreRowData, ScoringSource } from '@mastra/core/scores';
7
- import { MastraStorage } from '@mastra/core/storage';
8
- import type {
9
- TABLE_NAMES,
10
- PaginationInfo,
11
- StorageGetMessagesArg,
12
- StorageColumn,
13
- EvalRow,
14
- WorkflowRuns,
15
- StoragePagination,
16
- StorageDomains,
17
- StorageGetTracesPaginatedArg,
18
- StorageResourceType,
19
- } from '@mastra/core/storage';
20
- import type { Trace } from '@mastra/core/telemetry';
21
- import type { StepResult, WorkflowRunState } from '@mastra/core/workflows';
22
- import { StoreLegacyEvalsLance } from './domains/legacy-evals';
23
- import { StoreMemoryLance } from './domains/memory';
24
- import { StoreOperationsLance } from './domains/operations';
25
- import { StoreScoresLance } from './domains/scores';
26
- import { StoreTracesLance } from './domains/traces';
27
- import { StoreWorkflowsLance } from './domains/workflows';
28
-
29
- export class LanceStorage extends MastraStorage {
30
- stores: StorageDomains;
31
- private lanceClient!: Connection;
32
- /**
33
- * Creates a new instance of LanceStorage
34
- * @param uri The URI to connect to LanceDB
35
- * @param options connection options
36
- *
37
- * Usage:
38
- *
39
- * Connect to a local database
40
- * ```ts
41
- * const store = await LanceStorage.create('/path/to/db');
42
- * ```
43
- *
44
- * Connect to a LanceDB cloud database
45
- * ```ts
46
- * const store = await LanceStorage.create('db://host:port');
47
- * ```
48
- *
49
- * Connect to a cloud database
50
- * ```ts
51
- * const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
52
- * ```
53
- */
54
- public static async create(name: string, uri: string, options?: ConnectionOptions): Promise<LanceStorage> {
55
- const instance = new LanceStorage(name);
56
- try {
57
- instance.lanceClient = await connect(uri, options);
58
- const operations = new StoreOperationsLance({ client: instance.lanceClient });
59
- instance.stores = {
60
- operations: new StoreOperationsLance({ client: instance.lanceClient }),
61
- workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
62
- traces: new StoreTracesLance({ client: instance.lanceClient, operations }),
63
- scores: new StoreScoresLance({ client: instance.lanceClient }),
64
- memory: new StoreMemoryLance({ client: instance.lanceClient, operations }),
65
- legacyEvals: new StoreLegacyEvalsLance({ client: instance.lanceClient }),
66
- };
67
- return instance;
68
- } catch (e: any) {
69
- throw new MastraError(
70
- {
71
- id: 'STORAGE_LANCE_STORAGE_CONNECT_FAILED',
72
- domain: ErrorDomain.STORAGE,
73
- category: ErrorCategory.THIRD_PARTY,
74
- text: `Failed to connect to LanceDB: ${e.message || e}`,
75
- details: { uri, optionsProvided: !!options },
76
- },
77
- e,
78
- );
79
- }
80
- }
81
-
82
- /**
83
- * @internal
84
- * Private constructor to enforce using the create factory method
85
- */
86
- private constructor(name: string) {
87
- super({ name });
88
- const operations = new StoreOperationsLance({ client: this.lanceClient });
89
-
90
- this.stores = {
91
- operations: new StoreOperationsLance({ client: this.lanceClient }),
92
- workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
93
- traces: new StoreTracesLance({ client: this.lanceClient, operations }),
94
- scores: new StoreScoresLance({ client: this.lanceClient }),
95
- legacyEvals: new StoreLegacyEvalsLance({ client: this.lanceClient }),
96
- memory: new StoreMemoryLance({ client: this.lanceClient, operations }),
97
- };
98
- }
99
-
100
- async createTable({
101
- tableName,
102
- schema,
103
- }: {
104
- tableName: TABLE_NAMES;
105
- schema: Record<string, StorageColumn>;
106
- }): Promise<void> {
107
- return this.stores.operations.createTable({ tableName, schema });
108
- }
109
-
110
- async dropTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
111
- return this.stores.operations.dropTable({ tableName });
112
- }
113
-
114
- async alterTable({
115
- tableName,
116
- schema,
117
- ifNotExists,
118
- }: {
119
- tableName: TABLE_NAMES;
120
- schema: Record<string, StorageColumn>;
121
- ifNotExists: string[];
122
- }): Promise<void> {
123
- return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
124
- }
125
-
126
- async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
127
- return this.stores.operations.clearTable({ tableName });
128
- }
129
-
130
- async insert({ tableName, record }: { tableName: TABLE_NAMES; record: Record<string, any> }): Promise<void> {
131
- return this.stores.operations.insert({ tableName, record });
132
- }
133
-
134
- async batchInsert({ tableName, records }: { tableName: TABLE_NAMES; records: Record<string, any>[] }): Promise<void> {
135
- return this.stores.operations.batchInsert({ tableName, records });
136
- }
137
-
138
- async load({ tableName, keys }: { tableName: TABLE_NAMES; keys: Record<string, any> }): Promise<any> {
139
- return this.stores.operations.load({ tableName, keys });
140
- }
141
-
142
- async getThreadById({ threadId }: { threadId: string }): Promise<StorageThreadType | null> {
143
- return this.stores.memory.getThreadById({ threadId });
144
- }
145
-
146
- async getThreadsByResourceId({ resourceId }: { resourceId: string }): Promise<StorageThreadType[]> {
147
- return this.stores.memory.getThreadsByResourceId({ resourceId });
148
- }
149
-
150
- /**
151
- * Saves a thread to the database. This function doesn't overwrite existing threads.
152
- * @param thread - The thread to save
153
- * @returns The saved thread
154
- */
155
- async saveThread({ thread }: { thread: StorageThreadType }): Promise<StorageThreadType> {
156
- return this.stores.memory.saveThread({ thread });
157
- }
158
-
159
- async updateThread({
160
- id,
161
- title,
162
- metadata,
163
- }: {
164
- id: string;
165
- title: string;
166
- metadata: Record<string, unknown>;
167
- }): Promise<StorageThreadType> {
168
- return this.stores.memory.updateThread({ id, title, metadata });
169
- }
170
-
171
- async deleteThread({ threadId }: { threadId: string }): Promise<void> {
172
- return this.stores.memory.deleteThread({ threadId });
173
- }
174
-
175
- public get supports() {
176
- return {
177
- selectByIncludeResourceScope: true,
178
- resourceWorkingMemory: true,
179
- hasColumn: true,
180
- createTable: true,
181
- deleteMessages: false,
182
- };
183
- }
184
-
185
- async getResourceById({ resourceId }: { resourceId: string }): Promise<StorageResourceType | null> {
186
- return this.stores.memory.getResourceById({ resourceId });
187
- }
188
-
189
- async saveResource({ resource }: { resource: StorageResourceType }): Promise<StorageResourceType> {
190
- return this.stores.memory.saveResource({ resource });
191
- }
192
-
193
- async updateResource({
194
- resourceId,
195
- workingMemory,
196
- metadata,
197
- }: {
198
- resourceId: string;
199
- workingMemory?: string;
200
- metadata?: Record<string, unknown>;
201
- }): Promise<StorageResourceType> {
202
- return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
203
- }
204
-
205
- /**
206
- * Processes messages to include context messages based on withPreviousMessages and withNextMessages
207
- * @param records - The sorted array of records to process
208
- * @param include - The array of include specifications with context parameters
209
- * @returns The processed array with context messages included
210
- */
211
- private processMessagesWithContext(
212
- records: any[],
213
- include: { id: string; withPreviousMessages?: number; withNextMessages?: number }[],
214
- ): any[] {
215
- const messagesWithContext = include.filter(item => item.withPreviousMessages || item.withNextMessages);
216
-
217
- if (messagesWithContext.length === 0) {
218
- return records;
219
- }
220
-
221
- // Create a map of message id to index in the sorted array for quick lookup
222
- const messageIndexMap = new Map<string, number>();
223
- records.forEach((message, index) => {
224
- messageIndexMap.set(message.id, index);
225
- });
226
-
227
- // Keep track of additional indices to include
228
- const additionalIndices = new Set<number>();
229
-
230
- for (const item of messagesWithContext) {
231
- const messageIndex = messageIndexMap.get(item.id);
232
-
233
- if (messageIndex !== undefined) {
234
- // Add previous messages if requested
235
- if (item.withPreviousMessages) {
236
- const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
237
- for (let i = startIdx; i < messageIndex; i++) {
238
- additionalIndices.add(i);
239
- }
240
- }
241
-
242
- // Add next messages if requested
243
- if (item.withNextMessages) {
244
- const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
245
- for (let i = messageIndex + 1; i <= endIdx; i++) {
246
- additionalIndices.add(i);
247
- }
248
- }
249
- }
250
- }
251
-
252
- // If we need to include additional messages, create a new set of records
253
- if (additionalIndices.size === 0) {
254
- return records;
255
- }
256
-
257
- // Get IDs of the records that matched the original query
258
- const originalMatchIds = new Set(include.map(item => item.id));
259
-
260
- // Create a set of all indices we need to include
261
- const allIndices = new Set<number>();
262
-
263
- // Add indices of originally matched messages
264
- records.forEach((record, index) => {
265
- if (originalMatchIds.has(record.id)) {
266
- allIndices.add(index);
267
- }
268
- });
269
-
270
- // Add the additional context message indices
271
- additionalIndices.forEach(index => {
272
- allIndices.add(index);
273
- });
274
-
275
- // Create a new filtered array with only the required messages
276
- // while maintaining chronological order
277
- return Array.from(allIndices)
278
- .sort((a, b) => a - b)
279
- .map(index => records[index]);
280
- }
281
-
282
- public async getMessages(args: StorageGetMessagesArg & { format?: 'v1' }): Promise<MastraMessageV1[]>;
283
- public async getMessages(args: StorageGetMessagesArg & { format: 'v2' }): Promise<MastraMessageV2[]>;
284
- public async getMessages({
285
- threadId,
286
- resourceId,
287
- selectBy,
288
- format,
289
- threadConfig,
290
- }: StorageGetMessagesArg & { format?: 'v1' | 'v2' }): Promise<MastraMessageV1[] | MastraMessageV2[]> {
291
- return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format, threadConfig });
292
- }
293
-
294
- async getMessagesById({ messageIds, format }: { messageIds: string[]; format: 'v1' }): Promise<MastraMessageV1[]>;
295
- async getMessagesById({ messageIds, format }: { messageIds: string[]; format?: 'v2' }): Promise<MastraMessageV2[]>;
296
- async getMessagesById({
297
- messageIds,
298
- format,
299
- }: {
300
- messageIds: string[];
301
- format?: 'v1' | 'v2';
302
- }): Promise<MastraMessageV1[] | MastraMessageV2[]> {
303
- return this.stores.memory.getMessagesById({ messageIds, format });
304
- }
305
-
306
- async saveMessages(args: { messages: MastraMessageV1[]; format?: undefined | 'v1' }): Promise<MastraMessageV1[]>;
307
- async saveMessages(args: { messages: MastraMessageV2[]; format: 'v2' }): Promise<MastraMessageV2[]>;
308
- async saveMessages(
309
- args: { messages: MastraMessageV1[]; format?: undefined | 'v1' } | { messages: MastraMessageV2[]; format: 'v2' },
310
- ): Promise<MastraMessageV2[] | MastraMessageV1[]> {
311
- return this.stores.memory.saveMessages(args);
312
- }
313
-
314
- async getThreadsByResourceIdPaginated(args: {
315
- resourceId: string;
316
- page: number;
317
- perPage: number;
318
- }): Promise<PaginationInfo & { threads: StorageThreadType[] }> {
319
- return this.stores.memory.getThreadsByResourceIdPaginated(args);
320
- }
321
-
322
- async getMessagesPaginated(
323
- args: StorageGetMessagesArg & { format?: 'v1' | 'v2' },
324
- ): Promise<PaginationInfo & { messages: MastraMessageV1[] | MastraMessageV2[] }> {
325
- return this.stores.memory.getMessagesPaginated(args);
326
- }
327
-
328
- async updateMessages(_args: {
329
- messages: Partial<Omit<MastraMessageV2, 'createdAt'>> &
330
- {
331
- id: string;
332
- content?: { metadata?: MastraMessageContentV2['metadata']; content?: MastraMessageContentV2['content'] };
333
- }[];
334
- }): Promise<MastraMessageV2[]> {
335
- return this.stores.memory.updateMessages(_args);
336
- }
337
-
338
- async getTraceById(args: { traceId: string }): Promise<TraceType> {
339
- return (this.stores as any).traces.getTraceById(args);
340
- }
341
-
342
- async getTraces(args: {
343
- name?: string;
344
- scope?: string;
345
- page: number;
346
- perPage: number;
347
- attributes?: Record<string, string>;
348
- }): Promise<Trace[]> {
349
- return (this.stores as any).traces.getTraces(args);
350
- }
351
-
352
- async getTracesPaginated(args: StorageGetTracesPaginatedArg): Promise<PaginationInfo & { traces: Trace[] }> {
353
- return (this.stores as any).traces.getTracesPaginated(args);
354
- }
355
-
356
- async getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]> {
357
- return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
358
- }
359
-
360
- async getEvals(options: {
361
- agentName?: string;
362
- type?: 'test' | 'live';
363
- page?: number;
364
- perPage?: number;
365
- fromDate?: Date;
366
- toDate?: Date;
367
- dateRange?: { start?: Date; end?: Date };
368
- }): Promise<PaginationInfo & { evals: EvalRow[] }> {
369
- return this.stores.legacyEvals.getEvals(options);
370
- }
371
-
372
- async getWorkflowRuns(args?: {
373
- namespace?: string;
374
- workflowName?: string;
375
- fromDate?: Date;
376
- toDate?: Date;
377
- limit?: number;
378
- offset?: number;
379
- }): Promise<WorkflowRuns> {
380
- return this.stores.workflows.getWorkflowRuns(args);
381
- }
382
-
383
- async getWorkflowRunById(args: { runId: string; workflowName?: string }): Promise<{
384
- workflowName: string;
385
- runId: string;
386
- snapshot: any;
387
- createdAt: Date;
388
- updatedAt: Date;
389
- } | null> {
390
- return this.stores.workflows.getWorkflowRunById(args);
391
- }
392
-
393
- async updateWorkflowResults({
394
- workflowName,
395
- runId,
396
- stepId,
397
- result,
398
- runtimeContext,
399
- }: {
400
- workflowName: string;
401
- runId: string;
402
- stepId: string;
403
- result: StepResult<any, any, any, any>;
404
- runtimeContext: Record<string, any>;
405
- }): Promise<Record<string, StepResult<any, any, any, any>>> {
406
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
407
- }
408
-
409
- async updateWorkflowState({
410
- workflowName,
411
- runId,
412
- opts,
413
- }: {
414
- workflowName: string;
415
- runId: string;
416
- opts: {
417
- status: string;
418
- result?: StepResult<any, any, any, any>;
419
- error?: string;
420
- suspendedPaths?: Record<string, number[]>;
421
- waitingPaths?: Record<string, number[]>;
422
- };
423
- }): Promise<WorkflowRunState | undefined> {
424
- return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
425
- }
426
-
427
- async persistWorkflowSnapshot({
428
- workflowName,
429
- runId,
430
- snapshot,
431
- }: {
432
- workflowName: string;
433
- runId: string;
434
- snapshot: WorkflowRunState;
435
- }): Promise<void> {
436
- return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
437
- }
438
-
439
- async loadWorkflowSnapshot({
440
- workflowName,
441
- runId,
442
- }: {
443
- workflowName: string;
444
- runId: string;
445
- }): Promise<WorkflowRunState | null> {
446
- return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
447
- }
448
-
449
- async getScoreById({ id: _id }: { id: string }): Promise<ScoreRowData | null> {
450
- return this.stores.scores.getScoreById({ id: _id });
451
- }
452
-
453
- async getScoresByScorerId({
454
- scorerId,
455
- source,
456
- entityId,
457
- entityType,
458
- pagination,
459
- }: {
460
- scorerId: string;
461
- pagination: StoragePagination;
462
- source?: ScoringSource;
463
- entityId?: string;
464
- entityType?: string;
465
- }): Promise<{ pagination: PaginationInfo; scores: ScoreRowData[] }> {
466
- return this.stores.scores.getScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
467
- }
468
-
469
- async saveScore(_score: ScoreRowData): Promise<{ score: ScoreRowData }> {
470
- return this.stores.scores.saveScore(_score);
471
- }
472
-
473
- async getScoresByRunId({
474
- runId,
475
- pagination,
476
- }: {
477
- runId: string;
478
- pagination: StoragePagination;
479
- }): Promise<{ pagination: PaginationInfo; scores: ScoreRowData[] }> {
480
- return this.stores.scores.getScoresByRunId({ runId, pagination });
481
- }
482
-
483
- async getScoresByEntityId({
484
- entityId,
485
- entityType,
486
- pagination,
487
- }: {
488
- pagination: StoragePagination;
489
- entityId: string;
490
- entityType: string;
491
- }): Promise<{ pagination: PaginationInfo; scores: ScoreRowData[] }> {
492
- return this.stores.scores.getScoresByEntityId({ entityId, entityType, pagination });
493
- }
494
- }