@mastra/clickhouse 0.0.0-switch-to-core-20250424015131 → 0.0.0-vector-query-sources-20250516172905
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +281 -2
- package/dist/_tsup-dts-rollup.d.cts +15 -13
- package/dist/_tsup-dts-rollup.d.ts +15 -13
- package/dist/index.cjs +93 -21
- package/dist/index.js +93 -21
- package/package.json +5 -5
- package/src/storage/index.test.ts +229 -45
- package/src/storage/index.ts +122 -34
package/src/storage/index.ts
CHANGED
|
@@ -11,7 +11,14 @@ import {
|
|
|
11
11
|
TABLE_TRACES,
|
|
12
12
|
TABLE_WORKFLOW_SNAPSHOT,
|
|
13
13
|
} from '@mastra/core/storage';
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
EvalRow,
|
|
16
|
+
StorageColumn,
|
|
17
|
+
StorageGetMessagesArg,
|
|
18
|
+
TABLE_NAMES,
|
|
19
|
+
WorkflowRun,
|
|
20
|
+
WorkflowRuns,
|
|
21
|
+
} from '@mastra/core/storage';
|
|
15
22
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
16
23
|
|
|
17
24
|
function safelyParseJSON(jsonString: string): any {
|
|
@@ -203,6 +210,8 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
203
210
|
perPage,
|
|
204
211
|
attributes,
|
|
205
212
|
filters,
|
|
213
|
+
fromDate,
|
|
214
|
+
toDate,
|
|
206
215
|
}: {
|
|
207
216
|
name?: string;
|
|
208
217
|
scope?: string;
|
|
@@ -210,6 +219,8 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
210
219
|
perPage: number;
|
|
211
220
|
attributes?: Record<string, string>;
|
|
212
221
|
filters?: Record<string, any>;
|
|
222
|
+
fromDate?: Date;
|
|
223
|
+
toDate?: Date;
|
|
213
224
|
}): Promise<any[]> {
|
|
214
225
|
const limit = perPage;
|
|
215
226
|
const offset = page * perPage;
|
|
@@ -241,6 +252,16 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
241
252
|
});
|
|
242
253
|
}
|
|
243
254
|
|
|
255
|
+
if (fromDate) {
|
|
256
|
+
conditions.push(`createdAt >= {var_from_date:DateTime64(3)}`);
|
|
257
|
+
args.var_from_date = fromDate.getTime() / 1000; // Convert to Unix timestamp
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (toDate) {
|
|
261
|
+
conditions.push(`createdAt <= {var_to_date:DateTime64(3)}`);
|
|
262
|
+
args.var_to_date = toDate.getTime() / 1000; // Convert to Unix timestamp
|
|
263
|
+
}
|
|
264
|
+
|
|
244
265
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
245
266
|
|
|
246
267
|
const result = await this.db.query({
|
|
@@ -316,7 +337,6 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
316
337
|
${['id String'].concat(columns)}
|
|
317
338
|
)
|
|
318
339
|
ENGINE = ${TABLE_ENGINES[tableName]}
|
|
319
|
-
PARTITION BY "createdAt"
|
|
320
340
|
PRIMARY KEY (createdAt, run_id, workflow_name)
|
|
321
341
|
ORDER BY (createdAt, run_id, workflow_name)
|
|
322
342
|
${rowTtl ? `TTL toDateTime(${rowTtl.ttlKey ?? 'createdAt'}) + INTERVAL ${rowTtl.interval} ${rowTtl.unit}` : ''}
|
|
@@ -327,7 +347,6 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
327
347
|
${columns}
|
|
328
348
|
)
|
|
329
349
|
ENGINE = ${TABLE_ENGINES[tableName]}
|
|
330
|
-
PARTITION BY "createdAt"
|
|
331
350
|
PRIMARY KEY (createdAt, ${tableName === TABLE_EVALS ? 'run_id' : 'id'})
|
|
332
351
|
ORDER BY (createdAt, ${tableName === TABLE_EVALS ? 'run_id' : 'id'})
|
|
333
352
|
${this.ttl?.[tableName]?.row ? `TTL toDateTime(createdAt) + INTERVAL ${this.ttl[tableName].row.interval} ${this.ttl[tableName].row.unit}` : ''}
|
|
@@ -606,7 +625,7 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
606
625
|
try {
|
|
607
626
|
// First delete all messages associated with this thread
|
|
608
627
|
await this.db.command({
|
|
609
|
-
query: `DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id =
|
|
628
|
+
query: `DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id = {var_thread_id:String};`,
|
|
610
629
|
query_params: { var_thread_id: threadId },
|
|
611
630
|
clickhouse_settings: {
|
|
612
631
|
output_format_json_quote_64bit_integers: 0,
|
|
@@ -627,7 +646,7 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
627
646
|
}
|
|
628
647
|
}
|
|
629
648
|
|
|
630
|
-
async getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T> {
|
|
649
|
+
async getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]> {
|
|
631
650
|
try {
|
|
632
651
|
const messages: any[] = [];
|
|
633
652
|
const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
|
|
@@ -734,7 +753,7 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
734
753
|
}
|
|
735
754
|
});
|
|
736
755
|
|
|
737
|
-
return messages as T;
|
|
756
|
+
return messages as T[];
|
|
738
757
|
} catch (error) {
|
|
739
758
|
console.error('Error getting messages:', error);
|
|
740
759
|
throw error;
|
|
@@ -856,28 +875,42 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
856
875
|
}
|
|
857
876
|
}
|
|
858
877
|
|
|
878
|
+
private parseWorkflowRun(row: any): WorkflowRun {
|
|
879
|
+
let parsedSnapshot: WorkflowRunState | string = row.snapshot as string;
|
|
880
|
+
if (typeof parsedSnapshot === 'string') {
|
|
881
|
+
try {
|
|
882
|
+
parsedSnapshot = JSON.parse(row.snapshot as string) as WorkflowRunState;
|
|
883
|
+
} catch (e) {
|
|
884
|
+
// If parsing fails, return the raw snapshot string
|
|
885
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
return {
|
|
890
|
+
workflowName: row.workflow_name,
|
|
891
|
+
runId: row.run_id,
|
|
892
|
+
snapshot: parsedSnapshot,
|
|
893
|
+
createdAt: new Date(row.createdAt),
|
|
894
|
+
updatedAt: new Date(row.updatedAt),
|
|
895
|
+
resourceId: row.resourceId,
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
|
|
859
899
|
async getWorkflowRuns({
|
|
860
900
|
workflowName,
|
|
861
901
|
fromDate,
|
|
862
902
|
toDate,
|
|
863
903
|
limit,
|
|
864
904
|
offset,
|
|
905
|
+
resourceId,
|
|
865
906
|
}: {
|
|
866
907
|
workflowName?: string;
|
|
867
908
|
fromDate?: Date;
|
|
868
909
|
toDate?: Date;
|
|
869
910
|
limit?: number;
|
|
870
911
|
offset?: number;
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
workflowName: string;
|
|
874
|
-
runId: string;
|
|
875
|
-
snapshot: WorkflowRunState | string;
|
|
876
|
-
createdAt: Date;
|
|
877
|
-
updatedAt: Date;
|
|
878
|
-
}>;
|
|
879
|
-
total: number;
|
|
880
|
-
}> {
|
|
912
|
+
resourceId?: string;
|
|
913
|
+
} = {}): Promise<WorkflowRuns> {
|
|
881
914
|
try {
|
|
882
915
|
const conditions: string[] = [];
|
|
883
916
|
const values: Record<string, any> = {};
|
|
@@ -887,6 +920,16 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
887
920
|
values.var_workflow_name = workflowName;
|
|
888
921
|
}
|
|
889
922
|
|
|
923
|
+
if (resourceId) {
|
|
924
|
+
const hasResourceId = await this.hasColumn(TABLE_WORKFLOW_SNAPSHOT, 'resourceId');
|
|
925
|
+
if (hasResourceId) {
|
|
926
|
+
conditions.push(`resourceId = {var_resourceId:String}`);
|
|
927
|
+
values.var_resourceId = resourceId;
|
|
928
|
+
} else {
|
|
929
|
+
console.warn(`[${TABLE_WORKFLOW_SNAPSHOT}] resourceId column not found. Skipping resourceId filter.`);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
890
933
|
if (fromDate) {
|
|
891
934
|
conditions.push(`createdAt >= {var_from_date:DateTime64(3)}`);
|
|
892
935
|
values.var_from_date = fromDate.getTime() / 1000; // Convert to Unix timestamp
|
|
@@ -921,7 +964,8 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
921
964
|
run_id,
|
|
922
965
|
snapshot,
|
|
923
966
|
toDateTime64(createdAt, 3) as createdAt,
|
|
924
|
-
toDateTime64(updatedAt, 3) as updatedAt
|
|
967
|
+
toDateTime64(updatedAt, 3) as updatedAt,
|
|
968
|
+
resourceId
|
|
925
969
|
FROM ${TABLE_WORKFLOW_SNAPSHOT} ${TABLE_ENGINES[TABLE_WORKFLOW_SNAPSHOT].startsWith('ReplacingMergeTree') ? 'FINAL' : ''}
|
|
926
970
|
${whereClause}
|
|
927
971
|
ORDER BY createdAt DESC
|
|
@@ -935,23 +979,7 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
935
979
|
const resultJson = await result.json();
|
|
936
980
|
const rows = resultJson as any[];
|
|
937
981
|
const runs = rows.map(row => {
|
|
938
|
-
|
|
939
|
-
if (typeof parsedSnapshot === 'string') {
|
|
940
|
-
try {
|
|
941
|
-
parsedSnapshot = JSON.parse(row.snapshot) as WorkflowRunState;
|
|
942
|
-
} catch (e) {
|
|
943
|
-
// If parsing fails, return the raw snapshot string
|
|
944
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
return {
|
|
949
|
-
workflowName: row.workflow_name,
|
|
950
|
-
runId: row.run_id,
|
|
951
|
-
snapshot: parsedSnapshot,
|
|
952
|
-
createdAt: new Date(row.createdAt),
|
|
953
|
-
updatedAt: new Date(row.updatedAt),
|
|
954
|
-
};
|
|
982
|
+
return this.parseWorkflowRun(row);
|
|
955
983
|
});
|
|
956
984
|
|
|
957
985
|
// Use runs.length as total when not paginating
|
|
@@ -962,6 +990,66 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
962
990
|
}
|
|
963
991
|
}
|
|
964
992
|
|
|
993
|
+
async getWorkflowRunById({
|
|
994
|
+
runId,
|
|
995
|
+
workflowName,
|
|
996
|
+
}: {
|
|
997
|
+
runId: string;
|
|
998
|
+
workflowName?: string;
|
|
999
|
+
}): Promise<WorkflowRun | null> {
|
|
1000
|
+
try {
|
|
1001
|
+
const conditions: string[] = [];
|
|
1002
|
+
const values: Record<string, any> = {};
|
|
1003
|
+
|
|
1004
|
+
if (runId) {
|
|
1005
|
+
conditions.push(`run_id = {var_runId:String}`);
|
|
1006
|
+
values.var_runId = runId;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
if (workflowName) {
|
|
1010
|
+
conditions.push(`workflow_name = {var_workflow_name:String}`);
|
|
1011
|
+
values.var_workflow_name = workflowName;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
1015
|
+
|
|
1016
|
+
// Get results
|
|
1017
|
+
const result = await this.db.query({
|
|
1018
|
+
query: `
|
|
1019
|
+
SELECT
|
|
1020
|
+
workflow_name,
|
|
1021
|
+
run_id,
|
|
1022
|
+
snapshot,
|
|
1023
|
+
toDateTime64(createdAt, 3) as createdAt,
|
|
1024
|
+
toDateTime64(updatedAt, 3) as updatedAt,
|
|
1025
|
+
resourceId
|
|
1026
|
+
FROM ${TABLE_WORKFLOW_SNAPSHOT} ${TABLE_ENGINES[TABLE_WORKFLOW_SNAPSHOT].startsWith('ReplacingMergeTree') ? 'FINAL' : ''}
|
|
1027
|
+
${whereClause}
|
|
1028
|
+
`,
|
|
1029
|
+
query_params: values,
|
|
1030
|
+
format: 'JSONEachRow',
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
const resultJson = await result.json();
|
|
1034
|
+
if (!Array.isArray(resultJson) || resultJson.length === 0) {
|
|
1035
|
+
return null;
|
|
1036
|
+
}
|
|
1037
|
+
return this.parseWorkflowRun(resultJson[0]);
|
|
1038
|
+
} catch (error) {
|
|
1039
|
+
console.error('Error getting workflow run by ID:', error);
|
|
1040
|
+
throw error;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
private async hasColumn(table: string, column: string): Promise<boolean> {
|
|
1045
|
+
const result = await this.db.query({
|
|
1046
|
+
query: `DESCRIBE TABLE ${table}`,
|
|
1047
|
+
format: 'JSONEachRow',
|
|
1048
|
+
});
|
|
1049
|
+
const columns = (await result.json()) as { name: string }[];
|
|
1050
|
+
return columns.some(c => c.name === column);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
965
1053
|
async close(): Promise<void> {
|
|
966
1054
|
await this.db.close();
|
|
967
1055
|
}
|