@mastra/clickhouse 0.0.0-vnextWorkflows-20250422142014 → 0.0.0-workflow-deno-20250616130925
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +23 -0
- package/CHANGELOG.md +521 -2
- package/dist/_tsup-dts-rollup.d.cts +57 -16
- package/dist/_tsup-dts-rollup.d.ts +57 -16
- package/dist/index.cjs +220 -46
- package/dist/index.js +220 -46
- package/package.json +14 -10
- package/src/storage/index.test.ts +470 -118
- package/src/storage/index.ts +279 -58
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { ClickHouseClient } from '@clickhouse/client';
|
|
2
2
|
import type { EvalRow } from '@mastra/core/storage';
|
|
3
|
+
import type { MastraMessageV1 } from '@mastra/core/memory';
|
|
4
|
+
import type { MastraMessageV2 } from '@mastra/core/memory';
|
|
3
5
|
import { MastraStorage } from '@mastra/core/storage';
|
|
4
|
-
import type {
|
|
6
|
+
import type { PaginationInfo } from '@mastra/core/storage';
|
|
5
7
|
import type { StorageColumn } from '@mastra/core/storage';
|
|
6
8
|
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
9
|
+
import type { StorageGetTracesArg } from '@mastra/core/storage';
|
|
7
10
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
8
11
|
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
9
12
|
import { TABLE_SCHEMAS } from '@mastra/core/storage';
|
|
13
|
+
import type { Trace } from '@mastra/core/telemetry';
|
|
14
|
+
import type { WorkflowRun } from '@mastra/core/storage';
|
|
15
|
+
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
10
16
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
11
17
|
|
|
12
18
|
declare type ClickhouseConfig = {
|
|
@@ -43,13 +49,15 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
43
49
|
tableName: TABLE_NAMES;
|
|
44
50
|
records: Record<string, any>[];
|
|
45
51
|
}): Promise<void>;
|
|
46
|
-
getTraces({ name, scope, page, perPage, attributes, filters, }: {
|
|
52
|
+
getTraces({ name, scope, page, perPage, attributes, filters, fromDate, toDate, }: {
|
|
47
53
|
name?: string;
|
|
48
54
|
scope?: string;
|
|
49
55
|
page: number;
|
|
50
56
|
perPage: number;
|
|
51
57
|
attributes?: Record<string, string>;
|
|
52
58
|
filters?: Record<string, any>;
|
|
59
|
+
fromDate?: Date;
|
|
60
|
+
toDate?: Date;
|
|
53
61
|
}): Promise<any[]>;
|
|
54
62
|
optimizeTable({ tableName }: {
|
|
55
63
|
tableName: TABLE_NAMES;
|
|
@@ -61,6 +69,18 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
61
69
|
tableName: TABLE_NAMES;
|
|
62
70
|
schema: Record<string, StorageColumn>;
|
|
63
71
|
}): Promise<void>;
|
|
72
|
+
protected getSqlType(type: StorageColumn['type']): string;
|
|
73
|
+
/**
|
|
74
|
+
* Alters table schema to add columns if they don't exist
|
|
75
|
+
* @param tableName Name of the table
|
|
76
|
+
* @param schema Schema of the table
|
|
77
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
78
|
+
*/
|
|
79
|
+
alterTable({ tableName, schema, ifNotExists, }: {
|
|
80
|
+
tableName: TABLE_NAMES;
|
|
81
|
+
schema: Record<string, StorageColumn>;
|
|
82
|
+
ifNotExists: string[];
|
|
83
|
+
}): Promise<void>;
|
|
64
84
|
clearTable({ tableName }: {
|
|
65
85
|
tableName: TABLE_NAMES;
|
|
66
86
|
}): Promise<void>;
|
|
@@ -89,10 +109,20 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
89
109
|
deleteThread({ threadId }: {
|
|
90
110
|
threadId: string;
|
|
91
111
|
}): Promise<void>;
|
|
92
|
-
getMessages
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
getMessages(args: StorageGetMessagesArg & {
|
|
113
|
+
format?: 'v1';
|
|
114
|
+
}): Promise<MastraMessageV1[]>;
|
|
115
|
+
getMessages(args: StorageGetMessagesArg & {
|
|
116
|
+
format: 'v2';
|
|
117
|
+
}): Promise<MastraMessageV2[]>;
|
|
118
|
+
saveMessages(args: {
|
|
119
|
+
messages: MastraMessageV1[];
|
|
120
|
+
format?: undefined | 'v1';
|
|
121
|
+
}): Promise<MastraMessageV1[]>;
|
|
122
|
+
saveMessages(args: {
|
|
123
|
+
messages: MastraMessageV2[];
|
|
124
|
+
format: 'v2';
|
|
125
|
+
}): Promise<MastraMessageV2[]>;
|
|
96
126
|
persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
|
|
97
127
|
workflowName: string;
|
|
98
128
|
runId: string;
|
|
@@ -102,21 +132,32 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
102
132
|
workflowName: string;
|
|
103
133
|
runId: string;
|
|
104
134
|
}): Promise<WorkflowRunState | null>;
|
|
105
|
-
|
|
135
|
+
private parseWorkflowRun;
|
|
136
|
+
getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId, }?: {
|
|
106
137
|
workflowName?: string;
|
|
107
138
|
fromDate?: Date;
|
|
108
139
|
toDate?: Date;
|
|
109
140
|
limit?: number;
|
|
110
141
|
offset?: number;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
142
|
+
resourceId?: string;
|
|
143
|
+
}): Promise<WorkflowRuns>;
|
|
144
|
+
getWorkflowRunById({ runId, workflowName, }: {
|
|
145
|
+
runId: string;
|
|
146
|
+
workflowName?: string;
|
|
147
|
+
}): Promise<WorkflowRun | null>;
|
|
148
|
+
private hasColumn;
|
|
149
|
+
getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & {
|
|
150
|
+
traces: Trace[];
|
|
151
|
+
}>;
|
|
152
|
+
getThreadsByResourceIdPaginated(_args: {
|
|
153
|
+
resourceId: string;
|
|
154
|
+
page?: number;
|
|
155
|
+
perPage?: number;
|
|
156
|
+
}): Promise<PaginationInfo & {
|
|
157
|
+
threads: StorageThreadType[];
|
|
158
|
+
}>;
|
|
159
|
+
getMessagesPaginated(_args: StorageGetMessagesArg): Promise<PaginationInfo & {
|
|
160
|
+
messages: MastraMessageV1[] | MastraMessageV2[];
|
|
120
161
|
}>;
|
|
121
162
|
close(): Promise<void>;
|
|
122
163
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var client = require('@clickhouse/client');
|
|
4
|
+
var agent = require('@mastra/core/agent');
|
|
4
5
|
var storage = require('@mastra/core/storage');
|
|
5
6
|
|
|
6
7
|
// src/storage/index.ts
|
|
@@ -138,7 +139,9 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
138
139
|
page,
|
|
139
140
|
perPage,
|
|
140
141
|
attributes,
|
|
141
|
-
filters
|
|
142
|
+
filters,
|
|
143
|
+
fromDate,
|
|
144
|
+
toDate
|
|
142
145
|
}) {
|
|
143
146
|
const limit = perPage;
|
|
144
147
|
const offset = page * perPage;
|
|
@@ -166,6 +169,14 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
166
169
|
args[`var_col_${key}`] = value;
|
|
167
170
|
});
|
|
168
171
|
}
|
|
172
|
+
if (fromDate) {
|
|
173
|
+
conditions.push(`createdAt >= {var_from_date:DateTime64(3)}`);
|
|
174
|
+
args.var_from_date = fromDate.getTime() / 1e3;
|
|
175
|
+
}
|
|
176
|
+
if (toDate) {
|
|
177
|
+
conditions.push(`createdAt <= {var_to_date:DateTime64(3)}`);
|
|
178
|
+
args.var_to_date = toDate.getTime() / 1e3;
|
|
179
|
+
}
|
|
169
180
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
170
181
|
const result = await this.db.query({
|
|
171
182
|
query: `SELECT *, toDateTime64(createdAt, 3) as createdAt FROM ${storage.TABLE_TRACES} ${whereClause} ORDER BY "createdAt" DESC LIMIT ${limit} OFFSET ${offset}`,
|
|
@@ -227,7 +238,6 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
227
238
|
${["id String"].concat(columns)}
|
|
228
239
|
)
|
|
229
240
|
ENGINE = ${TABLE_ENGINES[tableName]}
|
|
230
|
-
PARTITION BY "createdAt"
|
|
231
241
|
PRIMARY KEY (createdAt, run_id, workflow_name)
|
|
232
242
|
ORDER BY (createdAt, run_id, workflow_name)
|
|
233
243
|
${rowTtl ? `TTL toDateTime(${rowTtl.ttlKey ?? "createdAt"}) + INTERVAL ${rowTtl.interval} ${rowTtl.unit}` : ""}
|
|
@@ -237,7 +247,6 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
237
247
|
${columns}
|
|
238
248
|
)
|
|
239
249
|
ENGINE = ${TABLE_ENGINES[tableName]}
|
|
240
|
-
PARTITION BY "createdAt"
|
|
241
250
|
PRIMARY KEY (createdAt, ${tableName === storage.TABLE_EVALS ? "run_id" : "id"})
|
|
242
251
|
ORDER BY (createdAt, ${tableName === storage.TABLE_EVALS ? "run_id" : "id"})
|
|
243
252
|
${this.ttl?.[tableName]?.row ? `TTL toDateTime(createdAt) + INTERVAL ${this.ttl[tableName].row.interval} ${this.ttl[tableName].row.unit}` : ""}
|
|
@@ -258,6 +267,61 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
258
267
|
throw error;
|
|
259
268
|
}
|
|
260
269
|
}
|
|
270
|
+
getSqlType(type) {
|
|
271
|
+
switch (type) {
|
|
272
|
+
case "text":
|
|
273
|
+
return "String";
|
|
274
|
+
case "timestamp":
|
|
275
|
+
return "DateTime64(3)";
|
|
276
|
+
case "integer":
|
|
277
|
+
case "bigint":
|
|
278
|
+
return "Int64";
|
|
279
|
+
case "jsonb":
|
|
280
|
+
return "String";
|
|
281
|
+
default:
|
|
282
|
+
return super.getSqlType(type);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Alters table schema to add columns if they don't exist
|
|
287
|
+
* @param tableName Name of the table
|
|
288
|
+
* @param schema Schema of the table
|
|
289
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
290
|
+
*/
|
|
291
|
+
async alterTable({
|
|
292
|
+
tableName,
|
|
293
|
+
schema,
|
|
294
|
+
ifNotExists
|
|
295
|
+
}) {
|
|
296
|
+
try {
|
|
297
|
+
const describeSql = `DESCRIBE TABLE ${tableName}`;
|
|
298
|
+
const result = await this.db.query({
|
|
299
|
+
query: describeSql
|
|
300
|
+
});
|
|
301
|
+
const rows = await result.json();
|
|
302
|
+
const existingColumnNames = new Set(rows.data.map((row) => row.name.toLowerCase()));
|
|
303
|
+
for (const columnName of ifNotExists) {
|
|
304
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
305
|
+
const columnDef = schema[columnName];
|
|
306
|
+
let sqlType = this.getSqlType(columnDef.type);
|
|
307
|
+
if (columnDef.nullable !== false) {
|
|
308
|
+
sqlType = `Nullable(${sqlType})`;
|
|
309
|
+
}
|
|
310
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
311
|
+
const alterSql = `ALTER TABLE ${tableName} ADD COLUMN IF NOT EXISTS "${columnName}" ${sqlType} ${defaultValue}`.trim();
|
|
312
|
+
await this.db.query({
|
|
313
|
+
query: alterSql
|
|
314
|
+
});
|
|
315
|
+
this.logger?.debug?.(`Added column ${columnName} to table ${tableName}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
this.logger?.error?.(
|
|
320
|
+
`Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`
|
|
321
|
+
);
|
|
322
|
+
throw new Error(`Failed to alter table ${tableName}: ${error}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
261
325
|
async clearTable({ tableName }) {
|
|
262
326
|
try {
|
|
263
327
|
await this.db.query({
|
|
@@ -459,15 +523,18 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
459
523
|
};
|
|
460
524
|
await this.db.insert({
|
|
461
525
|
table: storage.TABLE_THREADS,
|
|
526
|
+
format: "JSONEachRow",
|
|
462
527
|
values: [
|
|
463
528
|
{
|
|
464
|
-
|
|
529
|
+
id: updatedThread.id,
|
|
530
|
+
resourceId: updatedThread.resourceId,
|
|
531
|
+
title: updatedThread.title,
|
|
532
|
+
metadata: updatedThread.metadata,
|
|
533
|
+
createdAt: updatedThread.createdAt,
|
|
465
534
|
updatedAt: updatedThread.updatedAt.toISOString()
|
|
466
535
|
}
|
|
467
536
|
],
|
|
468
|
-
format: "JSONEachRow",
|
|
469
537
|
clickhouse_settings: {
|
|
470
|
-
// Allows to insert serialized JS Dates (such as '2023-12-06T10:54:48.000Z')
|
|
471
538
|
date_time_input_format: "best_effort",
|
|
472
539
|
use_client_time_zone: 1,
|
|
473
540
|
output_format_json_quote_64bit_integers: 0
|
|
@@ -482,7 +549,7 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
482
549
|
async deleteThread({ threadId }) {
|
|
483
550
|
try {
|
|
484
551
|
await this.db.command({
|
|
485
|
-
query: `DELETE FROM "${storage.TABLE_MESSAGES}" WHERE thread_id =
|
|
552
|
+
query: `DELETE FROM "${storage.TABLE_MESSAGES}" WHERE thread_id = {var_thread_id:String};`,
|
|
486
553
|
query_params: { var_thread_id: threadId },
|
|
487
554
|
clickhouse_settings: {
|
|
488
555
|
output_format_json_quote_64bit_integers: 0
|
|
@@ -500,7 +567,12 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
500
567
|
throw error;
|
|
501
568
|
}
|
|
502
569
|
}
|
|
503
|
-
async getMessages({
|
|
570
|
+
async getMessages({
|
|
571
|
+
threadId,
|
|
572
|
+
resourceId,
|
|
573
|
+
selectBy,
|
|
574
|
+
format
|
|
575
|
+
}) {
|
|
504
576
|
try {
|
|
505
577
|
const messages = [];
|
|
506
578
|
const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
|
|
@@ -596,16 +668,20 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
596
668
|
}
|
|
597
669
|
}
|
|
598
670
|
});
|
|
599
|
-
|
|
671
|
+
const list = new agent.MessageList({ threadId, resourceId }).add(messages, "memory");
|
|
672
|
+
if (format === `v2`) return list.get.all.v2();
|
|
673
|
+
return list.get.all.v1();
|
|
600
674
|
} catch (error) {
|
|
601
675
|
console.error("Error getting messages:", error);
|
|
602
676
|
throw error;
|
|
603
677
|
}
|
|
604
678
|
}
|
|
605
|
-
async saveMessages(
|
|
679
|
+
async saveMessages(args) {
|
|
680
|
+
const { messages, format = "v1" } = args;
|
|
606
681
|
if (messages.length === 0) return messages;
|
|
607
682
|
try {
|
|
608
683
|
const threadId = messages[0]?.threadId;
|
|
684
|
+
const resourceId = messages[0]?.resourceId;
|
|
609
685
|
if (!threadId) {
|
|
610
686
|
throw new Error("Thread ID is required");
|
|
611
687
|
}
|
|
@@ -613,25 +689,50 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
613
689
|
if (!thread) {
|
|
614
690
|
throw new Error(`Thread ${threadId} not found`);
|
|
615
691
|
}
|
|
616
|
-
await
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
692
|
+
await Promise.all([
|
|
693
|
+
// Insert messages
|
|
694
|
+
this.db.insert({
|
|
695
|
+
table: storage.TABLE_MESSAGES,
|
|
696
|
+
format: "JSONEachRow",
|
|
697
|
+
values: messages.map((message) => ({
|
|
698
|
+
id: message.id,
|
|
699
|
+
thread_id: threadId,
|
|
700
|
+
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
701
|
+
createdAt: message.createdAt.toISOString(),
|
|
702
|
+
role: message.role,
|
|
703
|
+
type: message.type || "v2"
|
|
704
|
+
})),
|
|
705
|
+
clickhouse_settings: {
|
|
706
|
+
// Allows to insert serialized JS Dates (such as '2023-12-06T10:54:48.000Z')
|
|
707
|
+
date_time_input_format: "best_effort",
|
|
708
|
+
use_client_time_zone: 1,
|
|
709
|
+
output_format_json_quote_64bit_integers: 0
|
|
710
|
+
}
|
|
711
|
+
}),
|
|
712
|
+
// Update thread's updatedAt timestamp
|
|
713
|
+
this.db.insert({
|
|
714
|
+
table: storage.TABLE_THREADS,
|
|
715
|
+
format: "JSONEachRow",
|
|
716
|
+
values: [
|
|
717
|
+
{
|
|
718
|
+
id: thread.id,
|
|
719
|
+
resourceId: thread.resourceId,
|
|
720
|
+
title: thread.title,
|
|
721
|
+
metadata: thread.metadata,
|
|
722
|
+
createdAt: thread.createdAt,
|
|
723
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
724
|
+
}
|
|
725
|
+
],
|
|
726
|
+
clickhouse_settings: {
|
|
727
|
+
date_time_input_format: "best_effort",
|
|
728
|
+
use_client_time_zone: 1,
|
|
729
|
+
output_format_json_quote_64bit_integers: 0
|
|
730
|
+
}
|
|
731
|
+
})
|
|
732
|
+
]);
|
|
733
|
+
const list = new agent.MessageList({ threadId, resourceId }).add(messages, "memory");
|
|
734
|
+
if (format === `v2`) return list.get.all.v2();
|
|
735
|
+
return list.get.all.v1();
|
|
635
736
|
} catch (error) {
|
|
636
737
|
console.error("Error saving messages:", error);
|
|
637
738
|
throw error;
|
|
@@ -696,12 +797,31 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
696
797
|
throw error;
|
|
697
798
|
}
|
|
698
799
|
}
|
|
800
|
+
parseWorkflowRun(row) {
|
|
801
|
+
let parsedSnapshot = row.snapshot;
|
|
802
|
+
if (typeof parsedSnapshot === "string") {
|
|
803
|
+
try {
|
|
804
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
805
|
+
} catch (e) {
|
|
806
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return {
|
|
810
|
+
workflowName: row.workflow_name,
|
|
811
|
+
runId: row.run_id,
|
|
812
|
+
snapshot: parsedSnapshot,
|
|
813
|
+
createdAt: new Date(row.createdAt),
|
|
814
|
+
updatedAt: new Date(row.updatedAt),
|
|
815
|
+
resourceId: row.resourceId
|
|
816
|
+
};
|
|
817
|
+
}
|
|
699
818
|
async getWorkflowRuns({
|
|
700
819
|
workflowName,
|
|
701
820
|
fromDate,
|
|
702
821
|
toDate,
|
|
703
822
|
limit,
|
|
704
|
-
offset
|
|
823
|
+
offset,
|
|
824
|
+
resourceId
|
|
705
825
|
} = {}) {
|
|
706
826
|
try {
|
|
707
827
|
const conditions = [];
|
|
@@ -710,6 +830,15 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
710
830
|
conditions.push(`workflow_name = {var_workflow_name:String}`);
|
|
711
831
|
values.var_workflow_name = workflowName;
|
|
712
832
|
}
|
|
833
|
+
if (resourceId) {
|
|
834
|
+
const hasResourceId = await this.hasColumn(storage.TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
835
|
+
if (hasResourceId) {
|
|
836
|
+
conditions.push(`resourceId = {var_resourceId:String}`);
|
|
837
|
+
values.var_resourceId = resourceId;
|
|
838
|
+
} else {
|
|
839
|
+
console.warn(`[${storage.TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
713
842
|
if (fromDate) {
|
|
714
843
|
conditions.push(`createdAt >= {var_from_date:DateTime64(3)}`);
|
|
715
844
|
values.var_from_date = fromDate.getTime() / 1e3;
|
|
@@ -738,7 +867,8 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
738
867
|
run_id,
|
|
739
868
|
snapshot,
|
|
740
869
|
toDateTime64(createdAt, 3) as createdAt,
|
|
741
|
-
toDateTime64(updatedAt, 3) as updatedAt
|
|
870
|
+
toDateTime64(updatedAt, 3) as updatedAt,
|
|
871
|
+
resourceId
|
|
742
872
|
FROM ${storage.TABLE_WORKFLOW_SNAPSHOT} ${TABLE_ENGINES[storage.TABLE_WORKFLOW_SNAPSHOT].startsWith("ReplacingMergeTree") ? "FINAL" : ""}
|
|
743
873
|
${whereClause}
|
|
744
874
|
ORDER BY createdAt DESC
|
|
@@ -751,21 +881,7 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
751
881
|
const resultJson = await result.json();
|
|
752
882
|
const rows = resultJson;
|
|
753
883
|
const runs = rows.map((row) => {
|
|
754
|
-
|
|
755
|
-
if (typeof parsedSnapshot === "string") {
|
|
756
|
-
try {
|
|
757
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
758
|
-
} catch (e) {
|
|
759
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
return {
|
|
763
|
-
workflowName: row.workflow_name,
|
|
764
|
-
runId: row.run_id,
|
|
765
|
-
snapshot: parsedSnapshot,
|
|
766
|
-
createdAt: new Date(row.createdAt),
|
|
767
|
-
updatedAt: new Date(row.updatedAt)
|
|
768
|
-
};
|
|
884
|
+
return this.parseWorkflowRun(row);
|
|
769
885
|
});
|
|
770
886
|
return { runs, total: total || runs.length };
|
|
771
887
|
} catch (error) {
|
|
@@ -773,6 +889,64 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
773
889
|
throw error;
|
|
774
890
|
}
|
|
775
891
|
}
|
|
892
|
+
async getWorkflowRunById({
|
|
893
|
+
runId,
|
|
894
|
+
workflowName
|
|
895
|
+
}) {
|
|
896
|
+
try {
|
|
897
|
+
const conditions = [];
|
|
898
|
+
const values = {};
|
|
899
|
+
if (runId) {
|
|
900
|
+
conditions.push(`run_id = {var_runId:String}`);
|
|
901
|
+
values.var_runId = runId;
|
|
902
|
+
}
|
|
903
|
+
if (workflowName) {
|
|
904
|
+
conditions.push(`workflow_name = {var_workflow_name:String}`);
|
|
905
|
+
values.var_workflow_name = workflowName;
|
|
906
|
+
}
|
|
907
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
908
|
+
const result = await this.db.query({
|
|
909
|
+
query: `
|
|
910
|
+
SELECT
|
|
911
|
+
workflow_name,
|
|
912
|
+
run_id,
|
|
913
|
+
snapshot,
|
|
914
|
+
toDateTime64(createdAt, 3) as createdAt,
|
|
915
|
+
toDateTime64(updatedAt, 3) as updatedAt,
|
|
916
|
+
resourceId
|
|
917
|
+
FROM ${storage.TABLE_WORKFLOW_SNAPSHOT} ${TABLE_ENGINES[storage.TABLE_WORKFLOW_SNAPSHOT].startsWith("ReplacingMergeTree") ? "FINAL" : ""}
|
|
918
|
+
${whereClause}
|
|
919
|
+
`,
|
|
920
|
+
query_params: values,
|
|
921
|
+
format: "JSONEachRow"
|
|
922
|
+
});
|
|
923
|
+
const resultJson = await result.json();
|
|
924
|
+
if (!Array.isArray(resultJson) || resultJson.length === 0) {
|
|
925
|
+
return null;
|
|
926
|
+
}
|
|
927
|
+
return this.parseWorkflowRun(resultJson[0]);
|
|
928
|
+
} catch (error) {
|
|
929
|
+
console.error("Error getting workflow run by ID:", error);
|
|
930
|
+
throw error;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
async hasColumn(table, column) {
|
|
934
|
+
const result = await this.db.query({
|
|
935
|
+
query: `DESCRIBE TABLE ${table}`,
|
|
936
|
+
format: "JSONEachRow"
|
|
937
|
+
});
|
|
938
|
+
const columns = await result.json();
|
|
939
|
+
return columns.some((c) => c.name === column);
|
|
940
|
+
}
|
|
941
|
+
async getTracesPaginated(_args) {
|
|
942
|
+
throw new Error("Method not implemented.");
|
|
943
|
+
}
|
|
944
|
+
async getThreadsByResourceIdPaginated(_args) {
|
|
945
|
+
throw new Error("Method not implemented.");
|
|
946
|
+
}
|
|
947
|
+
async getMessagesPaginated(_args) {
|
|
948
|
+
throw new Error("Method not implemented.");
|
|
949
|
+
}
|
|
776
950
|
async close() {
|
|
777
951
|
await this.db.close();
|
|
778
952
|
}
|