@mastra/core 0.2.0-alpha.99 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/agent/index.d.ts +6 -8
  2. package/dist/agent/index.js +15 -7
  3. package/dist/{telemetry-oCUM52DG.d.ts → base-BbtPAA6f.d.ts} +50 -8
  4. package/dist/{index-Cwb-5AzX.d.ts → base-Bpb7Dmwe.d.ts} +367 -320
  5. package/dist/base.d.ts +3 -43
  6. package/dist/base.js +3 -3
  7. package/dist/bundler/index.d.ts +3 -4
  8. package/dist/bundler/index.js +4 -4
  9. package/dist/{chunk-MCB4M5W4.js → chunk-22LC46YN.js} +3 -9
  10. package/dist/{chunk-A7SNFYQB.js → chunk-2JL6DQMZ.js} +20 -28
  11. package/dist/chunk-2SAHBQEF.js +3 -0
  12. package/dist/chunk-3HBFW3Q7.js +24 -0
  13. package/dist/{chunk-KNPBNSJ7.js → chunk-55GTEVHJ.js} +12 -13
  14. package/dist/chunk-65VPTVVP.js +218 -0
  15. package/dist/chunk-AWEACB2T.js +66 -0
  16. package/dist/chunk-C6A6W6XS.js +49 -0
  17. package/dist/chunk-FGZVE4CM.js +404 -0
  18. package/dist/{chunk-DHCULRJM.js → chunk-J3W3IHDO.js} +114 -88
  19. package/dist/chunk-K36NSQWH.js +10 -0
  20. package/dist/{chunk-EO3TIPGQ.js → chunk-K4DFI76V.js} +382 -370
  21. package/dist/{chunk-42DYOLDV.js → chunk-MEISIZMP.js} +13 -21
  22. package/dist/chunk-MLWGYRJR.js +87 -0
  23. package/dist/{chunk-ICMEXHKD.js → chunk-O2VP5JBC.js} +48 -55
  24. package/dist/{chunk-ZJOMHCWE.js → chunk-OJ26F3J4.js} +98 -153
  25. package/dist/chunk-RG66XEJT.js +8 -0
  26. package/dist/chunk-SB37QG7O.js +1203 -0
  27. package/dist/chunk-SDBM53G4.js +32 -0
  28. package/dist/{chunk-4LJFWC2Q.js → chunk-SIFBBGY6.js} +59 -85
  29. package/dist/chunk-U6J2FOU4.js +624 -0
  30. package/dist/chunk-VB7CO5ND.js +31 -0
  31. package/dist/{chunk-C55JWGDU.js → chunk-ZJOXJFJI.js} +43 -15
  32. package/dist/deployer/index.d.ts +2 -4
  33. package/dist/deployer/index.js +5 -5
  34. package/dist/eval/index.d.ts +8 -13
  35. package/dist/eval/index.js +3 -3
  36. package/dist/filter/index.js +2 -2
  37. package/dist/hooks/index.d.ts +13 -18
  38. package/dist/hooks/index.js +2 -2
  39. package/dist/{index-CBZ2mk2H.d.ts → index-B2JCcAQt.d.ts} +1 -1
  40. package/dist/index.d.ts +15 -15
  41. package/dist/index.js +43 -69
  42. package/dist/integration/index.d.ts +8 -10
  43. package/dist/integration/index.js +6 -3
  44. package/dist/llm/index.d.ts +6 -8
  45. package/dist/llm/index.js +1 -1
  46. package/dist/logger/index.d.ts +1 -1
  47. package/dist/logger/index.js +2 -2
  48. package/dist/mastra/index.d.ts +10 -13
  49. package/dist/mastra/index.js +20 -9
  50. package/dist/memory/index.d.ts +8 -10
  51. package/dist/memory/index.js +11 -9
  52. package/dist/relevance/index.js +16 -8
  53. package/dist/storage/index.d.ts +21 -10
  54. package/dist/storage/index.js +8 -7
  55. package/dist/telemetry/index.d.ts +35 -5
  56. package/dist/telemetry/index.js +3 -2
  57. package/dist/telemetry/otel-vendor.d.ts +7 -0
  58. package/dist/telemetry/otel-vendor.js +8 -0
  59. package/dist/tools/index.d.ts +6 -8
  60. package/dist/tools/index.js +2 -2
  61. package/dist/tts/index.d.ts +2 -4
  62. package/dist/tts/index.js +6 -5
  63. package/dist/{metric-BWeQNZt6.d.ts → types-m9RryK9a.d.ts} +6 -1
  64. package/dist/utils.js +2 -2
  65. package/dist/vector/index.d.ts +4 -6
  66. package/dist/vector/index.js +4 -4
  67. package/dist/vector/libsql/index.d.ts +2 -4
  68. package/dist/vector/libsql/index.js +6 -6
  69. package/dist/{workflow-DTtv7_Eq.d.ts → workflow-Cy8UTGCt.d.ts} +3 -6
  70. package/dist/workflows/index.d.ts +7 -9
  71. package/dist/workflows/index.js +4 -4
  72. package/package.json +14 -10
  73. package/dist/chunk-4ZUSEHLH.js +0 -285
  74. package/dist/chunk-AJJZUHB4.js +0 -14
  75. package/dist/chunk-G4MCO7XF.js +0 -70
  76. package/dist/chunk-HBTQNIAX.js +0 -90
  77. package/dist/chunk-HPXWJBQK.js +0 -222
  78. package/dist/chunk-JJ57BXQR.js +0 -16
  79. package/dist/chunk-JP37ODNX.js +0 -36
  80. package/dist/chunk-K3N7KJHH.js +0 -52
  81. package/dist/chunk-MDM2JS2U.js +0 -1288
  82. package/dist/chunk-VOUPGVRD.js +0 -27
  83. package/dist/chunk-Z7JFMQZZ.js +0 -551
  84. /package/dist/{chunk-AE3H2QEY.js → chunk-VDOJTUYY.js} +0 -0
