@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.
Files changed (46) hide show
  1. package/CHANGELOG.md +177 -9
  2. package/LICENSE.md +11 -42
  3. package/dist/index.cjs +1649 -643
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +1584 -578
  8. package/dist/index.js.map +1 -0
  9. package/dist/storage/domains/legacy-evals/index.d.ts +25 -0
  10. package/dist/storage/domains/legacy-evals/index.d.ts.map +1 -0
  11. package/dist/storage/domains/memory/index.d.ts +94 -0
  12. package/dist/storage/domains/memory/index.d.ts.map +1 -0
  13. package/dist/storage/domains/operations/index.d.ts +40 -0
  14. package/dist/storage/domains/operations/index.d.ts.map +1 -0
  15. package/dist/storage/domains/scores/index.d.ts +42 -0
  16. package/dist/storage/domains/scores/index.d.ts.map +1 -0
  17. package/dist/storage/domains/traces/index.d.ts +34 -0
  18. package/dist/storage/domains/traces/index.d.ts.map +1 -0
  19. package/dist/storage/domains/utils.d.ts +10 -0
  20. package/dist/storage/domains/utils.d.ts.map +1 -0
  21. package/dist/storage/domains/workflows/index.d.ts +38 -0
  22. package/dist/storage/domains/workflows/index.d.ts.map +1 -0
  23. package/dist/storage/index.d.ts +236 -0
  24. package/dist/storage/index.d.ts.map +1 -0
  25. package/dist/vector/filter.d.ts +41 -0
  26. package/dist/vector/filter.d.ts.map +1 -0
  27. package/dist/vector/index.d.ts +85 -0
  28. package/dist/vector/index.d.ts.map +1 -0
  29. package/dist/vector/types.d.ts +15 -0
  30. package/dist/vector/types.d.ts.map +1 -0
  31. package/package.json +11 -10
  32. package/src/storage/domains/legacy-evals/index.ts +156 -0
  33. package/src/storage/domains/memory/index.ts +947 -0
  34. package/src/storage/domains/operations/index.ts +489 -0
  35. package/src/storage/domains/scores/index.ts +243 -0
  36. package/src/storage/domains/traces/index.ts +212 -0
  37. package/src/storage/domains/utils.ts +158 -0
  38. package/src/storage/domains/workflows/index.ts +207 -0
  39. package/src/storage/index.test.ts +6 -1332
  40. package/src/storage/index.ts +163 -1162
  41. package/tsconfig.build.json +9 -0
  42. package/tsconfig.json +1 -1
  43. package/tsup.config.ts +17 -0
  44. package/dist/_tsup-dts-rollup.d.cts +0 -409
  45. package/dist/_tsup-dts-rollup.d.ts +0 -409
  46. 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 LanceStorage = class _LanceStorage extends storage.MastraStorage {
13
- lanceClient;
14
- /**
15
- * Creates a new instance of LanceStorage
16
- * @param uri The URI to connect to LanceDB
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 createTable({
71
- tableName,
72
- schema
73
- }) {
18
+ async getEvalsByAgentName(agentName, type) {
74
19
  try {
75
- if (!this.lanceClient) {
76
- throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
77
- }
78
- if (!tableName) {
79
- throw new Error("tableName is required for createTable.");
80
- }
81
- if (!schema) {
82
- throw new Error("schema is required for createTable.");
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: "STORAGE_LANCE_STORAGE_CREATE_TABLE_INVALID_ARGS",
47
+ id: "LANCE_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
88
48
  domain: error.ErrorDomain.STORAGE,
89
- category: error.ErrorCategory.USER,
90
- details: { tableName }
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 arrowSchema = this.translateSchema(schema);
97
- await this.lanceClient.createEmptyTable(tableName, arrowSchema);
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: "STORAGE_LANCE_STORAGE_CREATE_TABLE_FAILED",
116
+ id: "LANCE_STORE_GET_EVALS_FAILED",
102
117
  domain: error.ErrorDomain.STORAGE,
103
118
  category: error.ErrorCategory.THIRD_PARTY,
104
- details: { tableName }
119
+ details: { agentName: options.agentName ?? "" }
105
120
  },
106
121
  error$1
107
122
  );
108
123
  }
109
124
  }
110
- translateSchema(schema) {
111
- const fields = Object.entries(schema).map(([name, column]) => {
112
- let arrowType;
113
- switch (column.type.toLowerCase()) {
114
- case "text":
115
- case "uuid":
116
- arrowType = new apacheArrow.Utf8();
117
- break;
118
- case "int":
119
- case "integer":
120
- arrowType = new apacheArrow.Int32();
121
- break;
122
- case "bigint":
123
- arrowType = new apacheArrow.Float64();
124
- break;
125
- case "float":
126
- arrowType = new apacheArrow.Float32();
127
- break;
128
- case "jsonb":
129
- case "json":
130
- arrowType = new apacheArrow.Utf8();
131
- break;
132
- case "binary":
133
- arrowType = new apacheArrow.Binary();
134
- break;
135
- case "timestamp":
136
- arrowType = new apacheArrow.Float64();
137
- break;
138
- default:
139
- arrowType = new apacheArrow.Utf8();
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
- return new apacheArrow.Field(name, arrowType, column.nullable ?? true);
142
- });
143
- return new apacheArrow.Schema(fields);
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
- * Drop a table if it exists
147
- * @param tableName Name of the table to drop
148
- */
149
- async dropTable(tableName) {
150
- try {
151
- if (!this.lanceClient) {
152
- throw new Error("LanceDB client not initialized. Call LanceStorage.create() first.");
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
- if (!tableName) {
155
- throw new Error("tableName is required for dropTable.");
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
- } catch (validationError) {
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: "STORAGE_LANCE_STORAGE_DROP_TABLE_INVALID_ARGS",
266
+ id: "LANCE_STORE_GET_THREAD_BY_ID_FAILED",
161
267
  domain: error.ErrorDomain.STORAGE,
162
- category: error.ErrorCategory.USER,
163
- text: validationError.message,
164
- details: { tableName }
268
+ category: error.ErrorCategory.THIRD_PARTY
165
269
  },
166
- validationError
270
+ error$1
167
271
  );
168
272
  }
273
+ }
274
+ async getThreadsByResourceId({ resourceId }) {
169
275
  try {
170
- await this.lanceClient.dropTable(tableName);
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: "STORAGE_LANCE_STORAGE_DROP_TABLE_FAILED",
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
- * Get table schema
189
- * @param tableName Name of the table
190
- * @returns Table schema
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 getTableSchema(tableName) {
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 table = await this.lanceClient.openTable(tableName);
214
- const rawSchema = await table.schema();
215
- const fields = rawSchema.fields;
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: "STORAGE_LANCE_STORAGE_GET_TABLE_SCHEMA_FAILED",
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
- getDefaultValue(type) {
236
- switch (type) {
237
- case "text":
238
- return "''";
239
- case "timestamp":
240
- return "CURRENT_TIMESTAMP";
241
- case "integer":
242
- case "bigint":
243
- return "0";
244
- case "jsonb":
245
- return "'{}'";
246
- case "uuid":
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
- * Alters table schema to add columns if they don't exist
254
- * @param tableName Name of the table
255
- * @param schema Schema of the table
256
- * @param ifNotExists Array of column names to add if they don't exist
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.lanceClient) {
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.lanceClient.openTable(tableName);
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.lanceClient) {
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.lanceClient.openTable(tableName);
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.lanceClient) {
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.lanceClient.openTable(tableName);
389
- const primaryId = this.getPrimaryKeys(tableName);
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.lanceClient) {
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.lanceClient.openTable(tableName);
440
- const primaryId = this.getPrimaryKeys(tableName);
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.lanceClient) {
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.lanceClient.openTable(tableName);
496
- const tableSchema = await this.getTableSchema(tableName);
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
- this.validateKeyTypes(keys, tableSchema);
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 this.processResultWithTypeConversion(result[0], tableSchema);
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: "LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
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
- * Saves a thread to the database. This function doesn't overwrite existing threads.
637
- * @param thread - The thread to save
638
- * @returns The saved thread
639
- */
640
- async saveThread({ thread }) {
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 record = { ...thread, metadata: JSON.stringify(thread.metadata) };
643
- const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
644
- await table.add([record], { mode: "append" });
645
- return thread;
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: "LANCE_STORE_SAVE_THREAD_FAILED",
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 updateThread({
658
- id,
659
- title,
660
- metadata
661
- }) {
1395
+ async getScoreById({ id }) {
662
1396
  try {
663
- const record = { id, title, metadata: JSON.stringify(metadata) };
664
- const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
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 this.processResultWithTypeConversion(
669
- records[0],
670
- await this.getTableSchema(storage.TABLE_THREADS)
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: "LANCE_STORE_UPDATE_THREAD_FAILED",
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 deleteThread({ threadId }) {
1416
+ async getScoresByScorerId({
1417
+ scorerId,
1418
+ pagination,
1419
+ entityId,
1420
+ entityType,
1421
+ source
1422
+ }) {
684
1423
  try {
685
- const table = await this.lanceClient.openTable(storage.TABLE_THREADS);
686
- await table.delete(`id = '${threadId}'`);
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: "LANCE_STORE_DELETE_THREAD_FAILED",
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
- * Processes messages to include context messages based on withPreviousMessages and withNextMessages
700
- * @param records - The sorted array of records to process
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
- if (threadConfig) {
755
- throw new Error("ThreadConfig is not supported by LanceDB storage");
756
- }
757
- const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
758
- const table = await this.lanceClient.openTable(storage.TABLE_MESSAGES);
759
- let query = table.query().where(`\`threadId\` = '${threadId}'`);
760
- if (selectBy) {
761
- if (selectBy.include && selectBy.include.length > 0) {
762
- const includeIds = selectBy.include.map((item) => item.id);
763
- const includeClause = includeIds.map((id) => `\`id\` = '${id}'`).join(" OR ");
764
- query = query.where(`(\`threadId\` = '${threadId}' OR (${includeClause}))`);
765
- }
766
- }
767
- let records = await query.toArray();
768
- records.sort((a, b) => {
769
- const dateA = new Date(a.createdAt).getTime();
770
- const dateB = new Date(b.createdAt).getTime();
771
- return dateA - dateB;
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: "LANCE_STORE_GET_MESSAGES_FAILED",
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 saveMessages(args) {
1507
+ async getScoresByEntityId({
1508
+ entityId,
1509
+ entityType,
1510
+ pagination
1511
+ }) {
805
1512
  try {
806
- const { messages, format = "v1" } = args;
807
- if (messages.length === 0) {
808
- return [];
809
- }
810
- const threadId = messages[0]?.threadId;
811
- if (!threadId) {
812
- throw new Error("Thread ID is required");
813
- }
814
- const transformedMessages = messages.map((message) => ({
815
- ...message,
816
- content: JSON.stringify(message.content)
817
- }));
818
- const table = await this.lanceClient.openTable(storage.TABLE_MESSAGES);
819
- await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(transformedMessages);
820
- const list = new agent.MessageList().add(messages, "memory");
821
- if (format === `v2`) return list.get.all.v2();
822
- return list.get.all.v1();
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: "LANCE_STORE_SAVE_MESSAGES_FAILED",
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.lanceClient.openTable(storage.TABLE_TRACES);
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.lanceClient.openTable(storage.TABLE_TRACES);
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 this.processResultWithTypeConversion(records[0], await this.getTableSchema(storage.TABLE_TRACES));
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.lanceClient.openTable(storage.TABLE_TRACES);
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
- return {
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 saveEvals({ evals }) {
1651
+ async getTracesPaginated(args) {
926
1652
  try {
927
- const table = await this.lanceClient.openTable(storage.TABLE_EVALS);
928
- const transformedEvals = evals.map((evalRecord) => ({
929
- input: evalRecord.input,
930
- output: evalRecord.output,
931
- agent_name: evalRecord.agentName,
932
- metric_name: evalRecord.metricName,
933
- result: JSON.stringify(evalRecord.result),
934
- instructions: evalRecord.instructions,
935
- test_info: JSON.stringify(evalRecord.testInfo),
936
- global_run_id: evalRecord.globalRunId,
937
- run_id: evalRecord.runId,
938
- created_at: new Date(evalRecord.createdAt).getTime()
939
- }));
940
- await table.add(transformedEvals, { mode: "append" });
941
- return evals;
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: "LANCE_STORE_SAVE_EVALS_FAILED",
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 getEvalsByAgentName(agentName, type) {
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
- if (type) {
956
- this.logger.warn("Type is not implemented yet in LanceDB storage");
957
- }
958
- const table = await this.lanceClient.openTable(storage.TABLE_EVALS);
959
- const query = table.query().where(`agent_name = '${agentName}'`);
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
- return records.map((record) => {
962
- return {
963
- id: record.id,
964
- input: record.input,
965
- output: record.output,
966
- agentName: record.agent_name,
967
- metricName: record.metric_name,
968
- result: JSON.parse(record.result),
969
- instructions: record.instructions,
970
- testInfo: JSON.parse(record.test_info),
971
- globalRunId: record.global_run_id,
972
- runId: record.run_id,
973
- createdAt: new Date(record.created_at).toString()
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: "LANCE_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
1789
+ id: "LANCE_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
980
1790
  domain: error.ErrorDomain.STORAGE,
981
1791
  category: error.ErrorCategory.THIRD_PARTY,
982
- details: { agentName }
1792
+ details: { workflowName, runId }
983
1793
  },
984
1794
  error$1
985
1795
  );
986
1796
  }
987
1797
  }
988
- parseWorkflowRun(row) {
989
- let parsedSnapshot = row.snapshot;
990
- if (typeof parsedSnapshot === "string") {
991
- try {
992
- parsedSnapshot = JSON.parse(row.snapshot);
993
- } catch (e) {
994
- console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
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: "LANCE_STORE_GET_WORKFLOW_RUNS_FAILED",
1810
+ id: "LANCE_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
1034
1811
  domain: error.ErrorDomain.STORAGE,
1035
1812
  category: error.ErrorCategory.THIRD_PARTY,
1036
- details: { namespace: args?.namespace ?? "", workflowName: args?.workflowName ?? "" }
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.lanceClient.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
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 this.parseWorkflowRun(record);
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 persistWorkflowSnapshot({
1072
- workflowName,
1073
- runId,
1074
- snapshot
1075
- }) {
1843
+ async getWorkflowRuns(args) {
1076
1844
  try {
1077
- const table = await this.lanceClient.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
1078
- const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
1079
- const records = await query.toArray();
1080
- let createdAt;
1081
- const now = Date.now();
1082
- if (records.length > 0) {
1083
- createdAt = records[0].createdAt ?? now;
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
- createdAt = now;
1865
+ total = await table.countRows();
1086
1866
  }
1087
- const record = {
1088
- workflow_name: workflowName,
1089
- run_id: runId,
1090
- snapshot: JSON.stringify(snapshot),
1091
- createdAt,
1092
- updatedAt: now
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: "LANCE_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
1881
+ id: "LANCE_STORE_GET_WORKFLOW_RUNS_FAILED",
1099
1882
  domain: error.ErrorDomain.STORAGE,
1100
1883
  category: error.ErrorCategory.THIRD_PARTY,
1101
- details: { workflowName, runId }
1884
+ details: { namespace: args?.namespace ?? "", workflowName: args?.workflowName ?? "" }
1102
1885
  },
1103
1886
  error$1
1104
1887
  );
1105
1888
  }
1106
1889
  }
1107
- async loadWorkflowSnapshot({
1108
- workflowName,
1109
- runId
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
- const table = await this.lanceClient.openTable(storage.TABLE_WORKFLOW_SNAPSHOT);
1113
- const query = table.query().where(`workflow_name = '${workflowName}' AND run_id = '${runId}'`);
1114
- const records = await query.toArray();
1115
- return records.length > 0 ? JSON.parse(records[0].snapshot) : null;
1116
- } catch (error$1) {
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: "LANCE_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
1935
+ id: "STORAGE_LANCE_STORAGE_CONNECT_FAILED",
1120
1936
  domain: error.ErrorDomain.STORAGE,
1121
1937
  category: error.ErrorCategory.THIRD_PARTY,
1122
- details: { workflowName, runId }
1938
+ text: `Failed to connect to LanceDB: ${e.message || e}`,
1939
+ details: { uri, optionsProvided: !!options }
1123
1940
  },
1124
- error$1
1941
+ e
1125
1942
  );
1126
1943
  }
1127
1944
  }
1128
- async getTracesPaginated(_args) {
1129
- throw new error.MastraError(
1130
- {
1131
- id: "LANCE_STORE_GET_TRACES_PAGINATED_FAILED",
1132
- domain: error.ErrorDomain.STORAGE,
1133
- category: error.ErrorCategory.THIRD_PARTY
1134
- },
1135
- "Method not implemented."
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 getThreadsByResourceIdPaginated(_args) {
1139
- throw new error.MastraError(
1140
- {
1141
- id: "LANCE_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1142
- domain: error.ErrorDomain.STORAGE,
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 getMessagesPaginated(_args) {
1149
- throw new error.MastraError(
1150
- {
1151
- id: "LANCE_STORE_GET_MESSAGES_PAGINATED_FAILED",
1152
- domain: error.ErrorDomain.STORAGE,
1153
- category: error.ErrorCategory.THIRD_PARTY
1154
- },
1155
- "Method not implemented."
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.logger.error("updateMessages is not yet implemented in LanceStore");
1160
- throw new Error("Method not implemented");
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