@mastra/lance 0.0.0-mcp-changeset-20250707162621 → 0.0.0-memory-system-message-error-20250813233316
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 +177 -9
- package/LICENSE.md +11 -42
- package/dist/index.cjs +1649 -643
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1584 -578
- package/dist/index.js.map +1 -0
- package/dist/storage/domains/legacy-evals/index.d.ts +25 -0
- package/dist/storage/domains/legacy-evals/index.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +94 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -0
- package/dist/storage/domains/operations/index.d.ts +40 -0
- package/dist/storage/domains/operations/index.d.ts.map +1 -0
- package/dist/storage/domains/scores/index.d.ts +42 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -0
- package/dist/storage/domains/traces/index.d.ts +34 -0
- package/dist/storage/domains/traces/index.d.ts.map +1 -0
- package/dist/storage/domains/utils.d.ts +10 -0
- package/dist/storage/domains/utils.d.ts.map +1 -0
- package/dist/storage/domains/workflows/index.d.ts +38 -0
- package/dist/storage/domains/workflows/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +236 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/vector/filter.d.ts +41 -0
- package/dist/vector/filter.d.ts.map +1 -0
- package/dist/vector/index.d.ts +85 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/dist/vector/types.d.ts +15 -0
- package/dist/vector/types.d.ts.map +1 -0
- package/package.json +11 -10
- package/src/storage/domains/legacy-evals/index.ts +156 -0
- package/src/storage/domains/memory/index.ts +947 -0
- package/src/storage/domains/operations/index.ts +489 -0
- package/src/storage/domains/scores/index.ts +243 -0
- package/src/storage/domains/traces/index.ts +212 -0
- package/src/storage/domains/utils.ts +158 -0
- package/src/storage/domains/workflows/index.ts +207 -0
- package/src/storage/index.test.ts +6 -1332
- package/src/storage/index.ts +163 -1162
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +17 -0
- package/dist/_tsup-dts-rollup.d.cts +0 -409
- package/dist/_tsup-dts-rollup.d.ts +0 -409
- package/dist/index.d.cts +0 -2
package/dist/index.cjs
CHANGED
|
@@ -1,267 +1,1104 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var lancedb = require('@lancedb/lancedb');
|
|
4
|
-
var agent = require('@mastra/core/agent');
|
|
5
4
|
var error = require('@mastra/core/error');
|
|
6
5
|
var storage = require('@mastra/core/storage');
|
|
6
|
+
var agent = require('@mastra/core/agent');
|
|
7
7
|
var apacheArrow = require('apache-arrow');
|
|
8
8
|
var vector = require('@mastra/core/vector');
|
|
9
9
|
var filter = require('@mastra/core/vector/filter');
|
|
10
10
|
|
|
11
11
|
// src/storage/index.ts
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* @param options connection options
|
|
18
|
-
*
|
|
19
|
-
* Usage:
|
|
20
|
-
*
|
|
21
|
-
* Connect to a local database
|
|
22
|
-
* ```ts
|
|
23
|
-
* const store = await LanceStorage.create('/path/to/db');
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Connect to a LanceDB cloud database
|
|
27
|
-
* ```ts
|
|
28
|
-
* const store = await LanceStorage.create('db://host:port');
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* Connect to a cloud database
|
|
32
|
-
* ```ts
|
|
33
|
-
* const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
static async create(name, uri, options) {
|
|
37
|
-
const instance = new _LanceStorage(name);
|
|
38
|
-
try {
|
|
39
|
-
instance.lanceClient = await lancedb.connect(uri, options);
|
|
40
|
-
return instance;
|
|
41
|
-
} catch (e) {
|
|
42
|
-
throw new error.MastraError(
|
|
43
|
-
{
|
|
44
|
-
id: "STORAGE_LANCE_STORAGE_CONNECT_FAILED",
|
|
45
|
-
domain: error.ErrorDomain.STORAGE,
|
|
46
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
47
|
-
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
48
|
-
details: { uri, optionsProvided: !!options }
|
|
49
|
-
},
|
|
50
|
-
e
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
getPrimaryKeys(tableName) {
|
|
55
|
-
let primaryId = ["id"];
|
|
56
|
-
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
57
|
-
primaryId = ["workflow_name", "run_id"];
|
|
58
|
-
} else if (tableName === storage.TABLE_EVALS) {
|
|
59
|
-
primaryId = ["agent_name", "metric_name", "run_id"];
|
|
60
|
-
}
|
|
61
|
-
return primaryId;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* @internal
|
|
65
|
-
* Private constructor to enforce using the create factory method
|
|
66
|
-
*/
|
|
67
|
-
constructor(name) {
|
|
68
|
-
super({ name });
|
|
12
|
+
var StoreLegacyEvalsLance = class extends storage.LegacyEvalsStorage {
|
|
13
|
+
client;
|
|
14
|
+
constructor({ client }) {
|
|
15
|
+
super();
|
|
16
|
+
this.client = client;
|
|
69
17
|
}
|
|
70
|
-
async
|
|
71
|
-
tableName,
|
|
72
|
-
schema
|
|
73
|
-
}) {
|
|
18
|
+
async getEvalsByAgentName(agentName, type) {
|
|
74
19
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
|
|
20
|
+
const table = await this.client.openTable(storage.TABLE_EVALS);
|
|
21
|
+
const query = table.query().where(`agent_name = '${agentName}'`);
|
|
22
|
+
const records = await query.toArray();
|
|
23
|
+
let filteredRecords = records;
|
|
24
|
+
if (type === "live") {
|
|
25
|
+
filteredRecords = records.filter((record) => record.test_info === null);
|
|
26
|
+
} else if (type === "test") {
|
|
27
|
+
filteredRecords = records.filter((record) => record.test_info !== null);
|
|
83
28
|
}
|
|
29
|
+
return filteredRecords.map((record) => {
|
|
30
|
+
return {
|
|
31
|
+
id: record.id,
|
|
32
|
+
input: record.input,
|
|
33
|
+
output: record.output,
|
|
34
|
+
agentName: record.agent_name,
|
|
35
|
+
metricName: record.metric_name,
|
|
36
|
+
result: JSON.parse(record.result),
|
|
37
|
+
instructions: record.instructions,
|
|
38
|
+
testInfo: record.test_info ? JSON.parse(record.test_info) : null,
|
|
39
|
+
globalRunId: record.global_run_id,
|
|
40
|
+
runId: record.run_id,
|
|
41
|
+
createdAt: new Date(record.created_at).toString()
|
|
42
|
+
};
|
|
43
|
+
});
|
|
84
44
|
} catch (error$1) {
|
|
85
45
|
throw new error.MastraError(
|
|
86
46
|
{
|
|
87
|
-
id: "
|
|
47
|
+
id: "LANCE_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
|
|
88
48
|
domain: error.ErrorDomain.STORAGE,
|
|
89
|
-
category: error.ErrorCategory.
|
|
90
|
-
details: {
|
|
49
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
50
|
+
details: { agentName }
|
|
91
51
|
},
|
|
92
52
|
error$1
|
|
93
53
|
);
|
|
94
54
|
}
|
|
55
|
+
}
|
|
56
|
+
async getEvals(options) {
|
|
95
57
|
try {
|
|
96
|
-
const
|
|
97
|
-
|
|
58
|
+
const table = await this.client.openTable(storage.TABLE_EVALS);
|
|
59
|
+
const conditions = [];
|
|
60
|
+
if (options.agentName) {
|
|
61
|
+
conditions.push(`agent_name = '${options.agentName}'`);
|
|
62
|
+
}
|
|
63
|
+
if (options.type === "live") {
|
|
64
|
+
conditions.push("length(test_info) = 0");
|
|
65
|
+
} else if (options.type === "test") {
|
|
66
|
+
conditions.push("length(test_info) > 0");
|
|
67
|
+
}
|
|
68
|
+
const startDate = options.dateRange?.start || options.fromDate;
|
|
69
|
+
const endDate = options.dateRange?.end || options.toDate;
|
|
70
|
+
if (startDate) {
|
|
71
|
+
conditions.push(`\`created_at\` >= ${startDate.getTime()}`);
|
|
72
|
+
}
|
|
73
|
+
if (endDate) {
|
|
74
|
+
conditions.push(`\`created_at\` <= ${endDate.getTime()}`);
|
|
75
|
+
}
|
|
76
|
+
let total = 0;
|
|
77
|
+
if (conditions.length > 0) {
|
|
78
|
+
total = await table.countRows(conditions.join(" AND "));
|
|
79
|
+
} else {
|
|
80
|
+
total = await table.countRows();
|
|
81
|
+
}
|
|
82
|
+
const query = table.query();
|
|
83
|
+
if (conditions.length > 0) {
|
|
84
|
+
const whereClause = conditions.join(" AND ");
|
|
85
|
+
query.where(whereClause);
|
|
86
|
+
}
|
|
87
|
+
const records = await query.toArray();
|
|
88
|
+
const evals = records.sort((a, b) => b.created_at - a.created_at).map((record) => {
|
|
89
|
+
return {
|
|
90
|
+
id: record.id,
|
|
91
|
+
input: record.input,
|
|
92
|
+
output: record.output,
|
|
93
|
+
agentName: record.agent_name,
|
|
94
|
+
metricName: record.metric_name,
|
|
95
|
+
result: JSON.parse(record.result),
|
|
96
|
+
instructions: record.instructions,
|
|
97
|
+
testInfo: record.test_info ? JSON.parse(record.test_info) : null,
|
|
98
|
+
globalRunId: record.global_run_id,
|
|
99
|
+
runId: record.run_id,
|
|
100
|
+
createdAt: new Date(record.created_at).toISOString()
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
const page = options.page || 0;
|
|
104
|
+
const perPage = options.perPage || 10;
|
|
105
|
+
const pagedEvals = evals.slice(page * perPage, (page + 1) * perPage);
|
|
106
|
+
return {
|
|
107
|
+
evals: pagedEvals,
|
|
108
|
+
total,
|
|
109
|
+
page,
|
|
110
|
+
perPage,
|
|
111
|
+
hasMore: total > (page + 1) * perPage
|
|
112
|
+
};
|
|
98
113
|
} catch (error$1) {
|
|
99
114
|
throw new error.MastraError(
|
|
100
115
|
{
|
|
101
|
-
id: "
|
|
116
|
+
id: "LANCE_STORE_GET_EVALS_FAILED",
|
|
102
117
|
domain: error.ErrorDomain.STORAGE,
|
|
103
118
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
104
|
-
details: {
|
|
119
|
+
details: { agentName: options.agentName ?? "" }
|
|
105
120
|
},
|
|
106
121
|
error$1
|
|
107
122
|
);
|
|
108
123
|
}
|
|
109
124
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
125
|
+
};
|
|
126
|
+
function getPrimaryKeys(tableName) {
|
|
127
|
+
let primaryId = ["id"];
|
|
128
|
+
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
129
|
+
primaryId = ["workflow_name", "run_id"];
|
|
130
|
+
} else if (tableName === storage.TABLE_EVALS) {
|
|
131
|
+
primaryId = ["agent_name", "metric_name", "run_id"];
|
|
132
|
+
}
|
|
133
|
+
return primaryId;
|
|
134
|
+
}
|
|
135
|
+
function validateKeyTypes(keys, tableSchema) {
|
|
136
|
+
const fieldTypes = new Map(
|
|
137
|
+
tableSchema.fields.map((field) => [field.name, field.type?.toString().toLowerCase()])
|
|
138
|
+
);
|
|
139
|
+
for (const [key, value] of Object.entries(keys)) {
|
|
140
|
+
const fieldType = fieldTypes.get(key);
|
|
141
|
+
if (!fieldType) {
|
|
142
|
+
throw new Error(`Field '${key}' does not exist in table schema`);
|
|
143
|
+
}
|
|
144
|
+
if (value !== null) {
|
|
145
|
+
if ((fieldType.includes("int") || fieldType.includes("bigint")) && typeof value !== "number") {
|
|
146
|
+
throw new Error(`Expected numeric value for field '${key}', got ${typeof value}`);
|
|
147
|
+
}
|
|
148
|
+
if (fieldType.includes("utf8") && typeof value !== "string") {
|
|
149
|
+
throw new Error(`Expected string value for field '${key}', got ${typeof value}`);
|
|
150
|
+
}
|
|
151
|
+
if (fieldType.includes("timestamp") && !(value instanceof Date) && typeof value !== "string") {
|
|
152
|
+
throw new Error(`Expected Date or string value for field '${key}', got ${typeof value}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function processResultWithTypeConversion(rawResult, tableSchema) {
|
|
158
|
+
const fieldTypeMap = /* @__PURE__ */ new Map();
|
|
159
|
+
tableSchema.fields.forEach((field) => {
|
|
160
|
+
const fieldName = field.name;
|
|
161
|
+
const fieldTypeStr = field.type.toString().toLowerCase();
|
|
162
|
+
fieldTypeMap.set(fieldName, fieldTypeStr);
|
|
163
|
+
});
|
|
164
|
+
if (Array.isArray(rawResult)) {
|
|
165
|
+
return rawResult.map((item) => processResultWithTypeConversion(item, tableSchema));
|
|
166
|
+
}
|
|
167
|
+
const processedResult = { ...rawResult };
|
|
168
|
+
for (const key in processedResult) {
|
|
169
|
+
const fieldTypeStr = fieldTypeMap.get(key);
|
|
170
|
+
if (!fieldTypeStr) continue;
|
|
171
|
+
if (typeof processedResult[key] === "string") {
|
|
172
|
+
if (fieldTypeStr.includes("int32") || fieldTypeStr.includes("float32")) {
|
|
173
|
+
if (!isNaN(Number(processedResult[key]))) {
|
|
174
|
+
processedResult[key] = Number(processedResult[key]);
|
|
175
|
+
}
|
|
176
|
+
} else if (fieldTypeStr.includes("int64")) {
|
|
177
|
+
processedResult[key] = Number(processedResult[key]);
|
|
178
|
+
} else if (fieldTypeStr.includes("utf8") && key !== "id") {
|
|
179
|
+
try {
|
|
180
|
+
const parsed = JSON.parse(processedResult[key]);
|
|
181
|
+
if (typeof parsed === "object") {
|
|
182
|
+
processedResult[key] = JSON.parse(processedResult[key]);
|
|
183
|
+
}
|
|
184
|
+
} catch {
|
|
185
|
+
}
|
|
140
186
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
187
|
+
} else if (typeof processedResult[key] === "bigint") {
|
|
188
|
+
processedResult[key] = Number(processedResult[key]);
|
|
189
|
+
} else if (fieldTypeStr.includes("float64") && ["createdAt", "updatedAt"].includes(key)) {
|
|
190
|
+
processedResult[key] = new Date(processedResult[key]);
|
|
191
|
+
}
|
|
192
|
+
console.log(key, "processedResult", processedResult);
|
|
144
193
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
194
|
+
return processedResult;
|
|
195
|
+
}
|
|
196
|
+
async function getTableSchema({
|
|
197
|
+
tableName,
|
|
198
|
+
client
|
|
199
|
+
}) {
|
|
200
|
+
try {
|
|
201
|
+
if (!client) {
|
|
202
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
203
|
+
}
|
|
204
|
+
if (!tableName) {
|
|
205
|
+
throw new Error("tableName is required for getTableSchema.");
|
|
206
|
+
}
|
|
207
|
+
} catch (validationError) {
|
|
208
|
+
throw new error.MastraError(
|
|
209
|
+
{
|
|
210
|
+
id: "STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_INVALID_ARGS",
|
|
211
|
+
domain: error.ErrorDomain.STORAGE,
|
|
212
|
+
category: error.ErrorCategory.USER,
|
|
213
|
+
text: validationError.message,
|
|
214
|
+
details: { tableName }
|
|
215
|
+
},
|
|
216
|
+
validationError
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
try {
|
|
220
|
+
const table = await client.openTable(tableName);
|
|
221
|
+
const rawSchema = await table.schema();
|
|
222
|
+
const fields = rawSchema.fields;
|
|
223
|
+
return {
|
|
224
|
+
fields,
|
|
225
|
+
metadata: /* @__PURE__ */ new Map(),
|
|
226
|
+
get names() {
|
|
227
|
+
return fields.map((field) => field.name);
|
|
153
228
|
}
|
|
154
|
-
|
|
155
|
-
|
|
229
|
+
};
|
|
230
|
+
} catch (error$1) {
|
|
231
|
+
throw new error.MastraError(
|
|
232
|
+
{
|
|
233
|
+
id: "STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_FAILED",
|
|
234
|
+
domain: error.ErrorDomain.STORAGE,
|
|
235
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
236
|
+
details: { tableName }
|
|
237
|
+
},
|
|
238
|
+
error$1
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/storage/domains/memory/index.ts
|
|
244
|
+
var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
245
|
+
client;
|
|
246
|
+
operations;
|
|
247
|
+
constructor({ client, operations }) {
|
|
248
|
+
super();
|
|
249
|
+
this.client = client;
|
|
250
|
+
this.operations = operations;
|
|
251
|
+
}
|
|
252
|
+
async getThreadById({ threadId }) {
|
|
253
|
+
try {
|
|
254
|
+
const thread = await this.operations.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
255
|
+
if (!thread) {
|
|
256
|
+
return null;
|
|
156
257
|
}
|
|
157
|
-
|
|
258
|
+
return {
|
|
259
|
+
...thread,
|
|
260
|
+
createdAt: new Date(thread.createdAt),
|
|
261
|
+
updatedAt: new Date(thread.updatedAt)
|
|
262
|
+
};
|
|
263
|
+
} catch (error$1) {
|
|
158
264
|
throw new error.MastraError(
|
|
159
265
|
{
|
|
160
|
-
id: "
|
|
266
|
+
id: "LANCE_STORE_GET_THREAD_BY_ID_FAILED",
|
|
161
267
|
domain: error.ErrorDomain.STORAGE,
|
|
162
|
-
category: error.ErrorCategory.
|
|
163
|
-
text: validationError.message,
|
|
164
|
-
details: { tableName }
|
|
268
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
165
269
|
},
|
|
166
|
-
|
|
270
|
+
error$1
|
|
167
271
|
);
|
|
168
272
|
}
|
|
273
|
+
}
|
|
274
|
+
async getThreadsByResourceId({ resourceId }) {
|
|
169
275
|
try {
|
|
170
|
-
await this.
|
|
276
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
277
|
+
const query = table.query().where(`\`resourceId\` = '${resourceId}'`);
|
|
278
|
+
const records = await query.toArray();
|
|
279
|
+
return processResultWithTypeConversion(
|
|
280
|
+
records,
|
|
281
|
+
await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client })
|
|
282
|
+
);
|
|
171
283
|
} catch (error$1) {
|
|
172
|
-
if (error$1.toString().includes("was not found") || error$1.message?.includes("Table not found")) {
|
|
173
|
-
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
284
|
throw new error.MastraError(
|
|
177
285
|
{
|
|
178
|
-
id: "
|
|
286
|
+
id: "LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
179
287
|
domain: error.ErrorDomain.STORAGE,
|
|
180
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
181
|
-
details: { tableName }
|
|
288
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
182
289
|
},
|
|
183
290
|
error$1
|
|
184
291
|
);
|
|
185
292
|
}
|
|
186
293
|
}
|
|
187
294
|
/**
|
|
188
|
-
*
|
|
189
|
-
* @param
|
|
190
|
-
* @returns
|
|
295
|
+
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
296
|
+
* @param thread - The thread to save
|
|
297
|
+
* @returns The saved thread
|
|
191
298
|
*/
|
|
192
|
-
async
|
|
193
|
-
try {
|
|
194
|
-
if (!this.lanceClient) {
|
|
195
|
-
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
196
|
-
}
|
|
197
|
-
if (!tableName) {
|
|
198
|
-
throw new Error("tableName is required for getTableSchema.");
|
|
199
|
-
}
|
|
200
|
-
} catch (validationError) {
|
|
201
|
-
throw new error.MastraError(
|
|
202
|
-
{
|
|
203
|
-
id: "STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_INVALID_ARGS",
|
|
204
|
-
domain: error.ErrorDomain.STORAGE,
|
|
205
|
-
category: error.ErrorCategory.USER,
|
|
206
|
-
text: validationError.message,
|
|
207
|
-
details: { tableName }
|
|
208
|
-
},
|
|
209
|
-
validationError
|
|
210
|
-
);
|
|
211
|
-
}
|
|
299
|
+
async saveThread({ thread }) {
|
|
212
300
|
try {
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
return
|
|
217
|
-
fields,
|
|
218
|
-
metadata: /* @__PURE__ */ new Map(),
|
|
219
|
-
get names() {
|
|
220
|
-
return fields.map((field) => field.name);
|
|
221
|
-
}
|
|
222
|
-
};
|
|
301
|
+
const record = { ...thread, metadata: JSON.stringify(thread.metadata) };
|
|
302
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
303
|
+
await table.add([record], { mode: "append" });
|
|
304
|
+
return thread;
|
|
223
305
|
} catch (error$1) {
|
|
224
306
|
throw new error.MastraError(
|
|
225
307
|
{
|
|
226
|
-
id: "
|
|
308
|
+
id: "LANCE_STORE_SAVE_THREAD_FAILED",
|
|
227
309
|
domain: error.ErrorDomain.STORAGE,
|
|
228
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
229
|
-
details: { tableName }
|
|
310
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
230
311
|
},
|
|
231
312
|
error$1
|
|
232
313
|
);
|
|
233
314
|
}
|
|
234
315
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
316
|
+
async updateThread({
|
|
317
|
+
id,
|
|
318
|
+
title,
|
|
319
|
+
metadata
|
|
320
|
+
}) {
|
|
321
|
+
const maxRetries = 5;
|
|
322
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
323
|
+
try {
|
|
324
|
+
const current = await this.getThreadById({ threadId: id });
|
|
325
|
+
if (!current) {
|
|
326
|
+
throw new Error(`Thread with id ${id} not found`);
|
|
327
|
+
}
|
|
328
|
+
const mergedMetadata = { ...current.metadata, ...metadata };
|
|
329
|
+
const record = {
|
|
330
|
+
id,
|
|
331
|
+
title,
|
|
332
|
+
metadata: JSON.stringify(mergedMetadata),
|
|
333
|
+
updatedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
334
|
+
};
|
|
335
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
336
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
337
|
+
const updatedThread = await this.getThreadById({ threadId: id });
|
|
338
|
+
if (!updatedThread) {
|
|
339
|
+
throw new Error(`Failed to retrieve updated thread ${id}`);
|
|
340
|
+
}
|
|
341
|
+
return updatedThread;
|
|
342
|
+
} catch (error$1) {
|
|
343
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
344
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
345
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
throw new error.MastraError(
|
|
349
|
+
{
|
|
350
|
+
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
351
|
+
domain: error.ErrorDomain.STORAGE,
|
|
352
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
353
|
+
},
|
|
354
|
+
error$1
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
throw new error.MastraError(
|
|
359
|
+
{
|
|
360
|
+
id: "LANCE_STORE_UPDATE_THREAD_FAILED",
|
|
361
|
+
domain: error.ErrorDomain.STORAGE,
|
|
362
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
363
|
+
},
|
|
364
|
+
new Error("All retries exhausted")
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
async deleteThread({ threadId }) {
|
|
368
|
+
try {
|
|
369
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
370
|
+
await table.delete(`id = '${threadId}'`);
|
|
371
|
+
const messagesTable = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
372
|
+
await messagesTable.delete(`thread_id = '${threadId}'`);
|
|
373
|
+
} catch (error$1) {
|
|
374
|
+
throw new error.MastraError(
|
|
375
|
+
{
|
|
376
|
+
id: "LANCE_STORE_DELETE_THREAD_FAILED",
|
|
377
|
+
domain: error.ErrorDomain.STORAGE,
|
|
378
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
379
|
+
},
|
|
380
|
+
error$1
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async getMessages({
|
|
385
|
+
threadId,
|
|
386
|
+
resourceId,
|
|
387
|
+
selectBy,
|
|
388
|
+
format,
|
|
389
|
+
threadConfig
|
|
390
|
+
}) {
|
|
391
|
+
try {
|
|
392
|
+
if (threadConfig) {
|
|
393
|
+
throw new Error("ThreadConfig is not supported by LanceDB storage");
|
|
394
|
+
}
|
|
395
|
+
const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
|
|
396
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
397
|
+
let allRecords = [];
|
|
398
|
+
if (selectBy?.include && selectBy.include.length > 0) {
|
|
399
|
+
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
400
|
+
for (const threadId2 of threadIds) {
|
|
401
|
+
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
402
|
+
let threadRecords = await threadQuery.toArray();
|
|
403
|
+
allRecords.push(...threadRecords);
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
let query = table.query().where(`\`thread_id\` = '${threadId}'`);
|
|
407
|
+
allRecords = await query.toArray();
|
|
408
|
+
}
|
|
409
|
+
allRecords.sort((a, b) => {
|
|
410
|
+
const dateA = new Date(a.createdAt).getTime();
|
|
411
|
+
const dateB = new Date(b.createdAt).getTime();
|
|
412
|
+
return dateA - dateB;
|
|
413
|
+
});
|
|
414
|
+
if (selectBy?.include && selectBy.include.length > 0) {
|
|
415
|
+
allRecords = this.processMessagesWithContext(allRecords, selectBy.include);
|
|
416
|
+
}
|
|
417
|
+
if (limit !== Number.MAX_SAFE_INTEGER) {
|
|
418
|
+
allRecords = allRecords.slice(-limit);
|
|
419
|
+
}
|
|
420
|
+
const messages = processResultWithTypeConversion(
|
|
421
|
+
allRecords,
|
|
422
|
+
await getTableSchema({ tableName: storage.TABLE_MESSAGES, client: this.client })
|
|
423
|
+
);
|
|
424
|
+
const normalized = messages.map((msg) => {
|
|
425
|
+
const { thread_id, ...rest } = msg;
|
|
426
|
+
return {
|
|
427
|
+
...rest,
|
|
428
|
+
threadId: thread_id,
|
|
429
|
+
content: typeof msg.content === "string" ? (() => {
|
|
430
|
+
try {
|
|
431
|
+
return JSON.parse(msg.content);
|
|
432
|
+
} catch {
|
|
433
|
+
return msg.content;
|
|
434
|
+
}
|
|
435
|
+
})() : msg.content
|
|
436
|
+
};
|
|
437
|
+
});
|
|
438
|
+
const list = new agent.MessageList({ threadId, resourceId }).add(normalized, "memory");
|
|
439
|
+
if (format === "v2") return list.get.all.v2();
|
|
440
|
+
return list.get.all.v1();
|
|
441
|
+
} catch (error$1) {
|
|
442
|
+
throw new error.MastraError(
|
|
443
|
+
{
|
|
444
|
+
id: "LANCE_STORE_GET_MESSAGES_FAILED",
|
|
445
|
+
domain: error.ErrorDomain.STORAGE,
|
|
446
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
447
|
+
},
|
|
448
|
+
error$1
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
async saveMessages(args) {
|
|
453
|
+
try {
|
|
454
|
+
const { messages, format = "v1" } = args;
|
|
455
|
+
if (messages.length === 0) {
|
|
456
|
+
return [];
|
|
457
|
+
}
|
|
458
|
+
const threadId = messages[0]?.threadId;
|
|
459
|
+
if (!threadId) {
|
|
460
|
+
throw new Error("Thread ID is required");
|
|
461
|
+
}
|
|
462
|
+
for (const message of messages) {
|
|
463
|
+
if (!message.id) {
|
|
464
|
+
throw new Error("Message ID is required");
|
|
465
|
+
}
|
|
466
|
+
if (!message.threadId) {
|
|
467
|
+
throw new Error("Thread ID is required for all messages");
|
|
468
|
+
}
|
|
469
|
+
if (message.resourceId === null || message.resourceId === void 0) {
|
|
470
|
+
throw new Error("Resource ID cannot be null or undefined");
|
|
471
|
+
}
|
|
472
|
+
if (!message.content) {
|
|
473
|
+
throw new Error("Message content is required");
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const transformedMessages = messages.map((message) => {
|
|
477
|
+
const { threadId: threadId2, type, ...rest } = message;
|
|
478
|
+
return {
|
|
479
|
+
...rest,
|
|
480
|
+
thread_id: threadId2,
|
|
481
|
+
type: type ?? "v2",
|
|
482
|
+
content: JSON.stringify(message.content)
|
|
483
|
+
};
|
|
484
|
+
});
|
|
485
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
486
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
|
|
487
|
+
const threadsTable = await this.client.openTable(storage.TABLE_THREADS);
|
|
488
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
489
|
+
const updateRecord = { id: threadId, updatedAt: currentTime };
|
|
490
|
+
await threadsTable.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([updateRecord]);
|
|
491
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
492
|
+
if (format === `v2`) return list.get.all.v2();
|
|
493
|
+
return list.get.all.v1();
|
|
494
|
+
} catch (error$1) {
|
|
495
|
+
throw new error.MastraError(
|
|
496
|
+
{
|
|
497
|
+
id: "LANCE_STORE_SAVE_MESSAGES_FAILED",
|
|
498
|
+
domain: error.ErrorDomain.STORAGE,
|
|
499
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
500
|
+
},
|
|
501
|
+
error$1
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
506
|
+
try {
|
|
507
|
+
const { resourceId, page = 0, perPage = 10 } = args;
|
|
508
|
+
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
509
|
+
const total = await table.countRows(`\`resourceId\` = '${resourceId}'`);
|
|
510
|
+
const query = table.query().where(`\`resourceId\` = '${resourceId}'`);
|
|
511
|
+
const offset = page * perPage;
|
|
512
|
+
query.limit(perPage);
|
|
513
|
+
if (offset > 0) {
|
|
514
|
+
query.offset(offset);
|
|
515
|
+
}
|
|
516
|
+
const records = await query.toArray();
|
|
517
|
+
records.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
518
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_THREADS, client: this.client });
|
|
519
|
+
const threads = records.map((record) => processResultWithTypeConversion(record, schema));
|
|
520
|
+
return {
|
|
521
|
+
threads,
|
|
522
|
+
total,
|
|
523
|
+
page,
|
|
524
|
+
perPage,
|
|
525
|
+
hasMore: total > (page + 1) * perPage
|
|
526
|
+
};
|
|
527
|
+
} catch (error$1) {
|
|
528
|
+
throw new error.MastraError(
|
|
529
|
+
{
|
|
530
|
+
id: "LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
|
|
531
|
+
domain: error.ErrorDomain.STORAGE,
|
|
532
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
533
|
+
},
|
|
534
|
+
error$1
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
540
|
+
* @param records - The sorted array of records to process
|
|
541
|
+
* @param include - The array of include specifications with context parameters
|
|
542
|
+
* @returns The processed array with context messages included
|
|
543
|
+
*/
|
|
544
|
+
processMessagesWithContext(records, include) {
|
|
545
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
546
|
+
if (messagesWithContext.length === 0) {
|
|
547
|
+
return records;
|
|
548
|
+
}
|
|
549
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
550
|
+
records.forEach((message, index) => {
|
|
551
|
+
messageIndexMap.set(message.id, index);
|
|
552
|
+
});
|
|
553
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
554
|
+
for (const item of messagesWithContext) {
|
|
555
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
556
|
+
if (messageIndex !== void 0) {
|
|
557
|
+
if (item.withPreviousMessages) {
|
|
558
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
559
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
560
|
+
additionalIndices.add(i);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (item.withNextMessages) {
|
|
564
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
565
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
566
|
+
additionalIndices.add(i);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if (additionalIndices.size === 0) {
|
|
572
|
+
return records;
|
|
573
|
+
}
|
|
574
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
575
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
576
|
+
records.forEach((record, index) => {
|
|
577
|
+
if (originalMatchIds.has(record.id)) {
|
|
578
|
+
allIndices.add(index);
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
additionalIndices.forEach((index) => {
|
|
582
|
+
allIndices.add(index);
|
|
583
|
+
});
|
|
584
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
585
|
+
}
|
|
586
|
+
async getMessagesPaginated(args) {
|
|
587
|
+
try {
|
|
588
|
+
const { threadId, resourceId, selectBy, format = "v1" } = args;
|
|
589
|
+
if (!threadId) {
|
|
590
|
+
throw new Error("Thread ID is required for getMessagesPaginated");
|
|
591
|
+
}
|
|
592
|
+
const page = selectBy?.pagination?.page ?? 0;
|
|
593
|
+
const perPage = selectBy?.pagination?.perPage ?? 10;
|
|
594
|
+
const dateRange = selectBy?.pagination?.dateRange;
|
|
595
|
+
const fromDate = dateRange?.start;
|
|
596
|
+
const toDate = dateRange?.end;
|
|
597
|
+
const table = await this.client.openTable(storage.TABLE_MESSAGES);
|
|
598
|
+
const messages = [];
|
|
599
|
+
if (selectBy?.include && Array.isArray(selectBy.include)) {
|
|
600
|
+
const threadIds = [...new Set(selectBy.include.map((item) => item.threadId))];
|
|
601
|
+
const allThreadMessages = [];
|
|
602
|
+
for (const threadId2 of threadIds) {
|
|
603
|
+
const threadQuery = table.query().where(`thread_id = '${threadId2}'`);
|
|
604
|
+
let threadRecords = await threadQuery.toArray();
|
|
605
|
+
if (fromDate) threadRecords = threadRecords.filter((m) => m.createdAt >= fromDate.getTime());
|
|
606
|
+
if (toDate) threadRecords = threadRecords.filter((m) => m.createdAt <= toDate.getTime());
|
|
607
|
+
allThreadMessages.push(...threadRecords);
|
|
608
|
+
}
|
|
609
|
+
allThreadMessages.sort((a, b) => a.createdAt - b.createdAt);
|
|
610
|
+
const contextMessages = this.processMessagesWithContext(allThreadMessages, selectBy.include);
|
|
611
|
+
messages.push(...contextMessages);
|
|
612
|
+
}
|
|
613
|
+
const conditions = [`thread_id = '${threadId}'`];
|
|
614
|
+
if (resourceId) {
|
|
615
|
+
conditions.push(`\`resourceId\` = '${resourceId}'`);
|
|
616
|
+
}
|
|
617
|
+
if (fromDate) {
|
|
618
|
+
conditions.push(`\`createdAt\` >= ${fromDate.getTime()}`);
|
|
619
|
+
}
|
|
620
|
+
if (toDate) {
|
|
621
|
+
conditions.push(`\`createdAt\` <= ${toDate.getTime()}`);
|
|
622
|
+
}
|
|
623
|
+
let total = 0;
|
|
624
|
+
if (conditions.length > 0) {
|
|
625
|
+
total = await table.countRows(conditions.join(" AND "));
|
|
626
|
+
} else {
|
|
627
|
+
total = await table.countRows();
|
|
628
|
+
}
|
|
629
|
+
if (total === 0 && messages.length === 0) {
|
|
630
|
+
return {
|
|
631
|
+
messages: [],
|
|
632
|
+
total: 0,
|
|
633
|
+
page,
|
|
634
|
+
perPage,
|
|
635
|
+
hasMore: false
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
const excludeIds = messages.map((m) => m.id);
|
|
639
|
+
let selectedMessages = [];
|
|
640
|
+
if (selectBy?.last && selectBy.last > 0) {
|
|
641
|
+
const query = table.query();
|
|
642
|
+
if (conditions.length > 0) {
|
|
643
|
+
query.where(conditions.join(" AND "));
|
|
644
|
+
}
|
|
645
|
+
let records = await query.toArray();
|
|
646
|
+
records = records.sort((a, b) => a.createdAt - b.createdAt);
|
|
647
|
+
if (excludeIds.length > 0) {
|
|
648
|
+
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
649
|
+
}
|
|
650
|
+
selectedMessages = records.slice(-selectBy.last);
|
|
651
|
+
} else {
|
|
652
|
+
const query = table.query();
|
|
653
|
+
if (conditions.length > 0) {
|
|
654
|
+
query.where(conditions.join(" AND "));
|
|
655
|
+
}
|
|
656
|
+
let records = await query.toArray();
|
|
657
|
+
records = records.sort((a, b) => a.createdAt - b.createdAt);
|
|
658
|
+
if (excludeIds.length > 0) {
|
|
659
|
+
records = records.filter((m) => !excludeIds.includes(m.id));
|
|
660
|
+
}
|
|
661
|
+
selectedMessages = records.slice(page * perPage, (page + 1) * perPage);
|
|
662
|
+
}
|
|
663
|
+
const allMessages = [...messages, ...selectedMessages];
|
|
664
|
+
const seen = /* @__PURE__ */ new Set();
|
|
665
|
+
const dedupedMessages = allMessages.filter((m) => {
|
|
666
|
+
const key = `${m.id}:${m.thread_id}`;
|
|
667
|
+
if (seen.has(key)) return false;
|
|
668
|
+
seen.add(key);
|
|
669
|
+
return true;
|
|
670
|
+
});
|
|
671
|
+
const formattedMessages = dedupedMessages.map((msg) => {
|
|
672
|
+
const { thread_id, ...rest } = msg;
|
|
673
|
+
return {
|
|
674
|
+
...rest,
|
|
675
|
+
threadId: thread_id,
|
|
676
|
+
content: typeof msg.content === "string" ? (() => {
|
|
677
|
+
try {
|
|
678
|
+
return JSON.parse(msg.content);
|
|
679
|
+
} catch {
|
|
680
|
+
return msg.content;
|
|
681
|
+
}
|
|
682
|
+
})() : msg.content
|
|
683
|
+
};
|
|
684
|
+
});
|
|
685
|
+
const list = new agent.MessageList().add(formattedMessages, "memory");
|
|
686
|
+
return {
|
|
687
|
+
messages: format === "v2" ? list.get.all.v2() : list.get.all.v1(),
|
|
688
|
+
total,
|
|
689
|
+
// Total should be the count of messages matching the filters
|
|
690
|
+
page,
|
|
691
|
+
perPage,
|
|
692
|
+
hasMore: total > (page + 1) * perPage
|
|
693
|
+
};
|
|
694
|
+
} catch (error$1) {
|
|
695
|
+
throw new error.MastraError(
|
|
696
|
+
{
|
|
697
|
+
id: "LANCE_STORE_GET_MESSAGES_PAGINATED_FAILED",
|
|
698
|
+
domain: error.ErrorDomain.STORAGE,
|
|
699
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
700
|
+
},
|
|
701
|
+
error$1
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Parse message data from LanceDB record format to MastraMessageV2 format
|
|
707
|
+
*/
|
|
708
|
+
parseMessageData(data) {
|
|
709
|
+
const { thread_id, ...rest } = data;
|
|
710
|
+
return {
|
|
711
|
+
...rest,
|
|
712
|
+
threadId: thread_id,
|
|
713
|
+
content: typeof data.content === "string" ? (() => {
|
|
714
|
+
try {
|
|
715
|
+
return JSON.parse(data.content);
|
|
716
|
+
} catch {
|
|
717
|
+
return data.content;
|
|
718
|
+
}
|
|
719
|
+
})() : data.content,
|
|
720
|
+
createdAt: new Date(data.createdAt),
|
|
721
|
+
updatedAt: new Date(data.updatedAt)
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
async updateMessages(args) {
|
|
725
|
+
const { messages } = args;
|
|
726
|
+
this.logger.debug("Updating messages", { count: messages.length });
|
|
727
|
+
if (!messages.length) {
|
|
728
|
+
return [];
|
|
729
|
+
}
|
|
730
|
+
const updatedMessages = [];
|
|
731
|
+
const affectedThreadIds = /* @__PURE__ */ new Set();
|
|
732
|
+
try {
|
|
733
|
+
for (const updateData of messages) {
|
|
734
|
+
const { id, ...updates } = updateData;
|
|
735
|
+
const existingMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
736
|
+
if (!existingMessage) {
|
|
737
|
+
this.logger.warn("Message not found for update", { id });
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
const existingMsg = this.parseMessageData(existingMessage);
|
|
741
|
+
const originalThreadId = existingMsg.threadId;
|
|
742
|
+
affectedThreadIds.add(originalThreadId);
|
|
743
|
+
const updatePayload = {};
|
|
744
|
+
if ("role" in updates && updates.role !== void 0) updatePayload.role = updates.role;
|
|
745
|
+
if ("type" in updates && updates.type !== void 0) updatePayload.type = updates.type;
|
|
746
|
+
if ("resourceId" in updates && updates.resourceId !== void 0) updatePayload.resourceId = updates.resourceId;
|
|
747
|
+
if ("threadId" in updates && updates.threadId !== void 0 && updates.threadId !== null) {
|
|
748
|
+
updatePayload.thread_id = updates.threadId;
|
|
749
|
+
affectedThreadIds.add(updates.threadId);
|
|
750
|
+
}
|
|
751
|
+
if (updates.content) {
|
|
752
|
+
const existingContent = existingMsg.content;
|
|
753
|
+
let newContent = { ...existingContent };
|
|
754
|
+
if (updates.content.metadata !== void 0) {
|
|
755
|
+
newContent.metadata = {
|
|
756
|
+
...existingContent.metadata || {},
|
|
757
|
+
...updates.content.metadata || {}
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
if (updates.content.content !== void 0) {
|
|
761
|
+
newContent.content = updates.content.content;
|
|
762
|
+
}
|
|
763
|
+
if ("parts" in updates.content && updates.content.parts !== void 0) {
|
|
764
|
+
newContent.parts = updates.content.parts;
|
|
765
|
+
}
|
|
766
|
+
updatePayload.content = JSON.stringify(newContent);
|
|
767
|
+
}
|
|
768
|
+
await this.operations.insert({ tableName: storage.TABLE_MESSAGES, record: { id, ...updatePayload } });
|
|
769
|
+
const updatedMessage = await this.operations.load({ tableName: storage.TABLE_MESSAGES, keys: { id } });
|
|
770
|
+
if (updatedMessage) {
|
|
771
|
+
updatedMessages.push(this.parseMessageData(updatedMessage));
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
for (const threadId of affectedThreadIds) {
|
|
775
|
+
await this.operations.insert({
|
|
776
|
+
tableName: storage.TABLE_THREADS,
|
|
777
|
+
record: { id: threadId, updatedAt: Date.now() }
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
return updatedMessages;
|
|
781
|
+
} catch (error$1) {
|
|
782
|
+
throw new error.MastraError(
|
|
783
|
+
{
|
|
784
|
+
id: "LANCE_STORE_UPDATE_MESSAGES_FAILED",
|
|
785
|
+
domain: error.ErrorDomain.STORAGE,
|
|
786
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
787
|
+
details: { count: messages.length }
|
|
788
|
+
},
|
|
789
|
+
error$1
|
|
790
|
+
);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
async getResourceById({ resourceId }) {
|
|
794
|
+
try {
|
|
795
|
+
const resource = await this.operations.load({ tableName: storage.TABLE_RESOURCES, keys: { id: resourceId } });
|
|
796
|
+
if (!resource) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
let createdAt;
|
|
800
|
+
let updatedAt;
|
|
801
|
+
try {
|
|
802
|
+
if (resource.createdAt instanceof Date) {
|
|
803
|
+
createdAt = resource.createdAt;
|
|
804
|
+
} else if (typeof resource.createdAt === "string") {
|
|
805
|
+
createdAt = new Date(resource.createdAt);
|
|
806
|
+
} else if (typeof resource.createdAt === "number") {
|
|
807
|
+
createdAt = new Date(resource.createdAt);
|
|
808
|
+
} else {
|
|
809
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
810
|
+
}
|
|
811
|
+
if (isNaN(createdAt.getTime())) {
|
|
812
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
813
|
+
}
|
|
814
|
+
} catch {
|
|
815
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
816
|
+
}
|
|
817
|
+
try {
|
|
818
|
+
if (resource.updatedAt instanceof Date) {
|
|
819
|
+
updatedAt = resource.updatedAt;
|
|
820
|
+
} else if (typeof resource.updatedAt === "string") {
|
|
821
|
+
updatedAt = new Date(resource.updatedAt);
|
|
822
|
+
} else if (typeof resource.updatedAt === "number") {
|
|
823
|
+
updatedAt = new Date(resource.updatedAt);
|
|
824
|
+
} else {
|
|
825
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
826
|
+
}
|
|
827
|
+
if (isNaN(updatedAt.getTime())) {
|
|
828
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
829
|
+
}
|
|
830
|
+
} catch {
|
|
831
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
832
|
+
}
|
|
833
|
+
let workingMemory = resource.workingMemory;
|
|
834
|
+
if (workingMemory === null || workingMemory === void 0) {
|
|
835
|
+
workingMemory = void 0;
|
|
836
|
+
} else if (workingMemory === "") {
|
|
837
|
+
workingMemory = "";
|
|
838
|
+
} else if (typeof workingMemory === "object") {
|
|
839
|
+
workingMemory = JSON.stringify(workingMemory);
|
|
840
|
+
}
|
|
841
|
+
let metadata = resource.metadata;
|
|
842
|
+
if (metadata === "" || metadata === null || metadata === void 0) {
|
|
843
|
+
metadata = void 0;
|
|
844
|
+
} else if (typeof metadata === "string") {
|
|
845
|
+
try {
|
|
846
|
+
metadata = JSON.parse(metadata);
|
|
847
|
+
} catch {
|
|
848
|
+
metadata = metadata;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return {
|
|
852
|
+
...resource,
|
|
853
|
+
createdAt,
|
|
854
|
+
updatedAt,
|
|
855
|
+
workingMemory,
|
|
856
|
+
metadata
|
|
857
|
+
};
|
|
858
|
+
} catch (error$1) {
|
|
859
|
+
throw new error.MastraError(
|
|
860
|
+
{
|
|
861
|
+
id: "LANCE_STORE_GET_RESOURCE_BY_ID_FAILED",
|
|
862
|
+
domain: error.ErrorDomain.STORAGE,
|
|
863
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
864
|
+
},
|
|
865
|
+
error$1
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
async saveResource({ resource }) {
|
|
870
|
+
try {
|
|
871
|
+
const record = {
|
|
872
|
+
...resource,
|
|
873
|
+
metadata: resource.metadata ? JSON.stringify(resource.metadata) : "",
|
|
874
|
+
createdAt: resource.createdAt.getTime(),
|
|
875
|
+
// Store as timestamp (milliseconds)
|
|
876
|
+
updatedAt: resource.updatedAt.getTime()
|
|
877
|
+
// Store as timestamp (milliseconds)
|
|
878
|
+
};
|
|
879
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
880
|
+
await table.add([record], { mode: "append" });
|
|
881
|
+
return resource;
|
|
882
|
+
} catch (error$1) {
|
|
883
|
+
throw new error.MastraError(
|
|
884
|
+
{
|
|
885
|
+
id: "LANCE_STORE_SAVE_RESOURCE_FAILED",
|
|
886
|
+
domain: error.ErrorDomain.STORAGE,
|
|
887
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
888
|
+
},
|
|
889
|
+
error$1
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
async updateResource({
|
|
894
|
+
resourceId,
|
|
895
|
+
workingMemory,
|
|
896
|
+
metadata
|
|
897
|
+
}) {
|
|
898
|
+
const maxRetries = 3;
|
|
899
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
900
|
+
try {
|
|
901
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
902
|
+
if (!existingResource) {
|
|
903
|
+
const newResource = {
|
|
904
|
+
id: resourceId,
|
|
905
|
+
workingMemory,
|
|
906
|
+
metadata: metadata || {},
|
|
907
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
908
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
909
|
+
};
|
|
910
|
+
return this.saveResource({ resource: newResource });
|
|
911
|
+
}
|
|
912
|
+
const updatedResource = {
|
|
913
|
+
...existingResource,
|
|
914
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
915
|
+
metadata: {
|
|
916
|
+
...existingResource.metadata,
|
|
917
|
+
...metadata
|
|
918
|
+
},
|
|
919
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
920
|
+
};
|
|
921
|
+
const record = {
|
|
922
|
+
id: resourceId,
|
|
923
|
+
workingMemory: updatedResource.workingMemory || "",
|
|
924
|
+
metadata: updatedResource.metadata ? JSON.stringify(updatedResource.metadata) : "",
|
|
925
|
+
updatedAt: updatedResource.updatedAt.getTime()
|
|
926
|
+
// Store as timestamp (milliseconds)
|
|
927
|
+
};
|
|
928
|
+
const table = await this.client.openTable(storage.TABLE_RESOURCES);
|
|
929
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
930
|
+
return updatedResource;
|
|
931
|
+
} catch (error$1) {
|
|
932
|
+
if (error$1.message?.includes("Commit conflict") && attempt < maxRetries - 1) {
|
|
933
|
+
const delay = Math.pow(2, attempt) * 10;
|
|
934
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
throw new error.MastraError(
|
|
938
|
+
{
|
|
939
|
+
id: "LANCE_STORE_UPDATE_RESOURCE_FAILED",
|
|
940
|
+
domain: error.ErrorDomain.STORAGE,
|
|
941
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
942
|
+
},
|
|
943
|
+
error$1
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
throw new Error("Unexpected end of retry loop");
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
var StoreOperationsLance = class extends storage.StoreOperations {
|
|
951
|
+
client;
|
|
952
|
+
constructor({ client }) {
|
|
953
|
+
super();
|
|
954
|
+
this.client = client;
|
|
955
|
+
}
|
|
956
|
+
getDefaultValue(type) {
|
|
957
|
+
switch (type) {
|
|
958
|
+
case "text":
|
|
959
|
+
return "''";
|
|
960
|
+
case "timestamp":
|
|
961
|
+
return "CURRENT_TIMESTAMP";
|
|
962
|
+
case "integer":
|
|
963
|
+
case "bigint":
|
|
964
|
+
return "0";
|
|
965
|
+
case "jsonb":
|
|
966
|
+
return "'{}'";
|
|
967
|
+
case "uuid":
|
|
247
968
|
return "''";
|
|
248
969
|
default:
|
|
249
970
|
return super.getDefaultValue(type);
|
|
250
971
|
}
|
|
251
972
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
973
|
+
async hasColumn(tableName, columnName) {
|
|
974
|
+
const table = await this.client.openTable(tableName);
|
|
975
|
+
const schema = await table.schema();
|
|
976
|
+
return schema.fields.some((field) => field.name === columnName);
|
|
977
|
+
}
|
|
978
|
+
translateSchema(schema) {
|
|
979
|
+
const fields = Object.entries(schema).map(([name, column]) => {
|
|
980
|
+
let arrowType;
|
|
981
|
+
switch (column.type.toLowerCase()) {
|
|
982
|
+
case "text":
|
|
983
|
+
case "uuid":
|
|
984
|
+
arrowType = new apacheArrow.Utf8();
|
|
985
|
+
break;
|
|
986
|
+
case "int":
|
|
987
|
+
case "integer":
|
|
988
|
+
arrowType = new apacheArrow.Int32();
|
|
989
|
+
break;
|
|
990
|
+
case "bigint":
|
|
991
|
+
arrowType = new apacheArrow.Float64();
|
|
992
|
+
break;
|
|
993
|
+
case "float":
|
|
994
|
+
arrowType = new apacheArrow.Float32();
|
|
995
|
+
break;
|
|
996
|
+
case "jsonb":
|
|
997
|
+
case "json":
|
|
998
|
+
arrowType = new apacheArrow.Utf8();
|
|
999
|
+
break;
|
|
1000
|
+
case "binary":
|
|
1001
|
+
arrowType = new apacheArrow.Binary();
|
|
1002
|
+
break;
|
|
1003
|
+
case "timestamp":
|
|
1004
|
+
arrowType = new apacheArrow.Float64();
|
|
1005
|
+
break;
|
|
1006
|
+
default:
|
|
1007
|
+
arrowType = new apacheArrow.Utf8();
|
|
1008
|
+
}
|
|
1009
|
+
return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
|
|
1010
|
+
});
|
|
1011
|
+
return new apacheArrow.Schema(fields);
|
|
1012
|
+
}
|
|
1013
|
+
async createTable({
|
|
1014
|
+
tableName,
|
|
1015
|
+
schema
|
|
1016
|
+
}) {
|
|
1017
|
+
try {
|
|
1018
|
+
if (!this.client) {
|
|
1019
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
1020
|
+
}
|
|
1021
|
+
if (!tableName) {
|
|
1022
|
+
throw new Error("tableName is required for createTable.");
|
|
1023
|
+
}
|
|
1024
|
+
if (!schema) {
|
|
1025
|
+
throw new Error("schema is required for createTable.");
|
|
1026
|
+
}
|
|
1027
|
+
} catch (error$1) {
|
|
1028
|
+
throw new error.MastraError(
|
|
1029
|
+
{
|
|
1030
|
+
id: "STORAGE_LANCE_STORAGE_CREATE_TABLE_INVALID_ARGS",
|
|
1031
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1032
|
+
category: error.ErrorCategory.USER,
|
|
1033
|
+
details: { tableName }
|
|
1034
|
+
},
|
|
1035
|
+
error$1
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
try {
|
|
1039
|
+
const arrowSchema = this.translateSchema(schema);
|
|
1040
|
+
await this.client.createEmptyTable(tableName, arrowSchema);
|
|
1041
|
+
} catch (error$1) {
|
|
1042
|
+
if (error$1.message?.includes("already exists")) {
|
|
1043
|
+
this.logger.debug(`Table '${tableName}' already exists, skipping create`);
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
throw new error.MastraError(
|
|
1047
|
+
{
|
|
1048
|
+
id: "STORAGE_LANCE_STORAGE_CREATE_TABLE_FAILED",
|
|
1049
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1050
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1051
|
+
details: { tableName }
|
|
1052
|
+
},
|
|
1053
|
+
error$1
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
async dropTable({ tableName }) {
|
|
1058
|
+
try {
|
|
1059
|
+
if (!this.client) {
|
|
1060
|
+
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
1061
|
+
}
|
|
1062
|
+
if (!tableName) {
|
|
1063
|
+
throw new Error("tableName is required for dropTable.");
|
|
1064
|
+
}
|
|
1065
|
+
} catch (validationError) {
|
|
1066
|
+
throw new error.MastraError(
|
|
1067
|
+
{
|
|
1068
|
+
id: "STORAGE_LANCE_STORAGE_DROP_TABLE_INVALID_ARGS",
|
|
1069
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1070
|
+
category: error.ErrorCategory.USER,
|
|
1071
|
+
text: validationError.message,
|
|
1072
|
+
details: { tableName }
|
|
1073
|
+
},
|
|
1074
|
+
validationError
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
try {
|
|
1078
|
+
await this.client.dropTable(tableName);
|
|
1079
|
+
} catch (error$1) {
|
|
1080
|
+
if (error$1.toString().includes("was not found") || error$1.message?.includes("Table not found")) {
|
|
1081
|
+
this.logger.debug(`Table '${tableName}' does not exist, skipping drop`);
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
throw new error.MastraError(
|
|
1085
|
+
{
|
|
1086
|
+
id: "STORAGE_LANCE_STORAGE_DROP_TABLE_FAILED",
|
|
1087
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1088
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1089
|
+
details: { tableName }
|
|
1090
|
+
},
|
|
1091
|
+
error$1
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
258
1095
|
async alterTable({
|
|
259
1096
|
tableName,
|
|
260
1097
|
schema,
|
|
261
1098
|
ifNotExists
|
|
262
1099
|
}) {
|
|
263
1100
|
try {
|
|
264
|
-
if (!this.
|
|
1101
|
+
if (!this.client) {
|
|
265
1102
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
266
1103
|
}
|
|
267
1104
|
if (!tableName) {
|
|
@@ -287,7 +1124,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
287
1124
|
);
|
|
288
1125
|
}
|
|
289
1126
|
try {
|
|
290
|
-
const table = await this.
|
|
1127
|
+
const table = await this.client.openTable(tableName);
|
|
291
1128
|
const currentSchema = await table.schema();
|
|
292
1129
|
const existingFields = new Set(currentSchema.fields.map((f) => f.name));
|
|
293
1130
|
const typeMap = {
|
|
@@ -323,7 +1160,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
323
1160
|
}
|
|
324
1161
|
async clearTable({ tableName }) {
|
|
325
1162
|
try {
|
|
326
|
-
if (!this.
|
|
1163
|
+
if (!this.client) {
|
|
327
1164
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
328
1165
|
}
|
|
329
1166
|
if (!tableName) {
|
|
@@ -342,7 +1179,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
342
1179
|
);
|
|
343
1180
|
}
|
|
344
1181
|
try {
|
|
345
|
-
const table = await this.
|
|
1182
|
+
const table = await this.client.openTable(tableName);
|
|
346
1183
|
await table.delete("1=1");
|
|
347
1184
|
} catch (error$1) {
|
|
348
1185
|
throw new error.MastraError(
|
|
@@ -356,14 +1193,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
356
1193
|
);
|
|
357
1194
|
}
|
|
358
1195
|
}
|
|
359
|
-
/**
|
|
360
|
-
* Insert a single record into a table. This function overwrites the existing record if it exists. Use this function for inserting records into tables with custom schemas.
|
|
361
|
-
* @param tableName The name of the table to insert into.
|
|
362
|
-
* @param record The record to insert.
|
|
363
|
-
*/
|
|
364
1196
|
async insert({ tableName, record }) {
|
|
365
1197
|
try {
|
|
366
|
-
if (!this.
|
|
1198
|
+
if (!this.client) {
|
|
367
1199
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
368
1200
|
}
|
|
369
1201
|
if (!tableName) {
|
|
@@ -385,8 +1217,8 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
385
1217
|
);
|
|
386
1218
|
}
|
|
387
1219
|
try {
|
|
388
|
-
const table = await this.
|
|
389
|
-
const primaryId =
|
|
1220
|
+
const table = await this.client.openTable(tableName);
|
|
1221
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
390
1222
|
const processedRecord = { ...record };
|
|
391
1223
|
for (const key in processedRecord) {
|
|
392
1224
|
if (processedRecord[key] !== null && typeof processedRecord[key] === "object" && !(processedRecord[key] instanceof Date)) {
|
|
@@ -394,6 +1226,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
394
1226
|
processedRecord[key] = JSON.stringify(processedRecord[key]);
|
|
395
1227
|
}
|
|
396
1228
|
}
|
|
1229
|
+
console.log(await table.schema());
|
|
397
1230
|
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([processedRecord]);
|
|
398
1231
|
} catch (error$1) {
|
|
399
1232
|
throw new error.MastraError(
|
|
@@ -407,14 +1240,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
407
1240
|
);
|
|
408
1241
|
}
|
|
409
1242
|
}
|
|
410
|
-
/**
|
|
411
|
-
* Insert multiple records into a table. This function overwrites the existing records if they exist. Use this function for inserting records into tables with custom schemas.
|
|
412
|
-
* @param tableName The name of the table to insert into.
|
|
413
|
-
* @param records The records to insert.
|
|
414
|
-
*/
|
|
415
1243
|
async batchInsert({ tableName, records }) {
|
|
416
1244
|
try {
|
|
417
|
-
if (!this.
|
|
1245
|
+
if (!this.client) {
|
|
418
1246
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
419
1247
|
}
|
|
420
1248
|
if (!tableName) {
|
|
@@ -436,8 +1264,8 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
436
1264
|
);
|
|
437
1265
|
}
|
|
438
1266
|
try {
|
|
439
|
-
const table = await this.
|
|
440
|
-
const primaryId =
|
|
1267
|
+
const table = await this.client.openTable(tableName);
|
|
1268
|
+
const primaryId = getPrimaryKeys(tableName);
|
|
441
1269
|
const processedRecords = records.map((record) => {
|
|
442
1270
|
const processedRecord = { ...record };
|
|
443
1271
|
for (const key in processedRecord) {
|
|
@@ -448,6 +1276,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
448
1276
|
}
|
|
449
1277
|
return processedRecord;
|
|
450
1278
|
});
|
|
1279
|
+
console.log(processedRecords);
|
|
451
1280
|
await table.mergeInsert(primaryId).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(processedRecords);
|
|
452
1281
|
} catch (error$1) {
|
|
453
1282
|
throw new error.MastraError(
|
|
@@ -461,16 +1290,9 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
461
1290
|
);
|
|
462
1291
|
}
|
|
463
1292
|
}
|
|
464
|
-
/**
|
|
465
|
-
* Load a record from the database by its key(s)
|
|
466
|
-
* @param tableName The name of the table to query
|
|
467
|
-
* @param keys Record of key-value pairs to use for lookup
|
|
468
|
-
* @throws Error if invalid types are provided for keys
|
|
469
|
-
* @returns The loaded record with proper type conversions, or null if not found
|
|
470
|
-
*/
|
|
471
1293
|
async load({ tableName, keys }) {
|
|
472
1294
|
try {
|
|
473
|
-
if (!this.
|
|
1295
|
+
if (!this.client) {
|
|
474
1296
|
throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
|
|
475
1297
|
}
|
|
476
1298
|
if (!tableName) {
|
|
@@ -492,11 +1314,11 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
492
1314
|
);
|
|
493
1315
|
}
|
|
494
1316
|
try {
|
|
495
|
-
const table = await this.
|
|
496
|
-
const tableSchema = await
|
|
1317
|
+
const table = await this.client.openTable(tableName);
|
|
1318
|
+
const tableSchema = await getTableSchema({ tableName, client: this.client });
|
|
497
1319
|
const query = table.query();
|
|
498
1320
|
if (Object.keys(keys).length > 0) {
|
|
499
|
-
|
|
1321
|
+
validateKeyTypes(keys, tableSchema);
|
|
500
1322
|
const filterConditions = Object.entries(keys).map(([key, value]) => {
|
|
501
1323
|
const isCamelCase = /^[a-z][a-zA-Z]*$/.test(key) && /[A-Z]/.test(key);
|
|
502
1324
|
const quotedKey = isCamelCase ? `\`${key}\`` : key;
|
|
@@ -510,330 +1332,228 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
510
1332
|
}).join(" AND ");
|
|
511
1333
|
this.logger.debug("where clause generated: " + filterConditions);
|
|
512
1334
|
query.where(filterConditions);
|
|
513
|
-
}
|
|
514
|
-
const result = await query.limit(1).toArray();
|
|
515
|
-
if (result.length === 0) {
|
|
516
|
-
this.logger.debug("No record found");
|
|
517
|
-
return null;
|
|
518
|
-
}
|
|
519
|
-
return
|
|
520
|
-
} catch (error$1) {
|
|
521
|
-
if (error$1 instanceof error.MastraError) throw error$1;
|
|
522
|
-
throw new error.MastraError(
|
|
523
|
-
{
|
|
524
|
-
id: "STORAGE_LANCE_STORAGE_LOAD_FAILED",
|
|
525
|
-
domain: error.ErrorDomain.STORAGE,
|
|
526
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
527
|
-
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
528
|
-
},
|
|
529
|
-
error$1
|
|
530
|
-
);
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Validates that key types match the schema definition
|
|
535
|
-
* @param keys The keys to validate
|
|
536
|
-
* @param tableSchema The table schema to validate against
|
|
537
|
-
* @throws Error if a key has an incompatible type
|
|
538
|
-
*/
|
|
539
|
-
validateKeyTypes(keys, tableSchema) {
|
|
540
|
-
const fieldTypes = new Map(
|
|
541
|
-
tableSchema.fields.map((field) => [field.name, field.type?.toString().toLowerCase()])
|
|
542
|
-
);
|
|
543
|
-
for (const [key, value] of Object.entries(keys)) {
|
|
544
|
-
const fieldType = fieldTypes.get(key);
|
|
545
|
-
if (!fieldType) {
|
|
546
|
-
throw new Error(`Field '${key}' does not exist in table schema`);
|
|
547
|
-
}
|
|
548
|
-
if (value !== null) {
|
|
549
|
-
if ((fieldType.includes("int") || fieldType.includes("bigint")) && typeof value !== "number") {
|
|
550
|
-
throw new Error(`Expected numeric value for field '${key}', got ${typeof value}`);
|
|
551
|
-
}
|
|
552
|
-
if (fieldType.includes("utf8") && typeof value !== "string") {
|
|
553
|
-
throw new Error(`Expected string value for field '${key}', got ${typeof value}`);
|
|
554
|
-
}
|
|
555
|
-
if (fieldType.includes("timestamp") && !(value instanceof Date) && typeof value !== "string") {
|
|
556
|
-
throw new Error(`Expected Date or string value for field '${key}', got ${typeof value}`);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Process a database result with appropriate type conversions based on the table schema
|
|
563
|
-
* @param rawResult The raw result object from the database
|
|
564
|
-
* @param tableSchema The schema of the table containing type information
|
|
565
|
-
* @returns Processed result with correct data types
|
|
566
|
-
*/
|
|
567
|
-
processResultWithTypeConversion(rawResult, tableSchema) {
|
|
568
|
-
const fieldTypeMap = /* @__PURE__ */ new Map();
|
|
569
|
-
tableSchema.fields.forEach((field) => {
|
|
570
|
-
const fieldName = field.name;
|
|
571
|
-
const fieldTypeStr = field.type.toString().toLowerCase();
|
|
572
|
-
fieldTypeMap.set(fieldName, fieldTypeStr);
|
|
573
|
-
});
|
|
574
|
-
if (Array.isArray(rawResult)) {
|
|
575
|
-
return rawResult.map((item) => this.processResultWithTypeConversion(item, tableSchema));
|
|
576
|
-
}
|
|
577
|
-
const processedResult = { ...rawResult };
|
|
578
|
-
for (const key in processedResult) {
|
|
579
|
-
const fieldTypeStr = fieldTypeMap.get(key);
|
|
580
|
-
if (!fieldTypeStr) continue;
|
|
581
|
-
if (typeof processedResult[key] === "string") {
|
|
582
|
-
if (fieldTypeStr.includes("int32") || fieldTypeStr.includes("float32")) {
|
|
583
|
-
if (!isNaN(Number(processedResult[key]))) {
|
|
584
|
-
processedResult[key] = Number(processedResult[key]);
|
|
585
|
-
}
|
|
586
|
-
} else if (fieldTypeStr.includes("int64")) {
|
|
587
|
-
processedResult[key] = Number(processedResult[key]);
|
|
588
|
-
} else if (fieldTypeStr.includes("utf8")) {
|
|
589
|
-
try {
|
|
590
|
-
processedResult[key] = JSON.parse(processedResult[key]);
|
|
591
|
-
} catch (e) {
|
|
592
|
-
this.logger.debug(`Failed to parse JSON for key ${key}: ${e}`);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
} else if (typeof processedResult[key] === "bigint") {
|
|
596
|
-
processedResult[key] = Number(processedResult[key]);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
return processedResult;
|
|
600
|
-
}
|
|
601
|
-
getThreadById({ threadId }) {
|
|
602
|
-
try {
|
|
603
|
-
return this.load({ tableName: storage.TABLE_THREADS, keys: { id: threadId } });
|
|
604
|
-
} catch (error$1) {
|
|
605
|
-
throw new error.MastraError(
|
|
606
|
-
{
|
|
607
|
-
id: "LANCE_STORE_GET_THREAD_BY_ID_FAILED",
|
|
608
|
-
domain: error.ErrorDomain.STORAGE,
|
|
609
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
610
|
-
},
|
|
611
|
-
error$1
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
async getThreadsByResourceId({ resourceId }) {
|
|
616
|
-
try {
|
|
617
|
-
const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
|
|
618
|
-
const query = table.query().where(`\`resourceId\` = '${resourceId}'`);
|
|
619
|
-
const records = await query.toArray();
|
|
620
|
-
return this.processResultWithTypeConversion(
|
|
621
|
-
records,
|
|
622
|
-
await this.getTableSchema(storage.TABLE_THREADS)
|
|
623
|
-
);
|
|
1335
|
+
}
|
|
1336
|
+
const result = await query.limit(1).toArray();
|
|
1337
|
+
if (result.length === 0) {
|
|
1338
|
+
this.logger.debug("No record found");
|
|
1339
|
+
return null;
|
|
1340
|
+
}
|
|
1341
|
+
return processResultWithTypeConversion(result[0], tableSchema);
|
|
624
1342
|
} catch (error$1) {
|
|
1343
|
+
if (error$1 instanceof error.MastraError) throw error$1;
|
|
625
1344
|
throw new error.MastraError(
|
|
626
1345
|
{
|
|
627
|
-
id: "
|
|
1346
|
+
id: "STORAGE_LANCE_STORAGE_LOAD_FAILED",
|
|
628
1347
|
domain: error.ErrorDomain.STORAGE,
|
|
629
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1348
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1349
|
+
details: { tableName, keyCount: Object.keys(keys).length, firstKey: Object.keys(keys)[0] ?? "" }
|
|
630
1350
|
},
|
|
631
1351
|
error$1
|
|
632
1352
|
);
|
|
633
1353
|
}
|
|
634
1354
|
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
1355
|
+
};
|
|
1356
|
+
var StoreScoresLance = class extends storage.ScoresStorage {
|
|
1357
|
+
client;
|
|
1358
|
+
constructor({ client }) {
|
|
1359
|
+
super();
|
|
1360
|
+
this.client = client;
|
|
1361
|
+
}
|
|
1362
|
+
async saveScore(score) {
|
|
641
1363
|
try {
|
|
642
|
-
const
|
|
643
|
-
const table = await this.
|
|
644
|
-
await
|
|
645
|
-
|
|
1364
|
+
const id = crypto.randomUUID();
|
|
1365
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1366
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1367
|
+
const allowedFields = new Set(schema.fields.map((f) => f.name));
|
|
1368
|
+
const filteredScore = {};
|
|
1369
|
+
Object.keys(score).forEach((key) => {
|
|
1370
|
+
if (allowedFields.has(key)) {
|
|
1371
|
+
filteredScore[key] = score[key];
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
for (const key in filteredScore) {
|
|
1375
|
+
if (filteredScore[key] !== null && typeof filteredScore[key] === "object" && !(filteredScore[key] instanceof Date)) {
|
|
1376
|
+
filteredScore[key] = JSON.stringify(filteredScore[key]);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
filteredScore.id = id;
|
|
1380
|
+
await table.add([filteredScore], { mode: "append" });
|
|
1381
|
+
return { score };
|
|
646
1382
|
} catch (error$1) {
|
|
647
1383
|
throw new error.MastraError(
|
|
648
1384
|
{
|
|
649
|
-
id: "
|
|
1385
|
+
id: "LANCE_STORAGE_SAVE_SCORE_FAILED",
|
|
1386
|
+
text: "Failed to save score in LanceStorage",
|
|
650
1387
|
domain: error.ErrorDomain.STORAGE,
|
|
651
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1388
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1389
|
+
details: { error: error$1?.message }
|
|
652
1390
|
},
|
|
653
1391
|
error$1
|
|
654
1392
|
);
|
|
655
1393
|
}
|
|
656
1394
|
}
|
|
657
|
-
async
|
|
658
|
-
id,
|
|
659
|
-
title,
|
|
660
|
-
metadata
|
|
661
|
-
}) {
|
|
1395
|
+
async getScoreById({ id }) {
|
|
662
1396
|
try {
|
|
663
|
-
const
|
|
664
|
-
const
|
|
665
|
-
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
666
|
-
const query = table.query().where(`id = '${id}'`);
|
|
1397
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1398
|
+
const query = table.query().where(`id = '${id}'`).limit(1);
|
|
667
1399
|
const records = await query.toArray();
|
|
668
|
-
return
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
);
|
|
1400
|
+
if (records.length === 0) return null;
|
|
1401
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1402
|
+
return processResultWithTypeConversion(records[0], schema);
|
|
672
1403
|
} catch (error$1) {
|
|
673
1404
|
throw new error.MastraError(
|
|
674
1405
|
{
|
|
675
|
-
id: "
|
|
1406
|
+
id: "LANCE_STORAGE_GET_SCORE_BY_ID_FAILED",
|
|
1407
|
+
text: "Failed to get score by id in LanceStorage",
|
|
676
1408
|
domain: error.ErrorDomain.STORAGE,
|
|
677
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1409
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1410
|
+
details: { error: error$1?.message }
|
|
678
1411
|
},
|
|
679
1412
|
error$1
|
|
680
1413
|
);
|
|
681
1414
|
}
|
|
682
1415
|
}
|
|
683
|
-
async
|
|
1416
|
+
async getScoresByScorerId({
|
|
1417
|
+
scorerId,
|
|
1418
|
+
pagination,
|
|
1419
|
+
entityId,
|
|
1420
|
+
entityType,
|
|
1421
|
+
source
|
|
1422
|
+
}) {
|
|
684
1423
|
try {
|
|
685
|
-
const table = await this.
|
|
686
|
-
|
|
1424
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1425
|
+
const { page = 0, perPage = 10 } = pagination || {};
|
|
1426
|
+
const offset = page * perPage;
|
|
1427
|
+
let query = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1428
|
+
if (source) {
|
|
1429
|
+
query = query.where(`\`source\` = '${source}'`);
|
|
1430
|
+
}
|
|
1431
|
+
if (entityId) {
|
|
1432
|
+
query = query.where(`\`entityId\` = '${entityId}'`);
|
|
1433
|
+
}
|
|
1434
|
+
if (entityType) {
|
|
1435
|
+
query = query.where(`\`entityType\` = '${entityType}'`);
|
|
1436
|
+
}
|
|
1437
|
+
query = query.limit(perPage);
|
|
1438
|
+
if (offset > 0) query.offset(offset);
|
|
1439
|
+
const records = await query.toArray();
|
|
1440
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1441
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1442
|
+
let totalQuery = table.query().where(`\`scorerId\` = '${scorerId}'`);
|
|
1443
|
+
if (source) {
|
|
1444
|
+
totalQuery = totalQuery.where(`\`source\` = '${source}'`);
|
|
1445
|
+
}
|
|
1446
|
+
const allRecords = await totalQuery.toArray();
|
|
1447
|
+
const total = allRecords.length;
|
|
1448
|
+
return {
|
|
1449
|
+
pagination: {
|
|
1450
|
+
page,
|
|
1451
|
+
perPage,
|
|
1452
|
+
total,
|
|
1453
|
+
hasMore: offset + scores.length < total
|
|
1454
|
+
},
|
|
1455
|
+
scores
|
|
1456
|
+
};
|
|
687
1457
|
} catch (error$1) {
|
|
688
1458
|
throw new error.MastraError(
|
|
689
1459
|
{
|
|
690
|
-
id: "
|
|
1460
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_SCORER_ID_FAILED",
|
|
1461
|
+
text: "Failed to get scores by scorerId in LanceStorage",
|
|
691
1462
|
domain: error.ErrorDomain.STORAGE,
|
|
692
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1463
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1464
|
+
details: { error: error$1?.message }
|
|
693
1465
|
},
|
|
694
1466
|
error$1
|
|
695
1467
|
);
|
|
696
1468
|
}
|
|
697
1469
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
* @param include - The array of include specifications with context parameters
|
|
702
|
-
* @returns The processed array with context messages included
|
|
703
|
-
*/
|
|
704
|
-
processMessagesWithContext(records, include) {
|
|
705
|
-
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
706
|
-
if (messagesWithContext.length === 0) {
|
|
707
|
-
return records;
|
|
708
|
-
}
|
|
709
|
-
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
710
|
-
records.forEach((message, index) => {
|
|
711
|
-
messageIndexMap.set(message.id, index);
|
|
712
|
-
});
|
|
713
|
-
const additionalIndices = /* @__PURE__ */ new Set();
|
|
714
|
-
for (const item of messagesWithContext) {
|
|
715
|
-
const messageIndex = messageIndexMap.get(item.id);
|
|
716
|
-
if (messageIndex !== void 0) {
|
|
717
|
-
if (item.withPreviousMessages) {
|
|
718
|
-
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
719
|
-
for (let i = startIdx; i < messageIndex; i++) {
|
|
720
|
-
additionalIndices.add(i);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
if (item.withNextMessages) {
|
|
724
|
-
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
725
|
-
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
726
|
-
additionalIndices.add(i);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
if (additionalIndices.size === 0) {
|
|
732
|
-
return records;
|
|
733
|
-
}
|
|
734
|
-
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
735
|
-
const allIndices = /* @__PURE__ */ new Set();
|
|
736
|
-
records.forEach((record, index) => {
|
|
737
|
-
if (originalMatchIds.has(record.id)) {
|
|
738
|
-
allIndices.add(index);
|
|
739
|
-
}
|
|
740
|
-
});
|
|
741
|
-
additionalIndices.forEach((index) => {
|
|
742
|
-
allIndices.add(index);
|
|
743
|
-
});
|
|
744
|
-
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
745
|
-
}
|
|
746
|
-
async getMessages({
|
|
747
|
-
threadId,
|
|
748
|
-
resourceId,
|
|
749
|
-
selectBy,
|
|
750
|
-
format,
|
|
751
|
-
threadConfig
|
|
1470
|
+
async getScoresByRunId({
|
|
1471
|
+
runId,
|
|
1472
|
+
pagination
|
|
752
1473
|
}) {
|
|
753
1474
|
try {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
}
|
|
773
|
-
if (selectBy?.include && selectBy.include.length > 0) {
|
|
774
|
-
records = this.processMessagesWithContext(records, selectBy.include);
|
|
775
|
-
}
|
|
776
|
-
if (limit !== Number.MAX_SAFE_INTEGER) {
|
|
777
|
-
records = records.slice(-limit);
|
|
778
|
-
}
|
|
779
|
-
const messages = this.processResultWithTypeConversion(records, await this.getTableSchema(storage.TABLE_MESSAGES));
|
|
780
|
-
const normalized = messages.map((msg) => ({
|
|
781
|
-
...msg,
|
|
782
|
-
content: typeof msg.content === "string" ? (() => {
|
|
783
|
-
try {
|
|
784
|
-
return JSON.parse(msg.content);
|
|
785
|
-
} catch {
|
|
786
|
-
return msg.content;
|
|
787
|
-
}
|
|
788
|
-
})() : msg.content
|
|
789
|
-
}));
|
|
790
|
-
const list = new agent.MessageList({ threadId, resourceId }).add(normalized, "memory");
|
|
791
|
-
if (format === "v2") return list.get.all.v2();
|
|
792
|
-
return list.get.all.v1();
|
|
1475
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1476
|
+
const { page = 0, perPage = 10 } = pagination || {};
|
|
1477
|
+
const offset = page * perPage;
|
|
1478
|
+
const query = table.query().where(`\`runId\` = '${runId}'`).limit(perPage);
|
|
1479
|
+
if (offset > 0) query.offset(offset);
|
|
1480
|
+
const records = await query.toArray();
|
|
1481
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1482
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1483
|
+
const allRecords = await table.query().where(`\`runId\` = '${runId}'`).toArray();
|
|
1484
|
+
const total = allRecords.length;
|
|
1485
|
+
return {
|
|
1486
|
+
pagination: {
|
|
1487
|
+
page,
|
|
1488
|
+
perPage,
|
|
1489
|
+
total,
|
|
1490
|
+
hasMore: offset + scores.length < total
|
|
1491
|
+
},
|
|
1492
|
+
scores
|
|
1493
|
+
};
|
|
793
1494
|
} catch (error$1) {
|
|
794
1495
|
throw new error.MastraError(
|
|
795
1496
|
{
|
|
796
|
-
id: "
|
|
1497
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_RUN_ID_FAILED",
|
|
1498
|
+
text: "Failed to get scores by runId in LanceStorage",
|
|
797
1499
|
domain: error.ErrorDomain.STORAGE,
|
|
798
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1500
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1501
|
+
details: { error: error$1?.message }
|
|
799
1502
|
},
|
|
800
1503
|
error$1
|
|
801
1504
|
);
|
|
802
1505
|
}
|
|
803
1506
|
}
|
|
804
|
-
async
|
|
1507
|
+
async getScoresByEntityId({
|
|
1508
|
+
entityId,
|
|
1509
|
+
entityType,
|
|
1510
|
+
pagination
|
|
1511
|
+
}) {
|
|
805
1512
|
try {
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
1513
|
+
const table = await this.client.openTable(storage.TABLE_SCORERS);
|
|
1514
|
+
const { page = 0, perPage = 10 } = pagination || {};
|
|
1515
|
+
const offset = page * perPage;
|
|
1516
|
+
const query = table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).limit(perPage);
|
|
1517
|
+
if (offset > 0) query.offset(offset);
|
|
1518
|
+
const records = await query.toArray();
|
|
1519
|
+
const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
|
|
1520
|
+
const scores = processResultWithTypeConversion(records, schema);
|
|
1521
|
+
const allRecords = await table.query().where(`\`entityId\` = '${entityId}' AND \`entityType\` = '${entityType}'`).toArray();
|
|
1522
|
+
const total = allRecords.length;
|
|
1523
|
+
return {
|
|
1524
|
+
pagination: {
|
|
1525
|
+
page,
|
|
1526
|
+
perPage,
|
|
1527
|
+
total,
|
|
1528
|
+
hasMore: offset + scores.length < total
|
|
1529
|
+
},
|
|
1530
|
+
scores
|
|
1531
|
+
};
|
|
823
1532
|
} catch (error$1) {
|
|
824
1533
|
throw new error.MastraError(
|
|
825
1534
|
{
|
|
826
|
-
id: "
|
|
1535
|
+
id: "LANCE_STORAGE_GET_SCORES_BY_ENTITY_ID_FAILED",
|
|
1536
|
+
text: "Failed to get scores by entityId and entityType in LanceStorage",
|
|
827
1537
|
domain: error.ErrorDomain.STORAGE,
|
|
828
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1538
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1539
|
+
details: { error: error$1?.message }
|
|
829
1540
|
},
|
|
830
1541
|
error$1
|
|
831
1542
|
);
|
|
832
1543
|
}
|
|
833
1544
|
}
|
|
1545
|
+
};
|
|
1546
|
+
var StoreTracesLance = class extends storage.TracesStorage {
|
|
1547
|
+
client;
|
|
1548
|
+
operations;
|
|
1549
|
+
constructor({ client, operations }) {
|
|
1550
|
+
super();
|
|
1551
|
+
this.client = client;
|
|
1552
|
+
this.operations = operations;
|
|
1553
|
+
}
|
|
834
1554
|
async saveTrace({ trace }) {
|
|
835
1555
|
try {
|
|
836
|
-
const table = await this.
|
|
1556
|
+
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
837
1557
|
const record = {
|
|
838
1558
|
...trace,
|
|
839
1559
|
attributes: JSON.stringify(trace.attributes),
|
|
@@ -857,10 +1577,10 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
857
1577
|
}
|
|
858
1578
|
async getTraceById({ traceId }) {
|
|
859
1579
|
try {
|
|
860
|
-
const table = await this.
|
|
1580
|
+
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
861
1581
|
const query = table.query().where(`id = '${traceId}'`);
|
|
862
1582
|
const records = await query.toArray();
|
|
863
|
-
return
|
|
1583
|
+
return records[0];
|
|
864
1584
|
} catch (error$1) {
|
|
865
1585
|
throw new error.MastraError(
|
|
866
1586
|
{
|
|
@@ -880,7 +1600,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
880
1600
|
attributes
|
|
881
1601
|
}) {
|
|
882
1602
|
try {
|
|
883
|
-
const table = await this.
|
|
1603
|
+
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
884
1604
|
const query = table.query();
|
|
885
1605
|
if (name) {
|
|
886
1606
|
query.where(`name = '${name}'`);
|
|
@@ -898,17 +1618,23 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
898
1618
|
}
|
|
899
1619
|
const records = await query.toArray();
|
|
900
1620
|
return records.map((record) => {
|
|
901
|
-
|
|
1621
|
+
const processed = {
|
|
902
1622
|
...record,
|
|
903
|
-
attributes: JSON.parse(record.attributes),
|
|
904
|
-
status: JSON.parse(record.status),
|
|
905
|
-
events: JSON.parse(record.events),
|
|
906
|
-
links: JSON.parse(record.links),
|
|
907
|
-
other: JSON.parse(record.other),
|
|
1623
|
+
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1624
|
+
status: record.status ? JSON.parse(record.status) : {},
|
|
1625
|
+
events: record.events ? JSON.parse(record.events) : [],
|
|
1626
|
+
links: record.links ? JSON.parse(record.links) : [],
|
|
1627
|
+
other: record.other ? JSON.parse(record.other) : {},
|
|
908
1628
|
startTime: new Date(record.startTime),
|
|
909
1629
|
endTime: new Date(record.endTime),
|
|
910
1630
|
createdAt: new Date(record.createdAt)
|
|
911
1631
|
};
|
|
1632
|
+
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1633
|
+
processed.parentSpanId = "";
|
|
1634
|
+
} else {
|
|
1635
|
+
processed.parentSpanId = String(processed.parentSpanId);
|
|
1636
|
+
}
|
|
1637
|
+
return processed;
|
|
912
1638
|
});
|
|
913
1639
|
} catch (error$1) {
|
|
914
1640
|
throw new error.MastraError(
|
|
@@ -922,131 +1648,177 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
922
1648
|
);
|
|
923
1649
|
}
|
|
924
1650
|
}
|
|
925
|
-
async
|
|
1651
|
+
async getTracesPaginated(args) {
|
|
926
1652
|
try {
|
|
927
|
-
const table = await this.
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
|
|
1653
|
+
const table = await this.client.openTable(storage.TABLE_TRACES);
|
|
1654
|
+
const query = table.query();
|
|
1655
|
+
const conditions = [];
|
|
1656
|
+
if (args.name) {
|
|
1657
|
+
conditions.push(`name = '${args.name}'`);
|
|
1658
|
+
}
|
|
1659
|
+
if (args.scope) {
|
|
1660
|
+
conditions.push(`scope = '${args.scope}'`);
|
|
1661
|
+
}
|
|
1662
|
+
if (args.attributes) {
|
|
1663
|
+
const attributesStr = JSON.stringify(args.attributes);
|
|
1664
|
+
conditions.push(`attributes LIKE '%${attributesStr.replace(/"/g, '\\"')}%'`);
|
|
1665
|
+
}
|
|
1666
|
+
if (args.dateRange?.start) {
|
|
1667
|
+
conditions.push(`\`createdAt\` >= ${args.dateRange.start.getTime()}`);
|
|
1668
|
+
}
|
|
1669
|
+
if (args.dateRange?.end) {
|
|
1670
|
+
conditions.push(`\`createdAt\` <= ${args.dateRange.end.getTime()}`);
|
|
1671
|
+
}
|
|
1672
|
+
if (conditions.length > 0) {
|
|
1673
|
+
const whereClause = conditions.join(" AND ");
|
|
1674
|
+
query.where(whereClause);
|
|
1675
|
+
}
|
|
1676
|
+
let total = 0;
|
|
1677
|
+
if (conditions.length > 0) {
|
|
1678
|
+
const countQuery = table.query().where(conditions.join(" AND "));
|
|
1679
|
+
const allRecords = await countQuery.toArray();
|
|
1680
|
+
total = allRecords.length;
|
|
1681
|
+
} else {
|
|
1682
|
+
total = await table.countRows();
|
|
1683
|
+
}
|
|
1684
|
+
const page = args.page || 0;
|
|
1685
|
+
const perPage = args.perPage || 10;
|
|
1686
|
+
const offset = page * perPage;
|
|
1687
|
+
query.limit(perPage);
|
|
1688
|
+
if (offset > 0) {
|
|
1689
|
+
query.offset(offset);
|
|
1690
|
+
}
|
|
1691
|
+
const records = await query.toArray();
|
|
1692
|
+
const traces = records.map((record) => {
|
|
1693
|
+
const processed = {
|
|
1694
|
+
...record,
|
|
1695
|
+
attributes: record.attributes ? JSON.parse(record.attributes) : {},
|
|
1696
|
+
status: record.status ? JSON.parse(record.status) : {},
|
|
1697
|
+
events: record.events ? JSON.parse(record.events) : [],
|
|
1698
|
+
links: record.links ? JSON.parse(record.links) : [],
|
|
1699
|
+
other: record.other ? JSON.parse(record.other) : {},
|
|
1700
|
+
startTime: new Date(record.startTime),
|
|
1701
|
+
endTime: new Date(record.endTime),
|
|
1702
|
+
createdAt: new Date(record.createdAt)
|
|
1703
|
+
};
|
|
1704
|
+
if (processed.parentSpanId === null || processed.parentSpanId === void 0) {
|
|
1705
|
+
processed.parentSpanId = "";
|
|
1706
|
+
} else {
|
|
1707
|
+
processed.parentSpanId = String(processed.parentSpanId);
|
|
1708
|
+
}
|
|
1709
|
+
return processed;
|
|
1710
|
+
});
|
|
1711
|
+
return {
|
|
1712
|
+
traces,
|
|
1713
|
+
total,
|
|
1714
|
+
page,
|
|
1715
|
+
perPage,
|
|
1716
|
+
hasMore: total > (page + 1) * perPage
|
|
1717
|
+
};
|
|
942
1718
|
} catch (error$1) {
|
|
943
1719
|
throw new error.MastraError(
|
|
944
1720
|
{
|
|
945
|
-
id: "
|
|
1721
|
+
id: "LANCE_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
946
1722
|
domain: error.ErrorDomain.STORAGE,
|
|
947
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1723
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1724
|
+
details: { name: args.name ?? "", scope: args.scope ?? "" }
|
|
948
1725
|
},
|
|
949
1726
|
error$1
|
|
950
1727
|
);
|
|
951
1728
|
}
|
|
952
1729
|
}
|
|
953
|
-
async
|
|
1730
|
+
async batchTraceInsert({ records }) {
|
|
1731
|
+
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
1732
|
+
await this.operations.batchInsert({
|
|
1733
|
+
tableName: storage.TABLE_TRACES,
|
|
1734
|
+
records
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
};
|
|
1738
|
+
function parseWorkflowRun(row) {
|
|
1739
|
+
let parsedSnapshot = row.snapshot;
|
|
1740
|
+
if (typeof parsedSnapshot === "string") {
|
|
954
1741
|
try {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
|
|
1742
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1743
|
+
} catch (e) {
|
|
1744
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
return {
|
|
1748
|
+
workflowName: row.workflow_name,
|
|
1749
|
+
runId: row.run_id,
|
|
1750
|
+
snapshot: parsedSnapshot,
|
|
1751
|
+
createdAt: storage.ensureDate(row.createdAt),
|
|
1752
|
+
updatedAt: storage.ensureDate(row.updatedAt),
|
|
1753
|
+
resourceId: row.resourceId
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
1757
|
+
client;
|
|
1758
|
+
constructor({ client }) {
|
|
1759
|
+
super();
|
|
1760
|
+
this.client = client;
|
|
1761
|
+
}
|
|
1762
|
+
async persistWorkflowSnapshot({
|
|
1763
|
+
workflowName,
|
|
1764
|
+
runId,
|
|
1765
|
+
snapshot
|
|
1766
|
+
}) {
|
|
1767
|
+
try {
|
|
1768
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1769
|
+
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
960
1770
|
const records = await query.toArray();
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1771
|
+
let createdAt;
|
|
1772
|
+
const now = Date.now();
|
|
1773
|
+
if (records.length > 0) {
|
|
1774
|
+
createdAt = records[0].createdAt ?? now;
|
|
1775
|
+
} else {
|
|
1776
|
+
createdAt = now;
|
|
1777
|
+
}
|
|
1778
|
+
const record = {
|
|
1779
|
+
workflow_name: workflowName,
|
|
1780
|
+
run_id: runId,
|
|
1781
|
+
snapshot: JSON.stringify(snapshot),
|
|
1782
|
+
createdAt,
|
|
1783
|
+
updatedAt: now
|
|
1784
|
+
};
|
|
1785
|
+
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
976
1786
|
} catch (error$1) {
|
|
977
1787
|
throw new error.MastraError(
|
|
978
1788
|
{
|
|
979
|
-
id: "
|
|
1789
|
+
id: "LANCE_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
|
|
980
1790
|
domain: error.ErrorDomain.STORAGE,
|
|
981
1791
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
982
|
-
details: {
|
|
1792
|
+
details: { workflowName, runId }
|
|
983
1793
|
},
|
|
984
1794
|
error$1
|
|
985
1795
|
);
|
|
986
1796
|
}
|
|
987
1797
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
return {
|
|
998
|
-
workflowName: row.workflow_name,
|
|
999
|
-
runId: row.run_id,
|
|
1000
|
-
snapshot: parsedSnapshot,
|
|
1001
|
-
createdAt: this.ensureDate(row.createdAt),
|
|
1002
|
-
updatedAt: this.ensureDate(row.updatedAt),
|
|
1003
|
-
resourceId: row.resourceId
|
|
1004
|
-
};
|
|
1005
|
-
}
|
|
1006
|
-
async getWorkflowRuns(args) {
|
|
1007
|
-
try {
|
|
1008
|
-
const table = await this.lanceClient.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1009
|
-
const query = table.query();
|
|
1010
|
-
if (args?.workflowName) {
|
|
1011
|
-
query.where(`workflow_name = '${args.workflowName}'`);
|
|
1012
|
-
}
|
|
1013
|
-
if (args?.fromDate) {
|
|
1014
|
-
query.where(`\`createdAt\` >= ${args.fromDate.getTime()}`);
|
|
1015
|
-
}
|
|
1016
|
-
if (args?.toDate) {
|
|
1017
|
-
query.where(`\`createdAt\` <= ${args.toDate.getTime()}`);
|
|
1018
|
-
}
|
|
1019
|
-
if (args?.limit) {
|
|
1020
|
-
query.limit(args.limit);
|
|
1021
|
-
}
|
|
1022
|
-
if (args?.offset) {
|
|
1023
|
-
query.offset(args.offset);
|
|
1024
|
-
}
|
|
1798
|
+
async loadWorkflowSnapshot({
|
|
1799
|
+
workflowName,
|
|
1800
|
+
runId
|
|
1801
|
+
}) {
|
|
1802
|
+
try {
|
|
1803
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1804
|
+
const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
|
|
1025
1805
|
const records = await query.toArray();
|
|
1026
|
-
return
|
|
1027
|
-
runs: records.map((record) => this.parseWorkflowRun(record)),
|
|
1028
|
-
total: records.length
|
|
1029
|
-
};
|
|
1806
|
+
return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
|
|
1030
1807
|
} catch (error$1) {
|
|
1031
1808
|
throw new error.MastraError(
|
|
1032
1809
|
{
|
|
1033
|
-
id: "
|
|
1810
|
+
id: "LANCE_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
|
|
1034
1811
|
domain: error.ErrorDomain.STORAGE,
|
|
1035
1812
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1036
|
-
details: {
|
|
1813
|
+
details: { workflowName, runId }
|
|
1037
1814
|
},
|
|
1038
1815
|
error$1
|
|
1039
1816
|
);
|
|
1040
1817
|
}
|
|
1041
1818
|
}
|
|
1042
|
-
/**
|
|
1043
|
-
* Retrieve a single workflow run by its runId.
|
|
1044
|
-
* @param args The ID of the workflow run to retrieve
|
|
1045
|
-
* @returns The workflow run object or null if not found
|
|
1046
|
-
*/
|
|
1047
1819
|
async getWorkflowRunById(args) {
|
|
1048
1820
|
try {
|
|
1049
|
-
const table = await this.
|
|
1821
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1050
1822
|
let whereClause = `run_id = '${args.runId}'`;
|
|
1051
1823
|
if (args.workflowName) {
|
|
1052
1824
|
whereClause += ` AND workflow_name = '${args.workflowName}'`;
|
|
@@ -1055,7 +1827,7 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1055
1827
|
const records = await query.toArray();
|
|
1056
1828
|
if (records.length === 0) return null;
|
|
1057
1829
|
const record = records[0];
|
|
1058
|
-
return
|
|
1830
|
+
return parseWorkflowRun(record);
|
|
1059
1831
|
} catch (error$1) {
|
|
1060
1832
|
throw new error.MastraError(
|
|
1061
1833
|
{
|
|
@@ -1068,96 +1840,328 @@ var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
|
1068
1840
|
);
|
|
1069
1841
|
}
|
|
1070
1842
|
}
|
|
1071
|
-
async
|
|
1072
|
-
workflowName,
|
|
1073
|
-
runId,
|
|
1074
|
-
snapshot
|
|
1075
|
-
}) {
|
|
1843
|
+
async getWorkflowRuns(args) {
|
|
1076
1844
|
try {
|
|
1077
|
-
const table = await this.
|
|
1078
|
-
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1845
|
+
const table = await this.client.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1846
|
+
let query = table.query();
|
|
1847
|
+
const conditions = [];
|
|
1848
|
+
if (args?.workflowName) {
|
|
1849
|
+
conditions.push(`workflow_name = '${args.workflowName.replace(/'/g, "''")}'`);
|
|
1850
|
+
}
|
|
1851
|
+
if (args?.resourceId) {
|
|
1852
|
+
conditions.push(`\`resourceId\` = '${args.resourceId}'`);
|
|
1853
|
+
}
|
|
1854
|
+
if (args?.fromDate instanceof Date) {
|
|
1855
|
+
conditions.push(`\`createdAt\` >= ${args.fromDate.getTime()}`);
|
|
1856
|
+
}
|
|
1857
|
+
if (args?.toDate instanceof Date) {
|
|
1858
|
+
conditions.push(`\`createdAt\` <= ${args.toDate.getTime()}`);
|
|
1859
|
+
}
|
|
1860
|
+
let total = 0;
|
|
1861
|
+
if (conditions.length > 0) {
|
|
1862
|
+
query = query.where(conditions.join(" AND "));
|
|
1863
|
+
total = await table.countRows(conditions.join(" AND "));
|
|
1084
1864
|
} else {
|
|
1085
|
-
|
|
1865
|
+
total = await table.countRows();
|
|
1086
1866
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1867
|
+
if (args?.limit) {
|
|
1868
|
+
query.limit(args.limit);
|
|
1869
|
+
}
|
|
1870
|
+
if (args?.offset) {
|
|
1871
|
+
query.offset(args.offset);
|
|
1872
|
+
}
|
|
1873
|
+
const records = await query.toArray();
|
|
1874
|
+
return {
|
|
1875
|
+
runs: records.map((record) => parseWorkflowRun(record)),
|
|
1876
|
+
total: total || records.length
|
|
1093
1877
|
};
|
|
1094
|
-
await table.mergeInsert(["workflow_name", "run_id"]).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute([record]);
|
|
1095
1878
|
} catch (error$1) {
|
|
1096
1879
|
throw new error.MastraError(
|
|
1097
1880
|
{
|
|
1098
|
-
id: "
|
|
1881
|
+
id: "LANCE_STORE_GET_WORKFLOW_RUNS_FAILED",
|
|
1099
1882
|
domain: error.ErrorDomain.STORAGE,
|
|
1100
1883
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1101
|
-
details: {
|
|
1884
|
+
details: { namespace: args?.namespace ?? "", workflowName: args?.workflowName ?? "" }
|
|
1102
1885
|
},
|
|
1103
1886
|
error$1
|
|
1104
1887
|
);
|
|
1105
1888
|
}
|
|
1106
1889
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1890
|
+
};
|
|
1891
|
+
|
|
1892
|
+
// src/storage/index.ts
|
|
1893
|
+
var LanceStorage = class _LanceStorage extends storage.MastraStorage {
|
|
1894
|
+
stores;
|
|
1895
|
+
lanceClient;
|
|
1896
|
+
/**
|
|
1897
|
+
* Creates a new instance of LanceStorage
|
|
1898
|
+
* @param uri The URI to connect to LanceDB
|
|
1899
|
+
* @param options connection options
|
|
1900
|
+
*
|
|
1901
|
+
* Usage:
|
|
1902
|
+
*
|
|
1903
|
+
* Connect to a local database
|
|
1904
|
+
* ```ts
|
|
1905
|
+
* const store = await LanceStorage.create('/path/to/db');
|
|
1906
|
+
* ```
|
|
1907
|
+
*
|
|
1908
|
+
* Connect to a LanceDB cloud database
|
|
1909
|
+
* ```ts
|
|
1910
|
+
* const store = await LanceStorage.create('db://host:port');
|
|
1911
|
+
* ```
|
|
1912
|
+
*
|
|
1913
|
+
* Connect to a cloud database
|
|
1914
|
+
* ```ts
|
|
1915
|
+
* const store = await LanceStorage.create('s3://bucket/db', { storageOptions: { timeout: '60s' } });
|
|
1916
|
+
* ```
|
|
1917
|
+
*/
|
|
1918
|
+
static async create(name, uri, options) {
|
|
1919
|
+
const instance = new _LanceStorage(name);
|
|
1111
1920
|
try {
|
|
1112
|
-
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1921
|
+
instance.lanceClient = await lancedb.connect(uri, options);
|
|
1922
|
+
const operations = new StoreOperationsLance({ client: instance.lanceClient });
|
|
1923
|
+
instance.stores = {
|
|
1924
|
+
operations: new StoreOperationsLance({ client: instance.lanceClient }),
|
|
1925
|
+
workflows: new StoreWorkflowsLance({ client: instance.lanceClient }),
|
|
1926
|
+
traces: new StoreTracesLance({ client: instance.lanceClient, operations }),
|
|
1927
|
+
scores: new StoreScoresLance({ client: instance.lanceClient }),
|
|
1928
|
+
memory: new StoreMemoryLance({ client: instance.lanceClient, operations }),
|
|
1929
|
+
legacyEvals: new StoreLegacyEvalsLance({ client: instance.lanceClient })
|
|
1930
|
+
};
|
|
1931
|
+
return instance;
|
|
1932
|
+
} catch (e) {
|
|
1117
1933
|
throw new error.MastraError(
|
|
1118
1934
|
{
|
|
1119
|
-
id: "
|
|
1935
|
+
id: "STORAGE_LANCE_STORAGE_CONNECT_FAILED",
|
|
1120
1936
|
domain: error.ErrorDomain.STORAGE,
|
|
1121
1937
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1122
|
-
|
|
1938
|
+
text: `Failed to connect to LanceDB: ${e.message || e}`,
|
|
1939
|
+
details: { uri, optionsProvided: !!options }
|
|
1123
1940
|
},
|
|
1124
|
-
|
|
1941
|
+
e
|
|
1125
1942
|
);
|
|
1126
1943
|
}
|
|
1127
1944
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1945
|
+
/**
|
|
1946
|
+
* @internal
|
|
1947
|
+
* Private constructor to enforce using the create factory method
|
|
1948
|
+
*/
|
|
1949
|
+
constructor(name) {
|
|
1950
|
+
super({ name });
|
|
1951
|
+
const operations = new StoreOperationsLance({ client: this.lanceClient });
|
|
1952
|
+
this.stores = {
|
|
1953
|
+
operations: new StoreOperationsLance({ client: this.lanceClient }),
|
|
1954
|
+
workflows: new StoreWorkflowsLance({ client: this.lanceClient }),
|
|
1955
|
+
traces: new StoreTracesLance({ client: this.lanceClient, operations }),
|
|
1956
|
+
scores: new StoreScoresLance({ client: this.lanceClient }),
|
|
1957
|
+
legacyEvals: new StoreLegacyEvalsLance({ client: this.lanceClient }),
|
|
1958
|
+
memory: new StoreMemoryLance({ client: this.lanceClient, operations })
|
|
1959
|
+
};
|
|
1137
1960
|
}
|
|
1138
|
-
async
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1144
|
-
},
|
|
1145
|
-
"Method not implemented."
|
|
1146
|
-
);
|
|
1961
|
+
async createTable({
|
|
1962
|
+
tableName,
|
|
1963
|
+
schema
|
|
1964
|
+
}) {
|
|
1965
|
+
return this.stores.operations.createTable({ tableName, schema });
|
|
1147
1966
|
}
|
|
1148
|
-
async
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
);
|
|
1967
|
+
async dropTable({ tableName }) {
|
|
1968
|
+
return this.stores.operations.dropTable({ tableName });
|
|
1969
|
+
}
|
|
1970
|
+
async alterTable({
|
|
1971
|
+
tableName,
|
|
1972
|
+
schema,
|
|
1973
|
+
ifNotExists
|
|
1974
|
+
}) {
|
|
1975
|
+
return this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
1976
|
+
}
|
|
1977
|
+
async clearTable({ tableName }) {
|
|
1978
|
+
return this.stores.operations.clearTable({ tableName });
|
|
1979
|
+
}
|
|
1980
|
+
async insert({ tableName, record }) {
|
|
1981
|
+
return this.stores.operations.insert({ tableName, record });
|
|
1982
|
+
}
|
|
1983
|
+
async batchInsert({ tableName, records }) {
|
|
1984
|
+
return this.stores.operations.batchInsert({ tableName, records });
|
|
1985
|
+
}
|
|
1986
|
+
async load({ tableName, keys }) {
|
|
1987
|
+
return this.stores.operations.load({ tableName, keys });
|
|
1988
|
+
}
|
|
1989
|
+
async getThreadById({ threadId }) {
|
|
1990
|
+
return this.stores.memory.getThreadById({ threadId });
|
|
1991
|
+
}
|
|
1992
|
+
async getThreadsByResourceId({ resourceId }) {
|
|
1993
|
+
return this.stores.memory.getThreadsByResourceId({ resourceId });
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Saves a thread to the database. This function doesn't overwrite existing threads.
|
|
1997
|
+
* @param thread - The thread to save
|
|
1998
|
+
* @returns The saved thread
|
|
1999
|
+
*/
|
|
2000
|
+
async saveThread({ thread }) {
|
|
2001
|
+
return this.stores.memory.saveThread({ thread });
|
|
2002
|
+
}
|
|
2003
|
+
async updateThread({
|
|
2004
|
+
id,
|
|
2005
|
+
title,
|
|
2006
|
+
metadata
|
|
2007
|
+
}) {
|
|
2008
|
+
return this.stores.memory.updateThread({ id, title, metadata });
|
|
2009
|
+
}
|
|
2010
|
+
async deleteThread({ threadId }) {
|
|
2011
|
+
return this.stores.memory.deleteThread({ threadId });
|
|
2012
|
+
}
|
|
2013
|
+
get supports() {
|
|
2014
|
+
return {
|
|
2015
|
+
selectByIncludeResourceScope: true,
|
|
2016
|
+
resourceWorkingMemory: true,
|
|
2017
|
+
hasColumn: true,
|
|
2018
|
+
createTable: true,
|
|
2019
|
+
deleteMessages: false
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
2022
|
+
async getResourceById({ resourceId }) {
|
|
2023
|
+
return this.stores.memory.getResourceById({ resourceId });
|
|
2024
|
+
}
|
|
2025
|
+
async saveResource({ resource }) {
|
|
2026
|
+
return this.stores.memory.saveResource({ resource });
|
|
2027
|
+
}
|
|
2028
|
+
async updateResource({
|
|
2029
|
+
resourceId,
|
|
2030
|
+
workingMemory,
|
|
2031
|
+
metadata
|
|
2032
|
+
}) {
|
|
2033
|
+
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Processes messages to include context messages based on withPreviousMessages and withNextMessages
|
|
2037
|
+
* @param records - The sorted array of records to process
|
|
2038
|
+
* @param include - The array of include specifications with context parameters
|
|
2039
|
+
* @returns The processed array with context messages included
|
|
2040
|
+
*/
|
|
2041
|
+
processMessagesWithContext(records, include) {
|
|
2042
|
+
const messagesWithContext = include.filter((item) => item.withPreviousMessages || item.withNextMessages);
|
|
2043
|
+
if (messagesWithContext.length === 0) {
|
|
2044
|
+
return records;
|
|
2045
|
+
}
|
|
2046
|
+
const messageIndexMap = /* @__PURE__ */ new Map();
|
|
2047
|
+
records.forEach((message, index) => {
|
|
2048
|
+
messageIndexMap.set(message.id, index);
|
|
2049
|
+
});
|
|
2050
|
+
const additionalIndices = /* @__PURE__ */ new Set();
|
|
2051
|
+
for (const item of messagesWithContext) {
|
|
2052
|
+
const messageIndex = messageIndexMap.get(item.id);
|
|
2053
|
+
if (messageIndex !== void 0) {
|
|
2054
|
+
if (item.withPreviousMessages) {
|
|
2055
|
+
const startIdx = Math.max(0, messageIndex - item.withPreviousMessages);
|
|
2056
|
+
for (let i = startIdx; i < messageIndex; i++) {
|
|
2057
|
+
additionalIndices.add(i);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
if (item.withNextMessages) {
|
|
2061
|
+
const endIdx = Math.min(records.length - 1, messageIndex + item.withNextMessages);
|
|
2062
|
+
for (let i = messageIndex + 1; i <= endIdx; i++) {
|
|
2063
|
+
additionalIndices.add(i);
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
if (additionalIndices.size === 0) {
|
|
2069
|
+
return records;
|
|
2070
|
+
}
|
|
2071
|
+
const originalMatchIds = new Set(include.map((item) => item.id));
|
|
2072
|
+
const allIndices = /* @__PURE__ */ new Set();
|
|
2073
|
+
records.forEach((record, index) => {
|
|
2074
|
+
if (originalMatchIds.has(record.id)) {
|
|
2075
|
+
allIndices.add(index);
|
|
2076
|
+
}
|
|
2077
|
+
});
|
|
2078
|
+
additionalIndices.forEach((index) => {
|
|
2079
|
+
allIndices.add(index);
|
|
2080
|
+
});
|
|
2081
|
+
return Array.from(allIndices).sort((a, b) => a - b).map((index) => records[index]);
|
|
2082
|
+
}
|
|
2083
|
+
async getMessages({
|
|
2084
|
+
threadId,
|
|
2085
|
+
resourceId,
|
|
2086
|
+
selectBy,
|
|
2087
|
+
format,
|
|
2088
|
+
threadConfig
|
|
2089
|
+
}) {
|
|
2090
|
+
return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format, threadConfig });
|
|
2091
|
+
}
|
|
2092
|
+
async saveMessages(args) {
|
|
2093
|
+
return this.stores.memory.saveMessages(args);
|
|
2094
|
+
}
|
|
2095
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
2096
|
+
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2097
|
+
}
|
|
2098
|
+
async getMessagesPaginated(args) {
|
|
2099
|
+
return this.stores.memory.getMessagesPaginated(args);
|
|
1157
2100
|
}
|
|
1158
2101
|
async updateMessages(_args) {
|
|
1159
|
-
this.
|
|
1160
|
-
|
|
2102
|
+
return this.stores.memory.updateMessages(_args);
|
|
2103
|
+
}
|
|
2104
|
+
async getTraceById(args) {
|
|
2105
|
+
return this.stores.traces.getTraceById(args);
|
|
2106
|
+
}
|
|
2107
|
+
async getTraces(args) {
|
|
2108
|
+
return this.stores.traces.getTraces(args);
|
|
2109
|
+
}
|
|
2110
|
+
async getTracesPaginated(args) {
|
|
2111
|
+
return this.stores.traces.getTracesPaginated(args);
|
|
2112
|
+
}
|
|
2113
|
+
async getEvalsByAgentName(agentName, type) {
|
|
2114
|
+
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2115
|
+
}
|
|
2116
|
+
async getEvals(options) {
|
|
2117
|
+
return this.stores.legacyEvals.getEvals(options);
|
|
2118
|
+
}
|
|
2119
|
+
async getWorkflowRuns(args) {
|
|
2120
|
+
return this.stores.workflows.getWorkflowRuns(args);
|
|
2121
|
+
}
|
|
2122
|
+
async getWorkflowRunById(args) {
|
|
2123
|
+
return this.stores.workflows.getWorkflowRunById(args);
|
|
2124
|
+
}
|
|
2125
|
+
async persistWorkflowSnapshot({
|
|
2126
|
+
workflowName,
|
|
2127
|
+
runId,
|
|
2128
|
+
snapshot
|
|
2129
|
+
}) {
|
|
2130
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
2131
|
+
}
|
|
2132
|
+
async loadWorkflowSnapshot({
|
|
2133
|
+
workflowName,
|
|
2134
|
+
runId
|
|
2135
|
+
}) {
|
|
2136
|
+
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
2137
|
+
}
|
|
2138
|
+
async getScoreById({ id: _id }) {
|
|
2139
|
+
return this.stores.scores.getScoreById({ id: _id });
|
|
2140
|
+
}
|
|
2141
|
+
async getScoresByScorerId({
|
|
2142
|
+
scorerId,
|
|
2143
|
+
source,
|
|
2144
|
+
entityId,
|
|
2145
|
+
entityType,
|
|
2146
|
+
pagination
|
|
2147
|
+
}) {
|
|
2148
|
+
return this.stores.scores.getScoresByScorerId({ scorerId, source, pagination, entityId, entityType });
|
|
2149
|
+
}
|
|
2150
|
+
async saveScore(_score) {
|
|
2151
|
+
return this.stores.scores.saveScore(_score);
|
|
2152
|
+
}
|
|
2153
|
+
async getScoresByRunId({
|
|
2154
|
+
runId,
|
|
2155
|
+
pagination
|
|
2156
|
+
}) {
|
|
2157
|
+
return this.stores.scores.getScoresByRunId({ runId, pagination });
|
|
2158
|
+
}
|
|
2159
|
+
async getScoresByEntityId({
|
|
2160
|
+
entityId,
|
|
2161
|
+
entityType,
|
|
2162
|
+
pagination
|
|
2163
|
+
}) {
|
|
2164
|
+
return this.stores.scores.getScoresByEntityId({ entityId, entityType, pagination });
|
|
1161
2165
|
}
|
|
1162
2166
|
};
|
|
1163
2167
|
var LanceFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
@@ -2217,3 +3221,5 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2217
3221
|
|
|
2218
3222
|
exports.LanceStorage = LanceStorage;
|
|
2219
3223
|
exports.LanceVectorStore = LanceVectorStore;
|
|
3224
|
+
//# sourceMappingURL=index.cjs.map
|
|
3225
|
+
//# sourceMappingURL=index.cjs.map
|