@@ -0,0 +1,624 @@
1
+ import { TABLE_WORKFLOW_SNAPSHOT, TABLE_EVALS, TABLE_MESSAGES, TABLE_THREADS, TABLE_TRACES } from './chunk-RG66XEJT.js';
2
+ import { MastraBase } from './chunk-AWEACB2T.js';
3
+ import { createClient } from '@libsql/client';
4
+ import { join } from 'node:path';
5
+
6
+ // src/storage/base.ts
7
+ var MastraStorage = class extends MastraBase {
8
+ /** @deprecated import from { TABLE_WORKFLOW_SNAPSHOT } '@mastra/core/storage' instead */
9
+ static TABLE_WORKFLOW_SNAPSHOT = TABLE_WORKFLOW_SNAPSHOT;
10
+ /** @deprecated import from { TABLE_EVALS } '@mastra/core/storage' instead */
11
+ static TABLE_EVALS = TABLE_EVALS;
12
+ /** @deprecated import from { TABLE_MESSAGES } '@mastra/core/storage' instead */
13
+ static TABLE_MESSAGES = TABLE_MESSAGES;
14
+ /** @deprecated import from { TABLE_THREADS } '@mastra/core/storage' instead */
15
+ static TABLE_THREADS = TABLE_THREADS;
16
+ /** @deprecated import { TABLE_TRACES } from '@mastra/core/storage' instead */
17
+ static TABLE_TRACES = TABLE_TRACES;
18
+ hasInit = false;
19
+ constructor({ name }) {
20
+ super({
21
+ component: "STORAGE",
22
+ name
23
+ });
24
+ }
25
+ async __batchInsert({
26
+ tableName,
27
+ records
28
+ }) {
29
+ await this.init();
30
+ return this.batchInsert({ tableName, records });
31
+ }
32
+ async __getThreadById({ threadId }) {
33
+ await this.init();
34
+ return this.getThreadById({ threadId });
35
+ }
36
+ async __getThreadsByResourceId({ resourceId }) {
37
+ await this.init();
38
+ return this.getThreadsByResourceId({ resourceId });
39
+ }
40
+ async __saveThread({ thread }) {
41
+ await this.init();
42
+ return this.saveThread({ thread });
43
+ }
44
+ async __updateThread({
45
+ id,
46
+ title,
47
+ metadata
48
+ }) {
49
+ await this.init();
50
+ return this.updateThread({ id, title, metadata });
51
+ }
52
+ async __deleteThread({ threadId }) {
53
+ await this.init();
54
+ return this.deleteThread({ threadId });
55
+ }
56
+ async __getMessages({ threadId, selectBy, threadConfig }) {
57
+ await this.init();
58
+ return this.getMessages({ threadId, selectBy, threadConfig });
59
+ }
60
+ async __saveMessages({ messages }) {
61
+ await this.init();
62
+ return this.saveMessages({ messages });
63
+ }
64
+ async __getTraces({
65
+ scope,
66
+ page,
67
+ perPage,
68
+ attributes
69
+ }) {
70
+ await this.init();
71
+ return this.getTraces({ scope, page, perPage, attributes });
72
+ }
73
+ async init() {
74
+ if (this.hasInit) {
75
+ return;
76
+ }
77
+ await this.createTable({
78
+ tableName: TABLE_WORKFLOW_SNAPSHOT,
79
+ schema: {
80
+ workflow_name: {
81
+ type: "text"
82
+ },
83
+ run_id: {
84
+ type: "text"
85
+ },
86
+ snapshot: {
87
+ type: "text"
88
+ },
89
+ createdAt: {
90
+ type: "timestamp"
91
+ },
92
+ updatedAt: {
93
+ type: "timestamp"
94
+ }
95
+ }
96
+ });
97
+ await this.createTable({
98
+ tableName: TABLE_EVALS,
99
+ schema: {
100
+ input: {
101
+ type: "text"
102
+ },
103
+ output: {
104
+ type: "text"
105
+ },
106
+ result: {
107
+ type: "jsonb"
108
+ },
109
+ agent_name: {
110
+ type: "text"
111
+ },
112
+ metric_name: {
113
+ type: "text"
114
+ },
115
+ instructions: {
116
+ type: "text"
117
+ },
118
+ test_info: {
119
+ type: "jsonb",
120
+ nullable: true
121
+ },
122
+ global_run_id: {
123
+ type: "text"
124
+ },
125
+ run_id: {
126
+ type: "text"
127
+ },
128
+ created_at: {
129
+ type: "timestamp"
130
+ }
131
+ }
132
+ });
133
+ await this.createTable({
134
+ tableName: TABLE_THREADS,
135
+ schema: {
136
+ id: { type: "text", nullable: false, primaryKey: true },
137
+ resourceId: { type: "text", nullable: false },
138
+ title: { type: "text", nullable: false },
139
+ metadata: { type: "text", nullable: true },
140
+ createdAt: { type: "timestamp", nullable: false },
141
+ updatedAt: { type: "timestamp", nullable: false }
142
+ }
143
+ });
144
+ await this.createTable({
145
+ tableName: TABLE_MESSAGES,
146
+ schema: {
147
+ id: { type: "text", nullable: false, primaryKey: true },
148
+ thread_id: { type: "text", nullable: false },
149
+ content: { type: "text", nullable: false },
150
+ role: { type: "text", nullable: false },
151
+ type: { type: "text", nullable: false },
152
+ createdAt: { type: "timestamp", nullable: false }
153
+ }
154
+ });
155
+ await this.createTable({
156
+ tableName: TABLE_TRACES,
157
+ schema: {
158
+ id: { type: "text", nullable: false, primaryKey: true },
159
+ parentSpanId: { type: "text", nullable: true },
160
+ name: { type: "text", nullable: false },
161
+ traceId: { type: "text", nullable: false },
162
+ scope: { type: "text", nullable: false },
163
+ kind: { type: "integer", nullable: false },
164
+ attributes: { type: "jsonb", nullable: true },
165
+ status: { type: "jsonb", nullable: true },
166
+ events: { type: "jsonb", nullable: true },
167
+ links: { type: "jsonb", nullable: true },
168
+ other: { type: "text", nullable: true },
169
+ startTime: { type: "bigint", nullable: false },
170
+ endTime: { type: "bigint", nullable: false },
171
+ createdAt: { type: "timestamp", nullable: false }
172
+ }
173
+ });
174
+ this.hasInit = true;
175
+ }
176
+ async persistWorkflowSnapshot({
177
+ workflowName,
178
+ runId,
179
+ snapshot
180
+ }) {
181
+ await this.init();
182
+ const data = {
183
+ workflow_name: workflowName,
184
+ run_id: runId,
185
+ snapshot,
186
+ createdAt: /* @__PURE__ */ new Date(),
187
+ updatedAt: /* @__PURE__ */ new Date()
188
+ };
189
+ this.logger.debug("Persisting workflow snapshot", { workflowName, runId, data });
190
+ await this.insert({
191
+ tableName: TABLE_WORKFLOW_SNAPSHOT,
192
+ record: data
193
+ });
194
+ }
195
+ async loadWorkflowSnapshot({
196
+ workflowName,
197
+ runId
198
+ }) {
199
+ if (!this.hasInit) {
200
+ await this.init();
201
+ }
202
+ this.logger.debug("Loading workflow snapshot", { workflowName, runId });
203
+ const d = await this.load({
204
+ tableName: TABLE_WORKFLOW_SNAPSHOT,
205
+ keys: { workflow_name: workflowName, run_id: runId }
206
+ });
207
+ return d ? d.snapshot : null;
208
+ }
209
+ async __getEvalsByAgentName(agentName, type) {
210
+ await this.init();
211
+ return this.getEvalsByAgentName(agentName, type);
212
+ }
213
+ };
214
+ function safelyParseJSON(jsonString) {
215
+ try {
216
+ return JSON.parse(jsonString);
217
+ } catch (e) {
218
+ return {};
219
+ }
220
+ }
221
+ var DefaultStorage = class extends MastraStorage {
222
+ client;
223
+ constructor({ config }) {
224
+ super({ name: `MastraStorageLibSql` });
225
+ this.client = createClient({
226
+ url: this.rewriteDbUrl(config.url),
227
+ authToken: config.authToken
228
+ });
229
+ }
230
+ rewriteDbUrl(url) {
231
+ if (url.startsWith("file:") && !url.startsWith("file:/")) {
232
+ const cwd = process.cwd();
233
+ const relativePath = url.slice("file:".length);
234
+ if (cwd.endsWith(".mastra") || cwd.endsWith(".mastra/")) {
235
+ const baseDir = join(cwd, `..`);
236
+ const fullPath = join(baseDir, relativePath);
237
+ this.logger.debug(
238
+ `Initializing LibSQL db with url ${url} with relative file path from inside .mastra directory. Rewriting relative file url to "file:${fullPath}". This ensures it's outside the .mastra directory. If the db is stored inside .mastra it will be deleted when Mastra re-bundles code.`
239
+ );
240
+ return `file:${fullPath}`;
241
+ }
242
+ }
243
+ return url;
244
+ }
245
+ getCreateTableSQL(tableName, schema) {
246
+ const columns = Object.entries(schema).map(([name, col]) => {
247
+ let type = col.type.toUpperCase();
248
+ if (type === "TEXT") type = "TEXT";
249
+ if (type === "TIMESTAMP") type = "TEXT";
250
+ const nullable = col.nullable ? "" : "NOT NULL";
251
+ const primaryKey = col.primaryKey ? "PRIMARY KEY" : "";
252
+ return `${name} ${type} ${nullable} ${primaryKey}`.trim();
253
+ });
254
+ if (tableName === TABLE_WORKFLOW_SNAPSHOT) {
255
+ const stmnt = `CREATE TABLE IF NOT EXISTS ${tableName} (
256
+ ${columns.join(",\n")},
257
+ PRIMARY KEY (workflow_name, run_id)
258
+ )`;
259
+ return stmnt;
260
+ }
261
+ return `CREATE TABLE IF NOT EXISTS ${tableName} (${columns.join(", ")})`;
262
+ }
263
+ async createTable({
264
+ tableName,
265
+ schema
266
+ }) {
267
+ try {
268
+ this.logger.debug(`Creating database table`, { tableName, operation: "schema init" });
269
+ const sql = this.getCreateTableSQL(tableName, schema);
270
+ await this.client.execute(sql);
271
+ } catch (error) {
272
+ this.logger.error(`Error creating table ${tableName}: ${error}`);
273
+ throw error;
274
+ }
275
+ }
276
+ async clearTable({ tableName }) {
277
+ try {
278
+ await this.client.execute(`DELETE FROM ${tableName}`);
279
+ } catch (e) {
280
+ if (e instanceof Error) {
281
+ this.logger.error(e.message);
282
+ }
283
+ }
284
+ }
285
+ prepareStatement({ tableName, record }) {
286
+ const columns = Object.keys(record);
287
+ const values = Object.values(record).map((v) => {
288
+ if (typeof v === `undefined`) {
289
+ return null;
290
+ }
291
+ return typeof v === "object" ? JSON.stringify(v) : v;
292
+ });
293
+ const placeholders = values.map(() => "?").join(", ");
294
+ return {
295
+ sql: `INSERT OR REPLACE INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`,
296
+ args: values
297
+ };
298
+ }
299
+ async insert({ tableName, record }) {
300
+ try {
301
+ await this.client.execute(this.prepareStatement({ tableName, record }));
302
+ } catch (error) {
303
+ this.logger.error(`Error upserting into table ${tableName}: ${error}`);
304
+ throw error;
305
+ }
306
+ }
307
+ async batchInsert({ tableName, records }) {
308
+ if (records.length === 0) return;
309
+ try {
310
+ const batchStatements = records.map((r) => this.prepareStatement({ tableName, record: r }));
311
+ await this.client.batch(batchStatements, "write");
312
+ } catch (error) {
313
+ this.logger.error(`Error upserting into table ${tableName}: ${error}`);
314
+ throw error;
315
+ }
316
+ }
317
+ async load({ tableName, keys }) {
318
+ const conditions = Object.entries(keys).map(([key]) => `${key} = ?`).join(" AND ");
319
+ const values = Object.values(keys);
320
+ const result = await this.client.execute({
321
+ sql: `SELECT * FROM ${tableName} WHERE ${conditions} LIMIT 1`,
322
+ args: values
323
+ });
324
+ if (!result.rows || result.rows.length === 0) {
325
+ return null;
326
+ }
327
+ const row = result.rows[0];
328
+ const parsed = Object.fromEntries(
329
+ Object.entries(row || {}).map(([k, v]) => {
330
+ try {
331
+ return [k, typeof v === "string" ? JSON.parse(v) : v];
332
+ } catch {
333
+ return [k, v];
334
+ }
335
+ })
336
+ );
337
+ return parsed;
338
+ }
339
+ async getThreadById({ threadId }) {
340
+ const result = await this.load({
341
+ tableName: TABLE_THREADS,
342
+ keys: { id: threadId }
343
+ });
344
+ if (!result) {
345
+ return null;
346
+ }
347
+ return {
348
+ ...result,
349
+ metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
350
+ };
351
+ }
352
+ async getThreadsByResourceId({ resourceId }) {
353
+ const result = await this.client.execute({
354
+ sql: `SELECT * FROM ${TABLE_THREADS} WHERE resourceId = ?`,
355
+ args: [resourceId]
356
+ });
357
+ if (!result.rows) {
358
+ return [];
359
+ }
360
+ return result.rows.map((thread) => ({
361
+ id: thread.id,
362
+ resourceId: thread.resourceId,
363
+ title: thread.title,
364
+ createdAt: thread.createdAt,
365
+ updatedAt: thread.updatedAt,
366
+ metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata
367
+ }));
368
+ }
369
+ async saveThread({ thread }) {
370
+ await this.insert({
371
+ tableName: TABLE_THREADS,
372
+ record: {
373
+ ...thread,
374
+ metadata: JSON.stringify(thread.metadata)
375
+ }
376
+ });
377
+ return thread;
378
+ }
379
+ async updateThread({
380
+ id,
381
+ title,
382
+ metadata
383
+ }) {
384
+ const thread = await this.getThreadById({ threadId: id });
385
+ if (!thread) {
386
+ throw new Error(`Thread ${id} not found`);
387
+ }
388
+ const updatedThread = {
389
+ ...thread,
390
+ title,
391
+ metadata: {
392
+ ...thread.metadata,
393
+ ...metadata
394
+ }
395
+ };
396
+ await this.client.execute({
397
+ sql: `UPDATE ${TABLE_THREADS} SET title = ?, metadata = ? WHERE id = ?`,
398
+ args: [title, JSON.stringify(updatedThread.metadata), id]
399
+ });
400
+ return updatedThread;
401
+ }
402
+ async deleteThread({ threadId }) {
403
+ await this.client.execute({
404
+ sql: `DELETE FROM ${TABLE_THREADS} WHERE id = ?`,
405
+ args: [threadId]
406
+ });
407
+ }
408
+ parseRow(row) {
409
+ let content = row.content;
410
+ try {
411
+ content = JSON.parse(row.content);
412
+ } catch (e) {
413
+ }
414
+ return {
415
+ id: row.id,
416
+ content,
417
+ role: row.role,
418
+ type: row.type,
419
+ createdAt: new Date(row.createdAt),
420
+ threadId: row.thread_id
421
+ };
422
+ }
423
+ async getMessages({ threadId, selectBy }) {
424
+ try {
425
+ const messages = [];
426
+ const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
427
+ if (selectBy?.include?.length) {
428
+ const includeIds = selectBy.include.map((i) => i.id);
429
+ const maxPrev = Math.max(...selectBy.include.map((i) => i.withPreviousMessages || 0));
430
+ const maxNext = Math.max(...selectBy.include.map((i) => i.withNextMessages || 0));
431
+ const includeResult = await this.client.execute({
432
+ sql: `
433
+ WITH numbered_messages AS (
434
+ SELECT
435
+ id,
436
+ content,
437
+ role,
438
+ type,
439
+ "createdAt",
440
+ thread_id,
441
+ ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
442
+ FROM "${TABLE_MESSAGES}"
443
+ WHERE thread_id = ?
444
+ ),
445
+ target_positions AS (
446
+ SELECT row_num as target_pos
447
+ FROM numbered_messages
448
+ WHERE id IN (${includeIds.map(() => "?").join(", ")})
449
+ )
450
+ SELECT DISTINCT m.*
451
+ FROM numbered_messages m
452
+ CROSS JOIN target_positions t
453
+ WHERE m.row_num BETWEEN (t.target_pos - ?) AND (t.target_pos + ?)
454
+ ORDER BY m."createdAt" ASC
455
+ `,
456
+ args: [threadId, ...includeIds, maxPrev, maxNext]
457
+ });
458
+ if (includeResult.rows) {
459
+ messages.push(...includeResult.rows.map((row) => this.parseRow(row)));
460
+ }
461
+ }
462
+ const excludeIds = messages.map((m) => m.id);
463
+ const remainingSql = `
464
+ SELECT
465
+ id,
466
+ content,
467
+ role,
468
+ type,
469
+ "createdAt",
470
+ thread_id
471
+ FROM "${TABLE_MESSAGES}"
472
+ WHERE thread_id = ?
473
+ ${excludeIds.length ? `AND id NOT IN (${excludeIds.map(() => "?").join(", ")})` : ""}
474
+ ORDER BY "createdAt" DESC
475
+ LIMIT ?
476
+ `;
477
+ const remainingArgs = [threadId, ...excludeIds.length ? excludeIds : [], limit];
478
+ const remainingResult = await this.client.execute({
479
+ sql: remainingSql,
480
+ args: remainingArgs
481
+ });
482
+ if (remainingResult.rows) {
483
+ messages.push(...remainingResult.rows.map((row) => this.parseRow(row)));
484
+ }
485
+ messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
486
+ return messages;
487
+ } catch (error) {
488
+ this.logger.error("Error getting messages:", error);
489
+ throw error;
490
+ }
491
+ }
492
+ async saveMessages({ messages }) {
493
+ if (messages.length === 0) return messages;
494
+ const tx = await this.client.transaction("write");
495
+ try {
496
+ const threadId = messages[0]?.threadId;
497
+ if (!threadId) {
498
+ throw new Error("Thread ID is required");
499
+ }
500
+ for (const message of messages) {
501
+ const time = message.createdAt || /* @__PURE__ */ new Date();
502
+ await tx.execute({
503
+ sql: `INSERT INTO ${TABLE_MESSAGES} (id, thread_id, content, role, type, createdAt)
504
+ VALUES (?, ?, ?, ?, ?, ?)`,
505
+ args: [
506
+ message.id,
507
+ threadId,
508
+ typeof message.content === "object" ? JSON.stringify(message.content) : message.content,
509
+ message.role,
510
+ message.type,
511
+ time instanceof Date ? time.toISOString() : time
512
+ ]
513
+ });
514
+ }
515
+ await tx.commit();
516
+ return messages;
517
+ } catch (error) {
518
+ this.logger.error("Failed to save messages in database: " + error?.message);
519
+ await tx.rollback();
520
+ throw error;
521
+ }
522
+ }
523
+ transformEvalRow(row) {
524
+ const resultValue = JSON.parse(row.result);
525
+ const testInfoValue = row.test_info ? JSON.parse(row.test_info) : undefined;
526
+ if (!resultValue || typeof resultValue !== "object" || !("score" in resultValue)) {
527
+ throw new Error(`Invalid MetricResult format: ${JSON.stringify(resultValue)}`);
528
+ }
529
+ return {
530
+ input: row.input,
531
+ output: row.output,
532
+ result: resultValue,
533
+ agentName: row.agent_name,
534
+ metricName: row.metric_name,
535
+ instructions: row.instructions,
536
+ testInfo: testInfoValue,
537
+ globalRunId: row.global_run_id,
538
+ runId: row.run_id,
539
+ createdAt: row.created_at
540
+ };
541
+ }
542
+ async getEvalsByAgentName(agentName, type) {
543
+ try {
544
+ const baseQuery = `SELECT * FROM ${TABLE_EVALS} WHERE agent_name = ?`;
545
+ const typeCondition = type === "test" ? " AND test_info IS NOT NULL AND test_info->>'testPath' IS NOT NULL" : type === "live" ? " AND (test_info IS NULL OR test_info->>'testPath' IS NULL)" : "";
546
+ const result = await this.client.execute({
547
+ sql: `${baseQuery}${typeCondition} ORDER BY created_at DESC`,
548
+ args: [agentName]
549
+ });
550
+ return result.rows?.map((row) => this.transformEvalRow(row)) ?? [];
551
+ } catch (error) {
552
+ if (error instanceof Error && error.message.includes("no such table")) {
553
+ return [];
554
+ }
555
+ this.logger.error("Failed to get evals for the specified agent: " + error?.message);
556
+ throw error;
557
+ }
558
+ }
559
+ // TODO: add types
560
+ async getTraces({
561
+ name,
562
+ scope,
563
+ page,
564
+ perPage,
565
+ attributes
566
+ } = {
567
+ page: 0,
568
+ perPage: 100
569
+ }) {
570
+ const limit = perPage;
571
+ const offset = page * perPage;
572
+ const args = [];
573
+ const conditions = [];
574
+ if (name) {
575
+ conditions.push("name LIKE CONCAT(?, '%')");
576
+ }
577
+ if (scope) {
578
+ conditions.push("scope = ?");
579
+ }
580
+ if (attributes) {
581
+ Object.keys(attributes).forEach((key) => {
582
+ conditions.push(`attributes->>'$.${key}' = ?`);
583
+ });
584
+ }
585
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
586
+ if (name) {
587
+ args.push(name);
588
+ }
589
+ if (scope) {
590
+ args.push(scope);
591
+ }
592
+ if (attributes) {
593
+ for (const [_key, value] of Object.entries(attributes)) {
594
+ args.push(value);
595
+ }
596
+ }
597
+ args.push(limit, offset);
598
+ const result = await this.client.execute({
599
+ sql: `SELECT * FROM ${TABLE_TRACES} ${whereClause} ORDER BY "startTime" DESC LIMIT ? OFFSET ?`,
600
+ args
601
+ });
602
+ if (!result.rows) {
603
+ return [];
604
+ }
605
+ return result.rows.map((row) => ({
606
+ id: row.id,
607
+ parentSpanId: row.parentSpanId,
608
+ traceId: row.traceId,
609
+ name: row.name,
610
+ scope: row.scope,
611
+ kind: row.kind,
612
+ status: safelyParseJSON(row.status),
613
+ events: safelyParseJSON(row.events),
614
+ links: safelyParseJSON(row.links),
615
+ attributes: safelyParseJSON(row.attributes),
616
+ startTime: row.startTime,
617
+ endTime: row.endTime,
618
+ other: safelyParseJSON(row.other),
619
+ createdAt: row.createdAt
620
+ }));
621
+ }
622
+ };
623
+
624
+ export { DefaultStorage, MastraStorage };
@@ -0,0 +1,31 @@
1
+ import { executeHook } from './chunk-MLWGYRJR.js';
2
+
3
+ // src/eval/evaluation.ts
4
+ async function evaluate({
5
+ agentName,
6
+ input,
7
+ metric,
8
+ output,
9
+ runId,
10
+ globalRunId,
11
+ testInfo,
12
+ instructions
13
+ }) {
14
+ const runIdToUse = runId || crypto.randomUUID();
15
+ const metricResult = await metric.measure(input.toString(), output);
16
+ const traceObject = {
17
+ input: input.toString(),
18
+ output,
19
+ result: metricResult,
20
+ agentName,
21
+ metricName: metric.constructor.name,
22
+ instructions,
23
+ globalRunId,
24
+ runId: runIdToUse,
25
+ testInfo
26
+ };
27
+ executeHook("onEvaluation" /* ON_EVALUATION */, traceObject);
28
+ return metricResult;
29
+ }
30
+
31
+ export { evaluate };