@mastra/lance 0.0.0-monorepo-binary-20251013210052 → 0.0.0-netlify-no-bundle-20251127120354
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 +474 -3
- package/README.md +61 -4
- package/dist/index.cjs +517 -694
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +517 -694
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +15 -39
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +6 -5
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/utils.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +4 -11
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +27 -88
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/filter.d.ts +5 -5
- package/dist/vector/index.d.ts +6 -3
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +15 -10
- package/dist/storage/domains/legacy-evals/index.d.ts +0 -25
- package/dist/storage/domains/legacy-evals/index.d.ts.map +0 -1
- package/dist/storage/domains/traces/index.d.ts +0 -34
- package/dist/storage/domains/traces/index.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,133 +1,17 @@
|
|
|
1
1
|
import { connect, Index } from '@lancedb/lancedb';
|
|
2
2
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
3
|
-
import { MastraStorage, StoreOperations,
|
|
3
|
+
import { MastraStorage, StoreOperations, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, normalizePerPage, calculatePagination, TABLE_RESOURCES, ScoresStorage, TABLE_SCORERS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, ensureDate } from '@mastra/core/storage';
|
|
4
4
|
import { MessageList } from '@mastra/core/agent';
|
|
5
5
|
import { Utf8, Float64, Binary, Float32, Int32, Field, Schema } from 'apache-arrow';
|
|
6
|
-
import { saveScorePayloadSchema } from '@mastra/core/
|
|
6
|
+
import { saveScorePayloadSchema } from '@mastra/core/evals';
|
|
7
7
|
import { MastraVector } from '@mastra/core/vector';
|
|
8
8
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
9
9
|
|
|
10
10
|
// src/storage/index.ts
|
|
11
|
-
var StoreLegacyEvalsLance = class extends LegacyEvalsStorage {
|
|
12
|
-
client;
|
|
13
|
-
constructor({ client }) {
|
|
14
|
-
super();
|
|
15
|
-
this.client = client;
|
|
16
|
-
}
|
|
17
|
-
async getEvalsByAgentName(agentName, type) {
|
|
18
|
-
try {
|
|
19
|
-
const table = await this.client.openTable(TABLE_EVALS);
|
|
20
|
-
const query = table.query().where(`agent_name = '${agentName}'`);
|
|
21
|
-
const records = await query.toArray();
|
|
22
|
-
let filteredRecords = records;
|
|
23
|
-
if (type === "live") {
|
|
24
|
-
filteredRecords = records.filter((record) => record.test_info === null);
|
|
25
|
-
} else if (type === "test") {
|
|
26
|
-
filteredRecords = records.filter((record) => record.test_info !== null);
|
|
27
|
-
}
|
|
28
|
-
return filteredRecords.map((record) => {
|
|
29
|
-
return {
|
|
30
|
-
id: record.id,
|
|
31
|
-
input: record.input,
|
|
32
|
-
output: record.output,
|
|
33
|
-
agentName: record.agent_name,
|
|
34
|
-
metricName: record.metric_name,
|
|
35
|
-
result: JSON.parse(record.result),
|
|
36
|
-
instructions: record.instructions,
|
|
37
|
-
testInfo: record.test_info ? JSON.parse(record.test_info) : null,
|
|
38
|
-
globalRunId: record.global_run_id,
|
|
39
|
-
runId: record.run_id,
|
|
40
|
-
createdAt: new Date(record.created_at).toString()
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
} catch (error) {
|
|
44
|
-
throw new MastraError(
|
|
45
|
-
{
|
|
46
|
-
id: "LANCE_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
|
|
47
|
-
domain: ErrorDomain.STORAGE,
|
|
48
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
49
|
-
details: { agentName }
|
|
50
|
-
},
|
|
51
|
-
error
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
async getEvals(options) {
|
|
56
|
-
try {
|
|
57
|
-
const table = await this.client.openTable(TABLE_EVALS);
|
|
58
|
-
const conditions = [];
|
|
59
|
-
if (options.agentName) {
|
|
60
|
-
conditions.push(`agent_name = '${options.agentName}'`);
|
|
61
|
-
}
|
|
62
|
-
if (options.type === "live") {
|
|
63
|
-
conditions.push("length(test_info) = 0");
|
|
64
|
-
} else if (options.type === "test") {
|
|
65
|
-
conditions.push("length(test_info) > 0");
|
|
66
|
-
}
|
|
67
|
-
const startDate = options.dateRange?.start || options.fromDate;
|
|
68
|
-
const endDate = options.dateRange?.end || options.toDate;
|
|
69
|
-
if (startDate) {
|
|
70
|
-
conditions.push(`\`created_at\` >= ${startDate.getTime()}`);
|
|
71
|
-
}
|
|
72
|
-
if (endDate) {
|
|
73
|
-
conditions.push(`\`created_at\` <= ${endDate.getTime()}`);
|
|
74
|
-
}
|
|
75
|
-
let total = 0;
|
|
76
|
-
if (conditions.length > 0) {
|
|
77
|
-
total = await table.countRows(conditions.join(" AND "));
|
|
78
|
-
} else {
|
|
79
|
-
total = await table.countRows();
|
|
80
|
-
}
|
|
81
|
-
const query = table.query();
|
|
82
|
-
if (conditions.length > 0) {
|
|
83
|
-
const whereClause = conditions.join(" AND ");
|
|
84
|
-
query.where(whereClause);
|
|
85
|
-
}
|
|
86
|
-
const records = await query.toArray();
|
|
87
|
-
const evals = records.sort((a, b) => b.created_at - a.created_at).map((record) => {
|
|
88
|
-
return {
|
|
89
|
-
id: record.id,
|
|
90
|
-
input: record.input,
|
|
91
|
-
output: record.output,
|
|
92
|
-
agentName: record.agent_name,
|
|
93
|
-
metricName: record.metric_name,
|
|
94
|
-
result: JSON.parse(record.result),
|
|
95
|
-
instructions: record.instructions,
|
|
96
|
-
testInfo: record.test_info ? JSON.parse(record.test_info) : null,
|
|
97
|
-
globalRunId: record.global_run_id,
|
|
98
|
-
runId: record.run_id,
|
|
99
|
-
createdAt: new Date(record.created_at).toISOString()
|
|
100
|
-
};
|
|
101
|
-
});
|
|
102
|
-
const page = options.page || 0;
|
|
103
|
-
const perPage = options.perPage || 10;
|
|
104
|
-
const pagedEvals = evals.slice(page * perPage, (page + 1) * perPage);
|
|
105
|
-
return {
|
|
106
|
-
evals: pagedEvals,
|
|
107
|
-
total,
|
|
108
|
-
page,
|
|
109
|
-
perPage,
|
|
110
|
-
hasMore: total > (page + 1) * perPage
|
|
111
|
-
};
|
|
112
|
-
} catch (error) {
|
|
113
|
-
throw new MastraError(
|
|
114
|
-
{
|
|
115
|
-
id: "LANCE_STORE_GET_EVALS_FAILED",
|
|
116
|
-
domain: ErrorDomain.STORAGE,
|
|
117
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
118
|
-
details: { agentName: options.agentName ?? "" }
|
|
119
|
-
},
|
|
120
|
-
error
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
11
|
function getPrimaryKeys(tableName) {
|
|
126
12
|
let primaryId = ["id"];
|
|
127
13
|
if (tableName === TABLE_WORKFLOW_SNAPSHOT) {
|
|
128
14
|
primaryId = ["workflow_name", "run_id"];
|
|
129
|
-
} else if (tableName === TABLE_EVALS) {
|
|
130
|
-
primaryId = ["agent_name", "metric_name", "run_id"];
|
|
131
15
|
}
|
|
132
16
|
return primaryId;
|
|
133
17
|
}
|
|
@@ -247,6 +131,10 @@ var StoreMemoryLance = class extends MemoryStorage {
|
|
|
247
131
|
this.client = client;
|
|
248
132
|
this.operations = operations;
|
|
249
133
|
}
|
|
134
|
+
// Utility to escape single quotes in SQL strings
|
|
135
|
+
escapeSql(str) {
|
|
136
|
+
return str.replace(/'/g, "''");
|
|
137
|
+
}
|
|
250
138
|
async getThreadById({ threadId }) {
|
|
251
139
|
try {
|
|
252
140
|
const thread = await this.operations.load({ tableName: TABLE_THREADS, keys: { id: threadId } });
|
|
@@ -269,26 +157,6 @@ var StoreMemoryLance = class extends MemoryStorage {
|
|
|
269
157
|
);
|
|
270
158
|
}
|
|
271
159
|
}
|
|
272
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
273
|
-
try {
|
|
274
|
-
const table = await this.client.openTable(TABLE_THREADS);
|
|
275
|
-
const query = table.query().where(`\`resourceId\` = '${resourceId}'`);
|
|
276
|
-
const records = await query.toArray();
|
|
277
|
-
return processResultWithTypeConversion(
|
|
278
|
-
records,
|
|
279
|
-
await getTableSchema({ tableName: TABLE_THREADS, client: this.client })
|
|
280
|
-
);
|
|
281
|
-
} catch (error) {
|
|
282
|
-
throw new MastraError(
|
|
283
|
-
{
|
|
284
|
-
id: "LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
285
|
-
domain: ErrorDomain.STORAGE,
|
|
286
|
-
category: ErrorCategory.THIRD_PARTY
|
|
287
|
-
},
|
|
288
|
-
error
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
160
|
/**
|
|
293
161
|
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
294
162
|
* @param thread - The thread to save
|
|
@@ -393,100 +261,174 @@ var StoreMemoryLance = class extends MemoryStorage {
|
|
|
393
261
|
})() : message.content
|
|
394
262
|
};
|
|
395
263
|
}
|
|
396
|
-
async
|
|
397
|
-
|
|
398
|
-
resourceId,
|
|
399
|
-
selectBy,
|
|
400
|
-
format,
|
|
401
|
-
threadConfig
|
|
402
|
-
}) {
|
|
264
|
+
async listMessagesById({ messageIds }) {
|
|
265
|
+
if (messageIds.length === 0) return { messages: [] };
|
|
403
266
|
try {
|
|
404
|
-
if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
|
|
405
|
-
if (threadConfig) {
|
|
406
|
-
throw new Error("ThreadConfig is not supported by LanceDB storage");
|
|
407
|
-
}
|
|
408
|
-
const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
|
|
409
267
|
const table = await this.client.openTable(TABLE_MESSAGES);
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
413
|
-
for (const threadId2 of threadIds) {
|
|
414
|
-
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
415
|
-
let threadRecords = await threadQuery.toArray();
|
|
416
|
-
allRecords.push(...threadRecords);
|
|
417
|
-
}
|
|
418
|
-
} else {
|
|
419
|
-
let query = table.query().where(`\`thread_id\` = '${threadId}'`);
|
|
420
|
-
allRecords = await query.toArray();
|
|
421
|
-
}
|
|
422
|
-
allRecords.sort((a, b) => {
|
|
423
|
-
const dateA = new Date(a.createdAt).getTime();
|
|
424
|
-
const dateB = new Date(b.createdAt).getTime();
|
|
425
|
-
return dateA - dateB;
|
|
426
|
-
});
|
|
427
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
428
|
-
allRecords = this.processMessagesWithContext(allRecords, selectBy.include);
|
|
429
|
-
}
|
|
430
|
-
if (limit !== Number.MAX_SAFE_INTEGER) {
|
|
431
|
-
allRecords = allRecords.slice(-limit);
|
|
432
|
-
}
|
|
268
|
+
const quotedIds = messageIds.map((id) => `'${id}'`).join(", ");
|
|
269
|
+
const allRecords = await table.query().where(`id IN (${quotedIds})`).toArray();
|
|
433
270
|
const messages = processResultWithTypeConversion(
|
|
434
271
|
allRecords,
|
|
435
272
|
await getTableSchema({ tableName: TABLE_MESSAGES, client: this.client })
|
|
436
273
|
);
|
|
437
|
-
const list = new MessageList(
|
|
438
|
-
|
|
439
|
-
|
|
274
|
+
const list = new MessageList().add(
|
|
275
|
+
messages.map(this.normalizeMessage),
|
|
276
|
+
"memory"
|
|
277
|
+
);
|
|
278
|
+
return { messages: list.get.all.db() };
|
|
440
279
|
} catch (error) {
|
|
441
280
|
throw new MastraError(
|
|
442
281
|
{
|
|
443
|
-
id: "
|
|
282
|
+
id: "LANCE_STORE_LIST_MESSAGES_BY_ID_FAILED",
|
|
444
283
|
domain: ErrorDomain.STORAGE,
|
|
445
284
|
category: ErrorCategory.THIRD_PARTY,
|
|
446
285
|
details: {
|
|
447
|
-
|
|
448
|
-
resourceId: resourceId ?? ""
|
|
286
|
+
messageIds: JSON.stringify(messageIds)
|
|
449
287
|
}
|
|
450
288
|
},
|
|
451
289
|
error
|
|
452
290
|
);
|
|
453
291
|
}
|
|
454
292
|
}
|
|
455
|
-
async
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
293
|
+
async listMessages(args) {
|
|
294
|
+
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
295
|
+
if (!threadId.trim()) {
|
|
296
|
+
throw new MastraError(
|
|
297
|
+
{
|
|
298
|
+
id: "STORAGE_LANCE_LIST_MESSAGES_INVALID_THREAD_ID",
|
|
299
|
+
domain: ErrorDomain.STORAGE,
|
|
300
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
301
|
+
details: { threadId }
|
|
302
|
+
},
|
|
303
|
+
new Error("threadId must be a non-empty string")
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
const perPage = normalizePerPage(perPageInput, 40);
|
|
307
|
+
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
460
308
|
try {
|
|
309
|
+
if (page < 0) {
|
|
310
|
+
throw new MastraError(
|
|
311
|
+
{
|
|
312
|
+
id: "STORAGE_LANCE_LIST_MESSAGES_INVALID_PAGE",
|
|
313
|
+
domain: ErrorDomain.STORAGE,
|
|
314
|
+
category: ErrorCategory.USER,
|
|
315
|
+
details: { page }
|
|
316
|
+
},
|
|
317
|
+
new Error("page must be >= 0")
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
461
321
|
const table = await this.client.openTable(TABLE_MESSAGES);
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
322
|
+
const conditions = [`thread_id = '${this.escapeSql(threadId)}'`];
|
|
323
|
+
if (resourceId) {
|
|
324
|
+
conditions.push(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
325
|
+
}
|
|
326
|
+
if (filter?.dateRange?.start) {
|
|
327
|
+
const startTime = filter.dateRange.start instanceof Date ? filter.dateRange.start.getTime() : new Date(filter.dateRange.start).getTime();
|
|
328
|
+
conditions.push(`\`createdAt\` >= ${startTime}`);
|
|
329
|
+
}
|
|
330
|
+
if (filter?.dateRange?.end) {
|
|
331
|
+
const endTime = filter.dateRange.end instanceof Date ? filter.dateRange.end.getTime() : new Date(filter.dateRange.end).getTime();
|
|
332
|
+
conditions.push(`\`createdAt\` <= ${endTime}`);
|
|
333
|
+
}
|
|
334
|
+
const whereClause = conditions.join(" AND ");
|
|
335
|
+
const total = await table.countRows(whereClause);
|
|
336
|
+
const query = table.query().where(whereClause);
|
|
337
|
+
let allRecords = await query.toArray();
|
|
338
|
+
allRecords.sort((a, b) => {
|
|
339
|
+
const aValue = field === "createdAt" ? a.createdAt : a[field];
|
|
340
|
+
const bValue = field === "createdAt" ? b.createdAt : b[field];
|
|
341
|
+
if (aValue == null && bValue == null) return 0;
|
|
342
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
343
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
344
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
345
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
346
|
+
}
|
|
347
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
348
|
+
});
|
|
349
|
+
const paginatedRecords = allRecords.slice(offset, offset + perPage);
|
|
350
|
+
const messages = paginatedRecords.map((row) => this.normalizeMessage(row));
|
|
351
|
+
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
352
|
+
return {
|
|
353
|
+
messages: [],
|
|
354
|
+
total: 0,
|
|
355
|
+
page,
|
|
356
|
+
perPage: perPageForResponse,
|
|
357
|
+
hasMore: false
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const messageIds = new Set(messages.map((m) => m.id));
|
|
361
|
+
if (include && include.length > 0) {
|
|
362
|
+
const threadIds = [...new Set(include.map((item) => item.threadId || threadId))];
|
|
363
|
+
const allThreadMessages = [];
|
|
364
|
+
for (const tid of threadIds) {
|
|
365
|
+
const threadQuery = table.query().where(`thread_id = '${tid}'`);
|
|
366
|
+
let threadRecords = await threadQuery.toArray();
|
|
367
|
+
allThreadMessages.push(...threadRecords);
|
|
368
|
+
}
|
|
369
|
+
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
370
|
+
const contextMessages = this.processMessagesWithContext(allThreadMessages, include);
|
|
371
|
+
const includedMessages = contextMessages.map((row) => this.normalizeMessage(row));
|
|
372
|
+
for (const includeMsg of includedMessages) {
|
|
373
|
+
if (!messageIds.has(includeMsg.id)) {
|
|
374
|
+
messages.push(includeMsg);
|
|
375
|
+
messageIds.add(includeMsg.id);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
const list = new MessageList().add(messages, "memory");
|
|
380
|
+
let finalMessages = list.get.all.db();
|
|
381
|
+
finalMessages = finalMessages.sort((a, b) => {
|
|
382
|
+
const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
|
|
383
|
+
const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
|
|
384
|
+
if (aValue == null && bValue == null) return 0;
|
|
385
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
386
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
387
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
388
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
389
|
+
}
|
|
390
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
391
|
+
});
|
|
392
|
+
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
393
|
+
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
394
|
+
const fetchedAll = perPageInput === false || allThreadMessagesReturned;
|
|
395
|
+
const hasMore = !fetchedAll && offset + perPage < total;
|
|
396
|
+
return {
|
|
397
|
+
messages: finalMessages,
|
|
398
|
+
total,
|
|
399
|
+
page,
|
|
400
|
+
perPage: perPageForResponse,
|
|
401
|
+
hasMore
|
|
402
|
+
};
|
|
471
403
|
} catch (error) {
|
|
472
|
-
|
|
404
|
+
const mastraError = new MastraError(
|
|
473
405
|
{
|
|
474
|
-
id: "
|
|
406
|
+
id: "LANCE_STORE_LIST_MESSAGES_FAILED",
|
|
475
407
|
domain: ErrorDomain.STORAGE,
|
|
476
408
|
category: ErrorCategory.THIRD_PARTY,
|
|
477
409
|
details: {
|
|
478
|
-
|
|
410
|
+
threadId,
|
|
411
|
+
resourceId: resourceId ?? ""
|
|
479
412
|
}
|
|
480
413
|
},
|
|
481
414
|
error
|
|
482
415
|
);
|
|
416
|
+
this.logger?.error?.(mastraError.toString());
|
|
417
|
+
this.logger?.trackException?.(mastraError);
|
|
418
|
+
return {
|
|
419
|
+
messages: [],
|
|
420
|
+
total: 0,
|
|
421
|
+
page,
|
|
422
|
+
perPage: perPageForResponse,
|
|
423
|
+
hasMore: false
|
|
424
|
+
};
|
|
483
425
|
}
|
|
484
426
|
}
|
|
485
427
|
async saveMessages(args) {
|
|
486
428
|
try {
|
|
487
|
-
const { messages
|
|
429
|
+
const { messages } = args;
|
|
488
430
|
if (messages.length === 0) {
|
|
489
|
-
return [];
|
|
431
|
+
return { messages: [] };
|
|
490
432
|
}
|
|
491
433
|
const threadId = messages[0]?.threadId;
|
|
492
434
|
if (!threadId) {
|
|
@@ -522,8 +464,7 @@ var StoreMemoryLance = class extends MemoryStorage {
|
|
|
522
464
|
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
523
465
|
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
524
466
|
const list = new MessageList().add(messages, "memory");
|
|
525
|
-
|
|
526
|
-
return list.get.all.v1();
|
|
467
|
+
return { messages: list.get.all.db() };
|
|
527
468
|
} catch (error) {
|
|
528
469
|
throw new MastraError(
|
|
529
470
|
{
|
|
@@ -535,32 +476,54 @@ var StoreMemoryLance = class extends MemoryStorage {
|
|
|
535
476
|
);
|
|
536
477
|
}
|
|
537
478
|
}
|
|
538
|
-
async
|
|
479
|
+
async listThreadsByResourceId(args) {
|
|
539
480
|
try {
|
|
540
|
-
const { resourceId, page = 0, perPage
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
481
|
+
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
482
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
483
|
+
if (page < 0) {
|
|
484
|
+
throw new MastraError(
|
|
485
|
+
{
|
|
486
|
+
id: "STORAGE_LANCE_LIST_THREADS_BY_RESOURCE_ID_INVALID_PAGE",
|
|
487
|
+
domain: ErrorDomain.STORAGE,
|
|
488
|
+
category: ErrorCategory.USER,
|
|
489
|
+
details: { page }
|
|
490
|
+
},
|
|
491
|
+
new Error("page must be >= 0")
|
|
492
|
+
);
|
|
548
493
|
}
|
|
494
|
+
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
495
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
496
|
+
const table = await this.client.openTable(TABLE_THREADS);
|
|
497
|
+
const total = await table.countRows(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
498
|
+
const query = table.query().where(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
|
|
549
499
|
const records = await query.toArray();
|
|
550
|
-
records.sort((a, b) =>
|
|
500
|
+
records.sort((a, b) => {
|
|
501
|
+
const aValue = ["createdAt", "updatedAt"].includes(field) ? new Date(a[field]).getTime() : a[field];
|
|
502
|
+
const bValue = ["createdAt", "updatedAt"].includes(field) ? new Date(b[field]).getTime() : b[field];
|
|
503
|
+
if (aValue == null && bValue == null) return 0;
|
|
504
|
+
if (aValue == null) return direction === "ASC" ? -1 : 1;
|
|
505
|
+
if (bValue == null) return direction === "ASC" ? 1 : -1;
|
|
506
|
+
if (typeof aValue === "string" && typeof bValue === "string") {
|
|
507
|
+
return direction === "ASC" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
508
|
+
}
|
|
509
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
510
|
+
});
|
|
511
|
+
const paginatedRecords = records.slice(offset, offset + perPage);
|
|
551
512
|
const schema = await getTableSchema({ tableName: TABLE_THREADS, client: this.client });
|
|
552
|
-
const threads =
|
|
513
|
+
const threads = paginatedRecords.map(
|
|
514
|
+
(record) => processResultWithTypeConversion(record, schema)
|
|
515
|
+
);
|
|
553
516
|
return {
|
|
554
517
|
threads,
|
|
555
518
|
total,
|
|
556
519
|
page,
|
|
557
|
-
perPage,
|
|
558
|
-
hasMore:
|
|
520
|
+
perPage: perPageForResponse,
|
|
521
|
+
hasMore: offset + perPage < total
|
|
559
522
|
};
|
|
560
523
|
} catch (error) {
|
|
561
524
|
throw new MastraError(
|
|
562
525
|
{
|
|
563
|
-
id: "
|
|
526
|
+
id: "LANCE_STORE_LIST_THREADS_BY_RESOURCE_ID_FAILED",
|
|
564
527
|
domain: ErrorDomain.STORAGE,
|
|
565
528
|
category: ErrorCategory.THIRD_PARTY
|
|
566
529
|
},
|
|
@@ -616,132 +579,8 @@ var StoreMemoryLance = class extends MemoryStorage {
|
|
|
616
579
|
});
|
|
617
580
|
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
618
581
|
}
|
|
619
|
-
async getMessagesPaginated(args) {
|
|
620
|
-
const { threadId, resourceId, selectBy, format = "v1" } = args;
|
|
621
|
-
const page = selectBy?.pagination?.page ?? 0;
|
|
622
|
-
const perPage = selectBy?.pagination?.perPage ?? 10;
|
|
623
|
-
try {
|
|
624
|
-
if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
|
|
625
|
-
const dateRange = selectBy?.pagination?.dateRange;
|
|
626
|
-
const fromDate = dateRange?.start;
|
|
627
|
-
const toDate = dateRange?.end;
|
|
628
|
-
const table = await this.client.openTable(TABLE_MESSAGES);
|
|
629
|
-
const messages = [];
|
|
630
|
-
if (selectBy?.include && Array.isArray(selectBy.include)) {
|
|
631
|
-
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
632
|
-
const allThreadMessages = [];
|
|
633
|
-
for (const threadId2 of threadIds) {
|
|
634
|
-
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
635
|
-
let threadRecords = await threadQuery.toArray();
|
|
636
|
-
if (fromDate) threadRecords = threadRecords.filter((m) => m.createdAt >= fromDate.getTime());
|
|
637
|
-
if (toDate) threadRecords = threadRecords.filter((m) => m.createdAt <= toDate.getTime());
|
|
638
|
-
allThreadMessages.push(...threadRecords);
|
|
639
|
-
}
|
|
640
|
-
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
641
|
-
const contextMessages = this.processMessagesWithContext(allThreadMessages, selectBy.include);
|
|
642
|
-
messages.push(...contextMessages);
|
|
643
|
-
}
|
|
644
|
-
const conditions = [`thread_id = '${threadId}'`];
|
|
645
|
-
if (resourceId) {
|
|
646
|
-
conditions.push(`\`resourceId\` = '${resourceId}'`);
|
|
647
|
-
}
|
|
648
|
-
if (fromDate) {
|
|
649
|
-
conditions.push(`\`createdAt\` >= ${fromDate.getTime()}`);
|
|
650
|
-
}
|
|
651
|
-
if (toDate) {
|
|
652
|
-
conditions.push(`\`createdAt\` <= ${toDate.getTime()}`);
|
|
653
|
-
}
|
|
654
|
-
let total = 0;
|
|
655
|
-
if (conditions.length > 0) {
|
|
656
|
-
total = await table.countRows(conditions.join(" AND "));
|
|
657
|
-
} else {
|
|
658
|
-
total = await table.countRows();
|
|
659
|
-
}
|
|
660
|
-
if (total === 0 && messages.length === 0) {
|
|
661
|
-
return {
|
|
662
|
-
messages: [],
|
|
663
|
-
total: 0,
|
|
664
|
-
page,
|
|
665
|
-
perPage,
|
|
666
|
-
hasMore: false
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
const excludeIds = messages.map((m) => m.id);
|
|
670
|
-
let selectedMessages = [];
|
|
671
|
-
if (selectBy?.last && selectBy.last > 0) {
|
|
672
|
-
const query = table.query();
|
|
673
|
-
if (conditions.length > 0) {
|
|
674
|
-
query.where(conditions.join(" AND "));
|
|
675
|
-
}
|
|
676
|
-
let records = await query.toArray();
|
|
677
|
-
records = records.sort((a, b) => a.createdAt - b.createdAt);
|
|
678
|
-
if (excludeIds.length > 0) {
|
|
679
|
-
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
680
|
-
}
|
|
681
|
-
selectedMessages = records.slice(-selectBy.last);
|
|
682
|
-
} else {
|
|
683
|
-
const query = table.query();
|
|
684
|
-
if (conditions.length > 0) {
|
|
685
|
-
query.where(conditions.join(" AND "));
|
|
686
|
-
}
|
|
687
|
-
let records = await query.toArray();
|
|
688
|
-
records = records.sort((a, b) => a.createdAt - b.createdAt);
|
|
689
|
-
if (excludeIds.length > 0) {
|
|
690
|
-
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
691
|
-
}
|
|
692
|
-
selectedMessages = records.slice(page * perPage, (page + 1) * perPage);
|
|
693
|
-
}
|
|
694
|
-
const allMessages = [...messages, ...selectedMessages];
|
|
695
|
-
const seen = /* @__PURE__ */ new Set();
|
|
696
|
-
const dedupedMessages = allMessages.filter((m) => {
|
|
697
|
-
const key = `${m.id}:${m.thread_id}`;
|
|
698
|
-
if (seen.has(key)) return false;
|
|
699
|
-
seen.add(key);
|
|
700
|
-
return true;
|
|
701
|
-
});
|
|
702
|
-
const formattedMessages = dedupedMessages.map((msg) => {
|
|
703
|
-
const { thread_id, ...rest } = msg;
|
|
704
|
-
return {
|
|
705
|
-
...rest,
|
|
706
|
-
threadId: thread_id,
|
|
707
|
-
content: typeof msg.content === "string" ? (() => {
|
|
708
|
-
try {
|
|
709
|
-
return JSON.parse(msg.content);
|
|
710
|
-
} catch {
|
|
711
|
-
return msg.content;
|
|
712
|
-
}
|
|
713
|
-
})() : msg.content
|
|
714
|
-
};
|
|
715
|
-
});
|
|
716
|
-
const list = new MessageList().add(formattedMessages, "memory");
|
|
717
|
-
return {
|
|
718
|
-
messages: format === "v2" ? list.get.all.v2() : list.get.all.v1(),
|
|
719
|
-
total,
|
|
720
|
-
// Total should be the count of messages matching the filters
|
|
721
|
-
page,
|
|
722
|
-
perPage,
|
|
723
|
-
hasMore: total > (page + 1) * perPage
|
|
724
|
-
};
|
|
725
|
-
} catch (error) {
|
|
726
|
-
const mastraError = new MastraError(
|
|
727
|
-
{
|
|
728
|
-
id: "LANCE_STORE_GET_MESSAGES_PAGINATED_FAILED",
|
|
729
|
-
domain: ErrorDomain.STORAGE,
|
|
730
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
731
|
-
details: {
|
|
732
|
-
threadId,
|
|
733
|
-
resourceId: resourceId ?? ""
|
|
734
|
-
}
|
|
735
|
-
},
|
|
736
|
-
error
|
|
737
|
-
);
|
|
738
|
-
this.logger?.trackException?.(mastraError);
|
|
739
|
-
this.logger?.error?.(mastraError.toString());
|
|
740
|
-
return { messages: [], total: 0, page, perPage, hasMore: false };
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
582
|
/**
|
|
744
|
-
* Parse message data from LanceDB record format to
|
|
583
|
+
* Parse message data from LanceDB record format to MastraDBMessage format
|
|
745
584
|
*/
|
|
746
585
|
parseMessageData(data) {
|
|
747
586
|
const { thread_id, ...rest } = data;
|
|
@@ -1427,6 +1266,8 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1427
1266
|
filteredScore[key] = JSON.stringify(filteredScore[key]);
|
|
1428
1267
|
}
|
|
1429
1268
|
}
|
|
1269
|
+
filteredScore.createdAt = /* @__PURE__ */ new Date();
|
|
1270
|
+
filteredScore.updatedAt = /* @__PURE__ */ new Date();
|
|
1430
1271
|
filteredScore.id = id;
|
|
1431
1272
|
await table.add([filteredScore], { mode: "append" });
|
|
1432
1273
|
return { score };
|
|
@@ -1449,8 +1290,7 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1449
1290
|
const query = table.query().where(`id = '${id}'`).limit(1);
|
|
1450
1291
|
const records = await query.toArray();
|
|
1451
1292
|
if (records.length === 0) return null;
|
|
1452
|
-
|
|
1453
|
-
return processResultWithTypeConversion(records[0], schema);
|
|
1293
|
+
return await this.transformScoreRow(records[0]);
|
|
1454
1294
|
} catch (error) {
|
|
1455
1295
|
throw new MastraError(
|
|
1456
1296
|
{
|
|
@@ -1464,7 +1304,17 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1464
1304
|
);
|
|
1465
1305
|
}
|
|
1466
1306
|
}
|
|
1467
|
-
async
|
|
1307
|
+
async transformScoreRow(row) {
|
|
1308
|
+
const schema = await getTableSchema({ tableName: TABLE_SCORERS, client: this.client });
|
|
1309
|
+
const transformed = processResultWithTypeConversion(row, schema);
|
|
1310
|
+
const result = {
|
|
1311
|
+
...transformed,
|
|
1312
|
+
createdAt: row.createdAt,
|
|
1313
|
+
updatedAt: row.updatedAt
|
|
1314
|
+
};
|
|
1315
|
+
return result;
|
|
1316
|
+
}
|
|
1317
|
+
async listScoresByScorerId({
|
|
1468
1318
|
scorerId,
|
|
1469
1319
|
pagination,
|
|
1470
1320
|
entityId,
|
|
@@ -1472,9 +1322,10 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1472
1322
|
source
|
|
1473
1323
|
}) {
|
|
1474
1324
|
try {
|
|
1325
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1326
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
1327
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1475
1328
|
const table = await this.client.openTable(TABLE_SCORERS);
|
|
1476
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1477
|
-
const offset = page * perPage;
|
|
1478
1329
|
let query = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1479
1330
|
if (source) {
|
|
1480
1331
|
query = query.where(`\`source\` = '${source}'`);
|
|
@@ -1485,23 +1336,31 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1485
1336
|
if (entityType) {
|
|
1486
1337
|
query = query.where(`\`entityType\` = '${entityType}'`);
|
|
1487
1338
|
}
|
|
1488
|
-
query = query.limit(perPage);
|
|
1489
|
-
if (offset > 0) query.offset(offset);
|
|
1490
|
-
const records = await query.toArray();
|
|
1491
|
-
const schema = await getTableSchema({ tableName: TABLE_SCORERS, client: this.client });
|
|
1492
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1493
1339
|
let totalQuery = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1494
1340
|
if (source) {
|
|
1495
1341
|
totalQuery = totalQuery.where(`\`source\` = '${source}'`);
|
|
1496
1342
|
}
|
|
1343
|
+
if (entityId) {
|
|
1344
|
+
totalQuery = totalQuery.where(`\`entityId\` = '${entityId}'`);
|
|
1345
|
+
}
|
|
1346
|
+
if (entityType) {
|
|
1347
|
+
totalQuery = totalQuery.where(`\`entityType\` = '${entityType}'`);
|
|
1348
|
+
}
|
|
1497
1349
|
const allRecords = await totalQuery.toArray();
|
|
1498
1350
|
const total = allRecords.length;
|
|
1351
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1352
|
+
if (perPageInput !== false) {
|
|
1353
|
+
query = query.limit(perPage);
|
|
1354
|
+
if (start > 0) query = query.offset(start);
|
|
1355
|
+
}
|
|
1356
|
+
const records = await query.toArray();
|
|
1357
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1499
1358
|
return {
|
|
1500
1359
|
pagination: {
|
|
1501
1360
|
page,
|
|
1502
|
-
perPage,
|
|
1361
|
+
perPage: perPageForResponse,
|
|
1503
1362
|
total,
|
|
1504
|
-
hasMore:
|
|
1363
|
+
hasMore: end < total
|
|
1505
1364
|
},
|
|
1506
1365
|
scores
|
|
1507
1366
|
};
|
|
@@ -1518,27 +1377,31 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1518
1377
|
);
|
|
1519
1378
|
}
|
|
1520
1379
|
}
|
|
1521
|
-
async
|
|
1380
|
+
async listScoresByRunId({
|
|
1522
1381
|
runId,
|
|
1523
1382
|
pagination
|
|
1524
1383
|
}) {
|
|
1525
1384
|
try {
|
|
1385
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1386
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
1387
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1526
1388
|
const table = await this.client.openTable(TABLE_SCORERS);
|
|
1527
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1528
|
-
const offset = page * perPage;
|
|
1529
|
-
const query = table.query().where(`\`runId\` = '${runId}'`).limit(perPage);
|
|
1530
|
-
if (offset > 0) query.offset(offset);
|
|
1531
|
-
const records = await query.toArray();
|
|
1532
|
-
const schema = await getTableSchema({ tableName: TABLE_SCORERS, client: this.client });
|
|
1533
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1534
1389
|
const allRecords = await table.query().where(`\`runId\` = '${runId}'`).toArray();
|
|
1535
1390
|
const total = allRecords.length;
|
|
1391
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1392
|
+
let query = table.query().where(`\`runId\` = '${runId}'`);
|
|
1393
|
+
if (perPageInput !== false) {
|
|
1394
|
+
query = query.limit(perPage);
|
|
1395
|
+
if (start > 0) query = query.offset(start);
|
|
1396
|
+
}
|
|
1397
|
+
const records = await query.toArray();
|
|
1398
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1536
1399
|
return {
|
|
1537
1400
|
pagination: {
|
|
1538
1401
|
page,
|
|
1539
|
-
perPage,
|
|
1402
|
+
perPage: perPageForResponse,
|
|
1540
1403
|
total,
|
|
1541
|
-
hasMore:
|
|
1404
|
+
hasMore: end < total
|
|
1542
1405
|
},
|
|
1543
1406
|
scores
|
|
1544
1407
|
};
|
|
@@ -1555,28 +1418,32 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1555
1418
|
);
|
|
1556
1419
|
}
|
|
1557
1420
|
}
|
|
1558
|
-
async
|
|
1421
|
+
async listScoresByEntityId({
|
|
1559
1422
|
entityId,
|
|
1560
1423
|
entityType,
|
|
1561
1424
|
pagination
|
|
1562
1425
|
}) {
|
|
1563
1426
|
try {
|
|
1427
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1428
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
1429
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1564
1430
|
const table = await this.client.openTable(TABLE_SCORERS);
|
|
1565
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1566
|
-
const offset = page * perPage;
|
|
1567
|
-
const query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).limit(perPage);
|
|
1568
|
-
if (offset > 0) query.offset(offset);
|
|
1569
|
-
const records = await query.toArray();
|
|
1570
|
-
const schema = await getTableSchema({ tableName: TABLE_SCORERS, client: this.client });
|
|
1571
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1572
1431
|
const allRecords = await table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).toArray();
|
|
1573
1432
|
const total = allRecords.length;
|
|
1433
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1434
|
+
let query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`);
|
|
1435
|
+
if (perPageInput !== false) {
|
|
1436
|
+
query = query.limit(perPage);
|
|
1437
|
+
if (start > 0) query = query.offset(start);
|
|
1438
|
+
}
|
|
1439
|
+
const records = await query.toArray();
|
|
1440
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1574
1441
|
return {
|
|
1575
1442
|
pagination: {
|
|
1576
1443
|
page,
|
|
1577
|
-
perPage,
|
|
1444
|
+
perPage: perPageForResponse,
|
|
1578
1445
|
total,
|
|
1579
|
-
hasMore:
|
|
1446
|
+
hasMore: end < total
|
|
1580
1447
|
},
|
|
1581
1448
|
scores
|
|
1582
1449
|
};
|
|
@@ -1593,28 +1460,32 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1593
1460
|
);
|
|
1594
1461
|
}
|
|
1595
1462
|
}
|
|
1596
|
-
async
|
|
1463
|
+
async listScoresBySpan({
|
|
1597
1464
|
traceId,
|
|
1598
1465
|
spanId,
|
|
1599
1466
|
pagination
|
|
1600
1467
|
}) {
|
|
1601
1468
|
try {
|
|
1469
|
+
const { page, perPage: perPageInput } = pagination;
|
|
1470
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
1471
|
+
const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1602
1472
|
const table = await this.client.openTable(TABLE_SCORERS);
|
|
1603
|
-
const { page = 0, perPage = 10 } = pagination || {};
|
|
1604
|
-
const offset = page * perPage;
|
|
1605
|
-
const query = table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`).limit(perPage);
|
|
1606
|
-
if (offset > 0) query.offset(offset);
|
|
1607
|
-
const records = await query.toArray();
|
|
1608
|
-
const schema = await getTableSchema({ tableName: TABLE_SCORERS, client: this.client });
|
|
1609
|
-
const scores = processResultWithTypeConversion(records, schema);
|
|
1610
1473
|
const allRecords = await table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`).toArray();
|
|
1611
1474
|
const total = allRecords.length;
|
|
1475
|
+
const end = perPageInput === false ? total : start + perPage;
|
|
1476
|
+
let query = table.query().where(`\`traceId\` = '${traceId}' AND \`spanId\` = '${spanId}'`);
|
|
1477
|
+
if (perPageInput !== false) {
|
|
1478
|
+
query = query.limit(perPage);
|
|
1479
|
+
if (start > 0) query = query.offset(start);
|
|
1480
|
+
}
|
|
1481
|
+
const records = await query.toArray();
|
|
1482
|
+
const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
|
|
1612
1483
|
return {
|
|
1613
1484
|
pagination: {
|
|
1614
1485
|
page,
|
|
1615
|
-
perPage,
|
|
1486
|
+
perPage: perPageForResponse,
|
|
1616
1487
|
total,
|
|
1617
|
-
hasMore:
|
|
1488
|
+
hasMore: end < total
|
|
1618
1489
|
},
|
|
1619
1490
|
scores
|
|
1620
1491
|
};
|
|
@@ -1632,198 +1503,6 @@ var StoreScoresLance = class extends ScoresStorage {
|
|
|
1632
1503
|
}
|
|
1633
1504
|
}
|
|
1634
1505
|
};
|
|
1635
|
-
var StoreTracesLance = class extends TracesStorage {
|
|
1636
|
-
client;
|
|
1637
|
-
operations;
|
|
1638
|
-
constructor({ client, operations }) {
|
|
1639
|
-
super();
|
|
1640
|
-
this.client = client;
|
|
1641
|
-
this.operations = operations;
|
|
1642
|
-
}
|
|
1643
|
-
async saveTrace({ trace }) {
|
|
1644
|
-
try {
|
|
1645
|
-
const table = await this.client.openTable(TABLE_TRACES);
|
|
1646
|
-
const record = {
|
|
1647
|
-
...trace,
|
|
1648
|
-
attributes: JSON.stringify(trace.attributes),
|
|
1649
|
-
status: JSON.stringify(trace.status),
|
|
1650
|
-
events: JSON.stringify(trace.events),
|
|
1651
|
-
links: JSON.stringify(trace.links),
|
|
1652
|
-
other: JSON.stringify(trace.other)
|
|
1653
|
-
};
|
|
1654
|
-
await table.add([record], { mode: "append" });
|
|
1655
|
-
return trace;
|
|
1656
|
-
} catch (error) {
|
|
1657
|
-
throw new MastraError(
|
|
1658
|
-
{
|
|
1659
|
-
id: "LANCE_STORE_SAVE_TRACE_FAILED",
|
|
1660
|
-
domain: ErrorDomain.STORAGE,
|
|
1661
|
-
category: ErrorCategory.THIRD_PARTY
|
|
1662
|
-
},
|
|
1663
|
-
error
|
|
1664
|
-
);
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
async getTraceById({ traceId }) {
|
|
1668
|
-
try {
|
|
1669
|
-
const table = await this.client.openTable(TABLE_TRACES);
|
|
1670
|
-
const query = table.query().where(`id = '${traceId}'`);
|
|
1671
|
-
const records = await query.toArray();
|
|
1672
|
-
return records[0];
|
|
1673
|
-
} catch (error) {
|
|
1674
|
-
throw new MastraError(
|
|
1675
|
-
{
|
|
1676
|
-
id: "LANCE_STORE_GET_TRACE_BY_ID_FAILED",
|
|
1677
|
-
domain: ErrorDomain.STORAGE,
|
|
1678
|
-
category: ErrorCategory.THIRD_PARTY
|
|
1679
|
-
},
|
|
1680
|
-
error
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
async getTraces({
|
|
1685
|
-
name,
|
|
1686
|
-
scope,
|
|
1687
|
-
page = 1,
|
|
1688
|
-
perPage = 10,
|
|
1689
|
-
attributes
|
|
1690
|
-
}) {
|
|
1691
|
-
try {
|
|
1692
|
-
const table = await this.client.openTable(TABLE_TRACES);
|
|
1693
|
-
const query = table.query();
|
|
1694
|
-
if (name) {
|
|
1695
|
-
query.where(`name = '${name}'`);
|
|
1696
|
-
}
|
|
1697
|
-
if (scope) {
|
|
1698
|
-
query.where(`scope = '${scope}'`);
|
|
1699
|
-
}
|
|
1700
|
-
if (attributes) {
|
|
1701
|
-
query.where(`attributes = '${JSON.stringify(attributes)}'`);
|
|
1702
|
-
}
|
|
1703
|
-
const offset = (page - 1) * perPage;
|
|
1704
|
-
query.limit(perPage);
|
|
1705
|
-
if (offset > 0) {
|
|
1706
|
-
query.offset(offset);
|
|
1707
|
-
}
|
|
1708
|
-
const records = await query.toArray();
|
|
1709
|
-
return records.map((record) => {
|
|
1710
|
-
const processed = {
|
|
1711
|
-
...record,
|
|
1712
|
-
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1713
|
-
status: record.status ? JSON.parse(record.status) : {},
|
|
1714
|
-
events: record.events ? JSON.parse(record.events) : [],
|
|
1715
|
-
links: record.links ? JSON.parse(record.links) : [],
|
|
1716
|
-
other: record.other ? JSON.parse(record.other) : {},
|
|
1717
|
-
startTime: new Date(record.startTime),
|
|
1718
|
-
endTime: new Date(record.endTime),
|
|
1719
|
-
createdAt: new Date(record.createdAt)
|
|
1720
|
-
};
|
|
1721
|
-
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1722
|
-
processed.parentSpanId = "";
|
|
1723
|
-
} else {
|
|
1724
|
-
processed.parentSpanId = String(processed.parentSpanId);
|
|
1725
|
-
}
|
|
1726
|
-
return processed;
|
|
1727
|
-
});
|
|
1728
|
-
} catch (error) {
|
|
1729
|
-
throw new MastraError(
|
|
1730
|
-
{
|
|
1731
|
-
id: "LANCE_STORE_GET_TRACES_FAILED",
|
|
1732
|
-
domain: ErrorDomain.STORAGE,
|
|
1733
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1734
|
-
details: { name: name ?? "", scope: scope ?? "" }
|
|
1735
|
-
},
|
|
1736
|
-
error
|
|
1737
|
-
);
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
async getTracesPaginated(args) {
|
|
1741
|
-
try {
|
|
1742
|
-
const table = await this.client.openTable(TABLE_TRACES);
|
|
1743
|
-
const query = table.query();
|
|
1744
|
-
const conditions = [];
|
|
1745
|
-
if (args.name) {
|
|
1746
|
-
conditions.push(`name = '${args.name}'`);
|
|
1747
|
-
}
|
|
1748
|
-
if (args.scope) {
|
|
1749
|
-
conditions.push(`scope = '${args.scope}'`);
|
|
1750
|
-
}
|
|
1751
|
-
if (args.attributes) {
|
|
1752
|
-
const attributesStr = JSON.stringify(args.attributes);
|
|
1753
|
-
conditions.push(`attributes LIKE '%${attributesStr.replace(/"/g, '\\"')}%'`);
|
|
1754
|
-
}
|
|
1755
|
-
if (args.dateRange?.start) {
|
|
1756
|
-
conditions.push(`\`createdAt\` >= ${args.dateRange.start.getTime()}`);
|
|
1757
|
-
}
|
|
1758
|
-
if (args.dateRange?.end) {
|
|
1759
|
-
conditions.push(`\`createdAt\` <= ${args.dateRange.end.getTime()}`);
|
|
1760
|
-
}
|
|
1761
|
-
if (conditions.length > 0) {
|
|
1762
|
-
const whereClause = conditions.join(" AND ");
|
|
1763
|
-
query.where(whereClause);
|
|
1764
|
-
}
|
|
1765
|
-
let total = 0;
|
|
1766
|
-
if (conditions.length > 0) {
|
|
1767
|
-
const countQuery = table.query().where(conditions.join(" AND "));
|
|
1768
|
-
const allRecords = await countQuery.toArray();
|
|
1769
|
-
total = allRecords.length;
|
|
1770
|
-
} else {
|
|
1771
|
-
total = await table.countRows();
|
|
1772
|
-
}
|
|
1773
|
-
const page = args.page || 0;
|
|
1774
|
-
const perPage = args.perPage || 10;
|
|
1775
|
-
const offset = page * perPage;
|
|
1776
|
-
query.limit(perPage);
|
|
1777
|
-
if (offset > 0) {
|
|
1778
|
-
query.offset(offset);
|
|
1779
|
-
}
|
|
1780
|
-
const records = await query.toArray();
|
|
1781
|
-
const traces = records.map((record) => {
|
|
1782
|
-
const processed = {
|
|
1783
|
-
...record,
|
|
1784
|
-
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1785
|
-
status: record.status ? JSON.parse(record.status) : {},
|
|
1786
|
-
events: record.events ? JSON.parse(record.events) : [],
|
|
1787
|
-
links: record.links ? JSON.parse(record.links) : [],
|
|
1788
|
-
other: record.other ? JSON.parse(record.other) : {},
|
|
1789
|
-
startTime: new Date(record.startTime),
|
|
1790
|
-
endTime: new Date(record.endTime),
|
|
1791
|
-
createdAt: new Date(record.createdAt)
|
|
1792
|
-
};
|
|
1793
|
-
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1794
|
-
processed.parentSpanId = "";
|
|
1795
|
-
} else {
|
|
1796
|
-
processed.parentSpanId = String(processed.parentSpanId);
|
|
1797
|
-
}
|
|
1798
|
-
return processed;
|
|
1799
|
-
});
|
|
1800
|
-
return {
|
|
1801
|
-
traces,
|
|
1802
|
-
total,
|
|
1803
|
-
page,
|
|
1804
|
-
perPage,
|
|
1805
|
-
hasMore: total > (page + 1) * perPage
|
|
1806
|
-
};
|
|
1807
|
-
} catch (error) {
|
|
1808
|
-
throw new MastraError(
|
|
1809
|
-
{
|
|
1810
|
-
id: "LANCE_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
1811
|
-
domain: ErrorDomain.STORAGE,
|
|
1812
|
-
category: ErrorCategory.THIRD_PARTY,
|
|
1813
|
-
details: { name: args.name ?? "", scope: args.scope ?? "" }
|
|
1814
|
-
},
|
|
1815
|
-
error
|
|
1816
|
-
);
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
async batchTraceInsert({ records }) {
|
|
1820
|
-
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1821
|
-
await this.operations.batchInsert({
|
|
1822
|
-
tableName: TABLE_TRACES,
|
|
1823
|
-
records
|
|
1824
|
-
});
|
|
1825
|
-
}
|
|
1826
|
-
};
|
|
1827
1506
|
function parseWorkflowRun(row) {
|
|
1828
1507
|
let parsedSnapshot = row.snapshot;
|
|
1829
1508
|
if (typeof parsedSnapshot === "string") {
|
|
@@ -1853,7 +1532,7 @@ var StoreWorkflowsLance = class extends WorkflowsStorage {
|
|
|
1853
1532
|
// runId,
|
|
1854
1533
|
// stepId,
|
|
1855
1534
|
// result,
|
|
1856
|
-
//
|
|
1535
|
+
// requestContext,
|
|
1857
1536
|
}) {
|
|
1858
1537
|
throw new Error("Method not implemented.");
|
|
1859
1538
|
}
|
|
@@ -1881,11 +1560,13 @@ var StoreWorkflowsLance = class extends WorkflowsStorage {
|
|
|
1881
1560
|
} else {
|
|
1882
1561
|
createdAt = now;
|
|
1883
1562
|
}
|
|
1563
|
+
const { status, value, ...rest } = snapshot;
|
|
1884
1564
|
const record = {
|
|
1885
1565
|
workflow_name: workflowName,
|
|
1886
1566
|
run_id: runId,
|
|
1887
1567
|
resourceId,
|
|
1888
|
-
snapshot: JSON.stringify(
|
|
1568
|
+
snapshot: JSON.stringify({ status, value, ...rest }),
|
|
1569
|
+
// this is to ensure status is always just before value, for when querying the db by status
|
|
1889
1570
|
createdAt,
|
|
1890
1571
|
updatedAt: now
|
|
1891
1572
|
};
|
|
@@ -1947,7 +1628,7 @@ var StoreWorkflowsLance = class extends WorkflowsStorage {
|
|
|
1947
1628
|
);
|
|
1948
1629
|
}
|
|
1949
1630
|
}
|
|
1950
|
-
async
|
|
1631
|
+
async listWorkflowRuns(args) {
|
|
1951
1632
|
try {
|
|
1952
1633
|
const table = await this.client.openTable(TABLE_WORKFLOW_SNAPSHOT);
|
|
1953
1634
|
let query = table.query();
|
|
@@ -1955,6 +1636,10 @@ var StoreWorkflowsLance = class extends WorkflowsStorage {
|
|
|
1955
1636
|
if (args?.workflowName) {
|
|
1956
1637
|
conditions.push(`workflow_name = '${args.workflowName.replace(/'/g, "''")}'`);
|
|
1957
1638
|
}
|
|
1639
|
+
if (args?.status) {
|
|
1640
|
+
const escapedStatus = args.status.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
1641
|
+
conditions.push(`\`snapshot\` LIKE '%"status":"${escapedStatus}","value"%'`);
|
|
1642
|
+
}
|
|
1958
1643
|
if (args?.resourceId) {
|
|
1959
1644
|
conditions.push(`\`resourceId\` = '${args.resourceId}'`);
|
|
1960
1645
|
}
|
|
@@ -1971,11 +1656,22 @@ var StoreWorkflowsLance = class extends WorkflowsStorage {
|
|
|
1971
1656
|
} else {
|
|
1972
1657
|
total = await table.countRows();
|
|
1973
1658
|
}
|
|
1974
|
-
if (args?.
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1659
|
+
if (args?.perPage !== void 0 && args?.page !== void 0) {
|
|
1660
|
+
const normalizedPerPage = normalizePerPage(args.perPage, Number.MAX_SAFE_INTEGER);
|
|
1661
|
+
if (args.page < 0 || !Number.isInteger(args.page)) {
|
|
1662
|
+
throw new MastraError(
|
|
1663
|
+
{
|
|
1664
|
+
id: "LANCE_STORE_INVALID_PAGINATION_PARAMS",
|
|
1665
|
+
domain: ErrorDomain.STORAGE,
|
|
1666
|
+
category: ErrorCategory.USER,
|
|
1667
|
+
details: { page: args.page, perPage: args.perPage }
|
|
1668
|
+
},
|
|
1669
|
+
new Error(`Invalid pagination parameters: page=${args.page}, perPage=${args.perPage}`)
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
const offset = args.page * normalizedPerPage;
|
|
1673
|
+
query.limit(normalizedPerPage);
|
|
1674
|
+
query.offset(offset);
|
|
1979
1675
|
}
|
|
1980
1676
|
const records = await query.toArray();
|
|
1981
1677
|
return {
|
|
@@ -1985,10 +1681,10 @@ var StoreWorkflowsLance = class extends WorkflowsStorage {
|
|
|
1985
1681
|
} catch (error) {
|
|
1986
1682
|
throw new MastraError(
|
|
1987
1683
|
{
|
|
1988
|
-
id: "
|
|
1684
|
+
id: "LANCE_STORE_LIST_WORKFLOW_RUNS_FAILED",
|
|
1989
1685
|
domain: ErrorDomain.STORAGE,
|
|
1990
1686
|
category: ErrorCategory.THIRD_PARTY,
|
|
1991
|
-
details: {
|
|
1687
|
+
details: { resourceId: args?.resourceId ?? "", workflowName: args?.workflowName ?? "" }
|
|
1992
1688
|
},
|
|
1993
1689
|
error
|
|
1994
1690
|
);
|
|
@@ -2002,6 +1698,8 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2002
1698
|
lanceClient;
|
|
2003
1699
|
/**
|
|
2004
1700
|
* Creates a new instance of LanceStorage
|
|
1701
|
+
* @param id The unique identifier for this storage instance
|
|
1702
|
+
* @param name The name for this storage instance
|
|
2005
1703
|
* @param uri The URI to connect to LanceDB
|
|
2006
1704
|
* @param options connection options
|
|
2007
1705
|
*
|
|
@@ -2009,31 +1707,29 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2009
1707
|
*
|
|
2010
1708
|
* Connect to a local database
|
|
2011
1709
|
* ```ts
|
|
2012
|
-
* const store = await LanceStorage.create('/path/to/db');
|
|
1710
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', '/path/to/db');
|
|
2013
1711
|
* ```
|
|
2014
1712
|
*
|
|
2015
1713
|
* Connect to a LanceDB cloud database
|
|
2016
1714
|
* ```ts
|
|
2017
|
-
* const store = await LanceStorage.create('db://host:port');
|
|
1715
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 'db://host:port');
|
|
2018
1716
|
* ```
|
|
2019
1717
|
*
|
|
2020
1718
|
* Connect to a cloud database
|
|
2021
1719
|
* ```ts
|
|
2022
|
-
* const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1720
|
+
* const store = await LanceStorage.create('my-storage-id', 'MyStorage', 's3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
2023
1721
|
* ```
|
|
2024
1722
|
*/
|
|
2025
|
-
static async create(name, uri, options) {
|
|
2026
|
-
const instance = new _LanceStorage(name);
|
|
1723
|
+
static async create(id, name, uri, options) {
|
|
1724
|
+
const instance = new _LanceStorage(id, name);
|
|
2027
1725
|
try {
|
|
2028
1726
|
instance.lanceClient = await connect(uri, options);
|
|
2029
1727
|
const operations = new StoreOperationsLance({ client: instance.lanceClient });
|
|
2030
1728
|
instance.stores = {
|
|
2031
1729
|
operations: new StoreOperationsLance({ client: instance.lanceClient }),
|
|
2032
1730
|
workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
|
|
2033
|
-
traces: new StoreTracesLance({ client: instance.lanceClient, operations }),
|
|
2034
1731
|
scores: new StoreScoresLance({ client: instance.lanceClient }),
|
|
2035
|
-
memory: new StoreMemoryLance({ client: instance.lanceClient, operations })
|
|
2036
|
-
legacyEvals: new StoreLegacyEvalsLance({ client: instance.lanceClient })
|
|
1732
|
+
memory: new StoreMemoryLance({ client: instance.lanceClient, operations })
|
|
2037
1733
|
};
|
|
2038
1734
|
return instance;
|
|
2039
1735
|
} catch (e) {
|
|
@@ -2053,15 +1749,13 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2053
1749
|
* @internal
|
|
2054
1750
|
* Private constructor to enforce using the create factory method
|
|
2055
1751
|
*/
|
|
2056
|
-
constructor(name) {
|
|
2057
|
-
super({ name });
|
|
1752
|
+
constructor(id, name) {
|
|
1753
|
+
super({ id, name });
|
|
2058
1754
|
const operations = new StoreOperationsLance({ client: this.lanceClient });
|
|
2059
1755
|
this.stores = {
|
|
2060
1756
|
operations: new StoreOperationsLance({ client: this.lanceClient }),
|
|
2061
1757
|
workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
|
|
2062
|
-
traces: new StoreTracesLance({ client: this.lanceClient, operations }),
|
|
2063
1758
|
scores: new StoreScoresLance({ client: this.lanceClient }),
|
|
2064
|
-
legacyEvals: new StoreLegacyEvalsLance({ client: this.lanceClient }),
|
|
2065
1759
|
memory: new StoreMemoryLance({ client: this.lanceClient, operations })
|
|
2066
1760
|
};
|
|
2067
1761
|
}
|
|
@@ -2096,9 +1790,6 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2096
1790
|
async getThreadById({ threadId }) {
|
|
2097
1791
|
return this.stores.memory.getThreadById({ threadId });
|
|
2098
1792
|
}
|
|
2099
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
2100
|
-
return this.stores.memory.getThreadsByResourceId({ resourceId });
|
|
2101
|
-
}
|
|
2102
1793
|
/**
|
|
2103
1794
|
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
2104
1795
|
* @param thread - The thread to save
|
|
@@ -2124,7 +1815,7 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2124
1815
|
hasColumn: true,
|
|
2125
1816
|
createTable: true,
|
|
2126
1817
|
deleteMessages: false,
|
|
2127
|
-
|
|
1818
|
+
listScoresBySpan: true
|
|
2128
1819
|
};
|
|
2129
1820
|
}
|
|
2130
1821
|
async getResourceById({ resourceId }) {
|
|
@@ -2188,50 +1879,17 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2188
1879
|
});
|
|
2189
1880
|
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
2190
1881
|
}
|
|
2191
|
-
async
|
|
2192
|
-
|
|
2193
|
-
resourceId,
|
|
2194
|
-
selectBy,
|
|
2195
|
-
format,
|
|
2196
|
-
threadConfig
|
|
2197
|
-
}) {
|
|
2198
|
-
return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format, threadConfig });
|
|
2199
|
-
}
|
|
2200
|
-
async getMessagesById({
|
|
2201
|
-
messageIds,
|
|
2202
|
-
format
|
|
2203
|
-
}) {
|
|
2204
|
-
return this.stores.memory.getMessagesById({ messageIds, format });
|
|
1882
|
+
async listMessagesById({ messageIds }) {
|
|
1883
|
+
return this.stores.memory.listMessagesById({ messageIds });
|
|
2205
1884
|
}
|
|
2206
1885
|
async saveMessages(args) {
|
|
2207
1886
|
return this.stores.memory.saveMessages(args);
|
|
2208
1887
|
}
|
|
2209
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
2210
|
-
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2211
|
-
}
|
|
2212
|
-
async getMessagesPaginated(args) {
|
|
2213
|
-
return this.stores.memory.getMessagesPaginated(args);
|
|
2214
|
-
}
|
|
2215
1888
|
async updateMessages(_args) {
|
|
2216
1889
|
return this.stores.memory.updateMessages(_args);
|
|
2217
1890
|
}
|
|
2218
|
-
async
|
|
2219
|
-
return this.stores.
|
|
2220
|
-
}
|
|
2221
|
-
async getTraces(args) {
|
|
2222
|
-
return this.stores.traces.getTraces(args);
|
|
2223
|
-
}
|
|
2224
|
-
async getTracesPaginated(args) {
|
|
2225
|
-
return this.stores.traces.getTracesPaginated(args);
|
|
2226
|
-
}
|
|
2227
|
-
async getEvalsByAgentName(agentName, type) {
|
|
2228
|
-
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2229
|
-
}
|
|
2230
|
-
async getEvals(options) {
|
|
2231
|
-
return this.stores.legacyEvals.getEvals(options);
|
|
2232
|
-
}
|
|
2233
|
-
async getWorkflowRuns(args) {
|
|
2234
|
-
return this.stores.workflows.getWorkflowRuns(args);
|
|
1891
|
+
async listWorkflowRuns(args) {
|
|
1892
|
+
return this.stores.workflows.listWorkflowRuns(args);
|
|
2235
1893
|
}
|
|
2236
1894
|
async getWorkflowRunById(args) {
|
|
2237
1895
|
return this.stores.workflows.getWorkflowRunById(args);
|
|
@@ -2241,9 +1899,9 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2241
1899
|
runId,
|
|
2242
1900
|
stepId,
|
|
2243
1901
|
result,
|
|
2244
|
-
|
|
1902
|
+
requestContext
|
|
2245
1903
|
}) {
|
|
2246
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result,
|
|
1904
|
+
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
2247
1905
|
}
|
|
2248
1906
|
async updateWorkflowState({
|
|
2249
1907
|
workflowName,
|
|
@@ -2269,37 +1927,37 @@ var LanceStorage = class _LanceStorage extends MastraStorage {
|
|
|
2269
1927
|
async getScoreById({ id: _id }) {
|
|
2270
1928
|
return this.stores.scores.getScoreById({ id: _id });
|
|
2271
1929
|
}
|
|
2272
|
-
async
|
|
1930
|
+
async listScoresByScorerId({
|
|
2273
1931
|
scorerId,
|
|
2274
1932
|
source,
|
|
2275
1933
|
entityId,
|
|
2276
1934
|
entityType,
|
|
2277
1935
|
pagination
|
|
2278
1936
|
}) {
|
|
2279
|
-
return this.stores.scores.
|
|
1937
|
+
return this.stores.scores.listScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
|
|
2280
1938
|
}
|
|
2281
1939
|
async saveScore(_score) {
|
|
2282
1940
|
return this.stores.scores.saveScore(_score);
|
|
2283
1941
|
}
|
|
2284
|
-
async
|
|
1942
|
+
async listScoresByRunId({
|
|
2285
1943
|
runId,
|
|
2286
1944
|
pagination
|
|
2287
1945
|
}) {
|
|
2288
|
-
return this.stores.scores.
|
|
1946
|
+
return this.stores.scores.listScoresByRunId({ runId, pagination });
|
|
2289
1947
|
}
|
|
2290
|
-
async
|
|
1948
|
+
async listScoresByEntityId({
|
|
2291
1949
|
entityId,
|
|
2292
1950
|
entityType,
|
|
2293
1951
|
pagination
|
|
2294
1952
|
}) {
|
|
2295
|
-
return this.stores.scores.
|
|
1953
|
+
return this.stores.scores.listScoresByEntityId({ entityId, entityType, pagination });
|
|
2296
1954
|
}
|
|
2297
|
-
async
|
|
1955
|
+
async listScoresBySpan({
|
|
2298
1956
|
traceId,
|
|
2299
1957
|
spanId,
|
|
2300
1958
|
pagination
|
|
2301
1959
|
}) {
|
|
2302
|
-
return this.stores.scores.
|
|
1960
|
+
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
|
|
2303
1961
|
}
|
|
2304
1962
|
};
|
|
2305
1963
|
var LanceFilterTranslator = class extends BaseFilterTranslator {
|
|
@@ -2648,7 +2306,7 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
2648
2306
|
* ```
|
|
2649
2307
|
*/
|
|
2650
2308
|
static async create(uri, options) {
|
|
2651
|
-
const instance = new _LanceVectorStore();
|
|
2309
|
+
const instance = new _LanceVectorStore(options?.id || crypto.randomUUID());
|
|
2652
2310
|
try {
|
|
2653
2311
|
instance.lanceClient = await connect(uri, options);
|
|
2654
2312
|
return instance;
|
|
@@ -2668,8 +2326,8 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
2668
2326
|
* @internal
|
|
2669
2327
|
* Private constructor to enforce using the create factory method
|
|
2670
2328
|
*/
|
|
2671
|
-
constructor() {
|
|
2672
|
-
super();
|
|
2329
|
+
constructor(id) {
|
|
2330
|
+
super({ id });
|
|
2673
2331
|
}
|
|
2674
2332
|
close() {
|
|
2675
2333
|
if (this.lanceClient) {
|
|
@@ -3192,7 +2850,44 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3192
2850
|
);
|
|
3193
2851
|
}
|
|
3194
2852
|
}
|
|
3195
|
-
async updateVector(
|
|
2853
|
+
async updateVector(params) {
|
|
2854
|
+
const { indexName, update } = params;
|
|
2855
|
+
if ("id" in params && "filter" in params && params.id && params.filter) {
|
|
2856
|
+
throw new MastraError({
|
|
2857
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2858
|
+
domain: ErrorDomain.STORAGE,
|
|
2859
|
+
category: ErrorCategory.USER,
|
|
2860
|
+
text: "id and filter are mutually exclusive",
|
|
2861
|
+
details: { indexName }
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
|
|
2865
|
+
throw new MastraError({
|
|
2866
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2867
|
+
domain: ErrorDomain.STORAGE,
|
|
2868
|
+
category: ErrorCategory.USER,
|
|
2869
|
+
text: "Either id or filter must be provided",
|
|
2870
|
+
details: { indexName }
|
|
2871
|
+
});
|
|
2872
|
+
}
|
|
2873
|
+
if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
|
|
2874
|
+
throw new MastraError({
|
|
2875
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2876
|
+
domain: ErrorDomain.STORAGE,
|
|
2877
|
+
category: ErrorCategory.USER,
|
|
2878
|
+
text: "Cannot update with empty filter",
|
|
2879
|
+
details: { indexName }
|
|
2880
|
+
});
|
|
2881
|
+
}
|
|
2882
|
+
if (!update.vector && !update.metadata) {
|
|
2883
|
+
throw new MastraError({
|
|
2884
|
+
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
2885
|
+
domain: ErrorDomain.STORAGE,
|
|
2886
|
+
category: ErrorCategory.USER,
|
|
2887
|
+
text: "No updates provided",
|
|
2888
|
+
details: { indexName }
|
|
2889
|
+
});
|
|
2890
|
+
}
|
|
3196
2891
|
try {
|
|
3197
2892
|
if (!this.lanceClient) {
|
|
3198
2893
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
@@ -3200,21 +2895,6 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3200
2895
|
if (!indexName) {
|
|
3201
2896
|
throw new Error("indexName is required");
|
|
3202
2897
|
}
|
|
3203
|
-
if (!id) {
|
|
3204
|
-
throw new Error("id is required");
|
|
3205
|
-
}
|
|
3206
|
-
} catch (err) {
|
|
3207
|
-
throw new MastraError(
|
|
3208
|
-
{
|
|
3209
|
-
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED_INVALID_ARGS",
|
|
3210
|
-
domain: ErrorDomain.STORAGE,
|
|
3211
|
-
category: ErrorCategory.USER,
|
|
3212
|
-
details: { indexName, id }
|
|
3213
|
-
},
|
|
3214
|
-
err
|
|
3215
|
-
);
|
|
3216
|
-
}
|
|
3217
|
-
try {
|
|
3218
2898
|
const tables = await this.lanceClient.tableNames();
|
|
3219
2899
|
for (const tableName of tables) {
|
|
3220
2900
|
this.logger.debug("Checking table:" + tableName);
|
|
@@ -3224,39 +2904,66 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3224
2904
|
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3225
2905
|
if (hasColumn) {
|
|
3226
2906
|
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3227
|
-
|
|
3228
|
-
if (
|
|
3229
|
-
|
|
2907
|
+
let whereClause;
|
|
2908
|
+
if ("id" in params && params.id) {
|
|
2909
|
+
whereClause = `id = '${params.id}'`;
|
|
2910
|
+
} else if ("filter" in params && params.filter) {
|
|
2911
|
+
const translator = new LanceFilterTranslator();
|
|
2912
|
+
const processFilterKeys = (filter) => {
|
|
2913
|
+
const processedFilter = {};
|
|
2914
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
2915
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
2916
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
2917
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
2918
|
+
});
|
|
2919
|
+
} else {
|
|
2920
|
+
processedFilter[`metadata_${key}`] = value;
|
|
2921
|
+
}
|
|
2922
|
+
});
|
|
2923
|
+
return processedFilter;
|
|
2924
|
+
};
|
|
2925
|
+
const prefixedFilter = processFilterKeys(params.filter);
|
|
2926
|
+
whereClause = translator.translate(prefixedFilter) || "";
|
|
2927
|
+
if (!whereClause) {
|
|
2928
|
+
throw new Error("Failed to translate filter to SQL");
|
|
2929
|
+
}
|
|
2930
|
+
} else {
|
|
2931
|
+
throw new Error("Either id or filter must be provided");
|
|
3230
2932
|
}
|
|
3231
|
-
const
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
2933
|
+
const existingRecords = await table.query().where(whereClause).select(schema.fields.map((field) => field.name)).toArray();
|
|
2934
|
+
if (existingRecords.length === 0) {
|
|
2935
|
+
this.logger.info(`No records found matching criteria in table ${tableName}`);
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
const updatedRecords = existingRecords.map((record) => {
|
|
2939
|
+
const rowData = {};
|
|
2940
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
2941
|
+
if (key !== "_distance") {
|
|
2942
|
+
if (key === indexName) {
|
|
2943
|
+
if (update.vector) {
|
|
2944
|
+
rowData[key] = update.vector;
|
|
3242
2945
|
} else {
|
|
3243
|
-
|
|
2946
|
+
if (Array.isArray(value)) {
|
|
2947
|
+
rowData[key] = [...value];
|
|
2948
|
+
} else if (typeof value === "object" && value !== null) {
|
|
2949
|
+
rowData[key] = Array.from(value);
|
|
2950
|
+
} else {
|
|
2951
|
+
rowData[key] = value;
|
|
2952
|
+
}
|
|
3244
2953
|
}
|
|
2954
|
+
} else {
|
|
2955
|
+
rowData[key] = value;
|
|
3245
2956
|
}
|
|
3246
|
-
} else {
|
|
3247
|
-
rowData[key] = value;
|
|
3248
2957
|
}
|
|
2958
|
+
});
|
|
2959
|
+
if (update.metadata) {
|
|
2960
|
+
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
2961
|
+
rowData[`metadata_${key}`] = value;
|
|
2962
|
+
});
|
|
3249
2963
|
}
|
|
2964
|
+
return rowData;
|
|
3250
2965
|
});
|
|
3251
|
-
|
|
3252
|
-
rowData[indexName] = update.vector;
|
|
3253
|
-
}
|
|
3254
|
-
if (update.metadata) {
|
|
3255
|
-
Object.entries(update.metadata).forEach(([key, value]) => {
|
|
3256
|
-
rowData[`metadata_${key}`] = value;
|
|
3257
|
-
});
|
|
3258
|
-
}
|
|
3259
|
-
await table.add([rowData], { mode: "overwrite" });
|
|
2966
|
+
await table.add(updatedRecords, { mode: "overwrite" });
|
|
3260
2967
|
return;
|
|
3261
2968
|
}
|
|
3262
2969
|
} catch (err) {
|
|
@@ -3266,12 +2973,19 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3266
2973
|
}
|
|
3267
2974
|
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3268
2975
|
} catch (error) {
|
|
2976
|
+
if (error instanceof MastraError) throw error;
|
|
3269
2977
|
throw new MastraError(
|
|
3270
2978
|
{
|
|
3271
2979
|
id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED",
|
|
3272
2980
|
domain: ErrorDomain.STORAGE,
|
|
3273
2981
|
category: ErrorCategory.THIRD_PARTY,
|
|
3274
|
-
details: {
|
|
2982
|
+
details: {
|
|
2983
|
+
indexName,
|
|
2984
|
+
..."id" in params && params.id && { id: params.id },
|
|
2985
|
+
..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) },
|
|
2986
|
+
hasVector: !!update.vector,
|
|
2987
|
+
hasMetadata: !!update.metadata
|
|
2988
|
+
}
|
|
3275
2989
|
},
|
|
3276
2990
|
error
|
|
3277
2991
|
);
|
|
@@ -3294,7 +3008,10 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3294
3008
|
id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED_INVALID_ARGS",
|
|
3295
3009
|
domain: ErrorDomain.STORAGE,
|
|
3296
3010
|
category: ErrorCategory.USER,
|
|
3297
|
-
details: {
|
|
3011
|
+
details: {
|
|
3012
|
+
indexName,
|
|
3013
|
+
...id && { id }
|
|
3014
|
+
}
|
|
3298
3015
|
},
|
|
3299
3016
|
err
|
|
3300
3017
|
);
|
|
@@ -3324,7 +3041,10 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3324
3041
|
id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED",
|
|
3325
3042
|
domain: ErrorDomain.STORAGE,
|
|
3326
3043
|
category: ErrorCategory.THIRD_PARTY,
|
|
3327
|
-
details: {
|
|
3044
|
+
details: {
|
|
3045
|
+
indexName,
|
|
3046
|
+
...id && { id }
|
|
3047
|
+
}
|
|
3328
3048
|
},
|
|
3329
3049
|
error
|
|
3330
3050
|
);
|
|
@@ -3355,6 +3075,109 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
|
|
|
3355
3075
|
});
|
|
3356
3076
|
return result;
|
|
3357
3077
|
}
|
|
3078
|
+
async deleteVectors({ indexName, filter, ids }) {
|
|
3079
|
+
if (ids && filter) {
|
|
3080
|
+
throw new MastraError({
|
|
3081
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3082
|
+
domain: ErrorDomain.STORAGE,
|
|
3083
|
+
category: ErrorCategory.USER,
|
|
3084
|
+
text: "ids and filter are mutually exclusive",
|
|
3085
|
+
details: { indexName }
|
|
3086
|
+
});
|
|
3087
|
+
}
|
|
3088
|
+
if (!ids && !filter) {
|
|
3089
|
+
throw new MastraError({
|
|
3090
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3091
|
+
domain: ErrorDomain.STORAGE,
|
|
3092
|
+
category: ErrorCategory.USER,
|
|
3093
|
+
text: "Either filter or ids must be provided",
|
|
3094
|
+
details: { indexName }
|
|
3095
|
+
});
|
|
3096
|
+
}
|
|
3097
|
+
if (ids && ids.length === 0) {
|
|
3098
|
+
throw new MastraError({
|
|
3099
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3100
|
+
domain: ErrorDomain.STORAGE,
|
|
3101
|
+
category: ErrorCategory.USER,
|
|
3102
|
+
text: "Cannot delete with empty ids array",
|
|
3103
|
+
details: { indexName }
|
|
3104
|
+
});
|
|
3105
|
+
}
|
|
3106
|
+
if (filter && Object.keys(filter).length === 0) {
|
|
3107
|
+
throw new MastraError({
|
|
3108
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
|
|
3109
|
+
domain: ErrorDomain.STORAGE,
|
|
3110
|
+
category: ErrorCategory.USER,
|
|
3111
|
+
text: "Cannot delete with empty filter",
|
|
3112
|
+
details: { indexName }
|
|
3113
|
+
});
|
|
3114
|
+
}
|
|
3115
|
+
try {
|
|
3116
|
+
if (!this.lanceClient) {
|
|
3117
|
+
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
3118
|
+
}
|
|
3119
|
+
if (!indexName) {
|
|
3120
|
+
throw new Error("indexName is required");
|
|
3121
|
+
}
|
|
3122
|
+
const tables = await this.lanceClient.tableNames();
|
|
3123
|
+
for (const tableName of tables) {
|
|
3124
|
+
this.logger.debug("Checking table:" + tableName);
|
|
3125
|
+
const table = await this.lanceClient.openTable(tableName);
|
|
3126
|
+
try {
|
|
3127
|
+
const schema = await table.schema();
|
|
3128
|
+
const hasColumn = schema.fields.some((field) => field.name === indexName);
|
|
3129
|
+
if (hasColumn) {
|
|
3130
|
+
this.logger.debug(`Found column ${indexName} in table ${tableName}`);
|
|
3131
|
+
if (ids) {
|
|
3132
|
+
const idsConditions = ids.map((id) => `id = '${id}'`).join(" OR ");
|
|
3133
|
+
await table.delete(idsConditions);
|
|
3134
|
+
} else if (filter) {
|
|
3135
|
+
const translator = new LanceFilterTranslator();
|
|
3136
|
+
const processFilterKeys = (filter2) => {
|
|
3137
|
+
const processedFilter = {};
|
|
3138
|
+
Object.entries(filter2).forEach(([key, value]) => {
|
|
3139
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3140
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
3141
|
+
processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
|
|
3142
|
+
});
|
|
3143
|
+
} else {
|
|
3144
|
+
processedFilter[`metadata_${key}`] = value;
|
|
3145
|
+
}
|
|
3146
|
+
});
|
|
3147
|
+
return processedFilter;
|
|
3148
|
+
};
|
|
3149
|
+
const prefixedFilter = processFilterKeys(filter);
|
|
3150
|
+
const whereClause = translator.translate(prefixedFilter);
|
|
3151
|
+
if (!whereClause) {
|
|
3152
|
+
throw new Error("Failed to translate filter to SQL");
|
|
3153
|
+
}
|
|
3154
|
+
await table.delete(whereClause);
|
|
3155
|
+
}
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
} catch (err) {
|
|
3159
|
+
this.logger.error(`Error checking schema for table ${tableName}:` + err);
|
|
3160
|
+
continue;
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3163
|
+
throw new Error(`No table found with column/index '${indexName}'`);
|
|
3164
|
+
} catch (error) {
|
|
3165
|
+
if (error instanceof MastraError) throw error;
|
|
3166
|
+
throw new MastraError(
|
|
3167
|
+
{
|
|
3168
|
+
id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_FAILED",
|
|
3169
|
+
domain: ErrorDomain.STORAGE,
|
|
3170
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
3171
|
+
details: {
|
|
3172
|
+
indexName,
|
|
3173
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
3174
|
+
...ids && { idsCount: ids.length }
|
|
3175
|
+
}
|
|
3176
|
+
},
|
|
3177
|
+
error
|
|
3178
|
+
);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3358
3181
|
};
|
|
3359
3182
|
|
|
3360
3183
|
export { LanceStorage, LanceVectorStore };
|