@mastra/clickhouse 0.0.0-vnext-inngest-20250508122351 → 0.0.0-vnextAgentNetwork-20250602134426

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 CHANGED
@@ -1,15 +1,205 @@
1
1
  # @mastra/clickhouse
2
2
 
3
- ## 0.0.0-vnext-inngest-20250508122351
3
+ ## 0.0.0-vnextAgentNetwork-20250602134426
4
4
 
5
5
  ### Patch Changes
6
6
 
7
+ - e5dc18d: Added a backwards compatible layer to begin storing/retrieving UIMessages in storage instead of CoreMessages
8
+ - c5bf1ce: Add backwards compat code for new MessageList in storage
9
+ - f0d559f: Fix peerdeps for alpha channel
10
+ - Updated dependencies [ee77e78]
11
+ - Updated dependencies [592a2db]
12
+ - Updated dependencies [e5dc18d]
13
+ - Updated dependencies [ab5adbe]
14
+ - Updated dependencies [1e8bb40]
15
+ - Updated dependencies [195c428]
16
+ - Updated dependencies [f73e11b]
17
+ - Updated dependencies [c5bf1ce]
18
+ - Updated dependencies [12b7002]
19
+ - Updated dependencies [2901125]
20
+ - @mastra/core@0.0.0-vnextAgentNetwork-20250602134426
21
+
22
+ ## 0.10.1-alpha.2
23
+
24
+ ### Patch Changes
25
+
26
+ - c5bf1ce: Add backwards compat code for new MessageList in storage
27
+ - Updated dependencies [c5bf1ce]
28
+ - Updated dependencies [12b7002]
29
+ - @mastra/core@0.10.2-alpha.4
30
+
31
+ ## 0.10.1-alpha.1
32
+
33
+ ### Patch Changes
34
+
35
+ - f0d559f: Fix peerdeps for alpha channel
36
+ - Updated dependencies [1e8bb40]
37
+ - @mastra/core@0.10.2-alpha.2
38
+
39
+ ## 0.10.1-alpha.0
40
+
41
+ ### Patch Changes
42
+
43
+ - e5dc18d: Added a backwards compatible layer to begin storing/retrieving UIMessages in storage instead of CoreMessages
44
+ - Updated dependencies [592a2db]
45
+ - Updated dependencies [e5dc18d]
46
+ - @mastra/core@0.10.2-alpha.0
47
+
48
+ ## 0.10.0
49
+
50
+ ### Minor Changes
51
+
52
+ - 83da932: Move @mastra/core to peerdeps
53
+
54
+ ### Patch Changes
55
+
56
+ - b3a3d63: BREAKING: Make vnext workflow the default worklow, and old workflow legacy_workflow
57
+ - eabdcd9: [MASTRA-3451] SQL Injection Protection
58
+ - Updated dependencies [b3a3d63]
59
+ - Updated dependencies [344f453]
60
+ - Updated dependencies [0a3ae6d]
61
+ - Updated dependencies [95911be]
62
+ - Updated dependencies [f53a6ac]
63
+ - Updated dependencies [5eb5a99]
64
+ - Updated dependencies [7e632c5]
65
+ - Updated dependencies [1e9fbfa]
66
+ - Updated dependencies [eabdcd9]
67
+ - Updated dependencies [90be034]
68
+ - Updated dependencies [99f050a]
69
+ - Updated dependencies [d0ee3c6]
70
+ - Updated dependencies [b2ae5aa]
71
+ - Updated dependencies [23f258c]
72
+ - Updated dependencies [a7292b0]
73
+ - Updated dependencies [0dcb9f0]
74
+ - Updated dependencies [2672a05]
75
+ - @mastra/core@0.10.0
76
+
77
+ ## 0.4.0-alpha.1
78
+
79
+ ### Minor Changes
80
+
81
+ - 83da932: Move @mastra/core to peerdeps
82
+
83
+ ### Patch Changes
84
+
85
+ - b3a3d63: BREAKING: Make vnext workflow the default worklow, and old workflow legacy_workflow
86
+ - Updated dependencies [b3a3d63]
87
+ - Updated dependencies [344f453]
88
+ - Updated dependencies [0a3ae6d]
89
+ - Updated dependencies [95911be]
90
+ - Updated dependencies [5eb5a99]
91
+ - Updated dependencies [7e632c5]
92
+ - Updated dependencies [1e9fbfa]
93
+ - Updated dependencies [b2ae5aa]
94
+ - Updated dependencies [a7292b0]
95
+ - Updated dependencies [0dcb9f0]
96
+ - @mastra/core@0.10.0-alpha.1
97
+
98
+ ## 0.3.5-alpha.0
99
+
100
+ ### Patch Changes
101
+
102
+ - eabdcd9: [MASTRA-3451] SQL Injection Protection
103
+ - Updated dependencies [f53a6ac]
104
+ - Updated dependencies [eabdcd9]
105
+ - Updated dependencies [90be034]
106
+ - Updated dependencies [99f050a]
107
+ - Updated dependencies [d0ee3c6]
108
+ - Updated dependencies [23f258c]
109
+ - Updated dependencies [2672a05]
110
+ - @mastra/core@0.9.5-alpha.0
111
+
112
+ ## 0.3.4
113
+
114
+ ### Patch Changes
115
+
116
+ - 302a9f0: fix: do not partition clickhouse trace table
117
+ - Updated dependencies [396be50]
118
+ - Updated dependencies [ab80e7e]
119
+ - Updated dependencies [c3bd795]
120
+ - Updated dependencies [da082f8]
121
+ - Updated dependencies [a5810ce]
122
+ - Updated dependencies [3e9c131]
123
+ - Updated dependencies [3171b5b]
124
+ - Updated dependencies [973e5ac]
125
+ - Updated dependencies [daf942f]
126
+ - Updated dependencies [0b8b868]
127
+ - Updated dependencies [9e1eff5]
128
+ - Updated dependencies [6fa1ad1]
129
+ - Updated dependencies [c28d7a0]
130
+ - Updated dependencies [edf1e88]
131
+ - @mastra/core@0.9.4
132
+
133
+ ## 0.3.4-alpha.4
134
+
135
+ ### Patch Changes
136
+
137
+ - Updated dependencies [3e9c131]
138
+ - @mastra/core@0.9.4-alpha.4
139
+
140
+ ## 0.3.4-alpha.3
141
+
142
+ ### Patch Changes
143
+
144
+ - 302a9f0: fix: do not partition clickhouse trace table
145
+ - Updated dependencies [396be50]
146
+ - Updated dependencies [c3bd795]
147
+ - Updated dependencies [da082f8]
148
+ - Updated dependencies [a5810ce]
149
+ - @mastra/core@0.9.4-alpha.3
150
+
151
+ ## 0.3.4-alpha.2
152
+
153
+ ### Patch Changes
154
+
155
+ - Updated dependencies [3171b5b]
156
+ - Updated dependencies [973e5ac]
157
+ - Updated dependencies [9e1eff5]
158
+ - @mastra/core@0.9.4-alpha.2
159
+
160
+ ## 0.3.4-alpha.1
161
+
162
+ ### Patch Changes
163
+
164
+ - Updated dependencies [ab80e7e]
165
+ - Updated dependencies [6fa1ad1]
166
+ - Updated dependencies [c28d7a0]
167
+ - Updated dependencies [edf1e88]
168
+ - @mastra/core@0.9.4-alpha.1
169
+
170
+ ## 0.3.4-alpha.0
171
+
172
+ ### Patch Changes
173
+
174
+ - Updated dependencies [daf942f]
175
+ - Updated dependencies [0b8b868]
176
+ - @mastra/core@0.9.4-alpha.0
177
+
178
+ ## 0.3.3
179
+
180
+ ### Patch Changes
181
+
182
+ - Updated dependencies [e450778]
183
+ - Updated dependencies [8902157]
184
+ - Updated dependencies [ca0dc88]
7
185
  - Updated dependencies [526c570]
186
+ - Updated dependencies [d7a6a33]
8
187
  - Updated dependencies [9cd1a46]
9
188
  - Updated dependencies [b5d2de0]
10
189
  - Updated dependencies [644f8ad]
11
190
  - Updated dependencies [70dbf51]
12
- - @mastra/core@0.0.0-vnext-inngest-20250508122351
191
+ - @mastra/core@0.9.3
192
+
193
+ ## 0.3.3-alpha.1
194
+
195
+ ### Patch Changes
196
+
197
+ - Updated dependencies [e450778]
198
+ - Updated dependencies [8902157]
199
+ - Updated dependencies [ca0dc88]
200
+ - Updated dependencies [9cd1a46]
201
+ - Updated dependencies [70dbf51]
202
+ - @mastra/core@0.9.3-alpha.1
13
203
 
14
204
  ## 0.3.3-alpha.0
15
205
 
@@ -1,7 +1,8 @@
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/agent';
3
5
  import { MastraStorage } from '@mastra/core/storage';
4
- import type { MessageType } from '@mastra/core/memory';
5
6
  import type { StorageColumn } from '@mastra/core/storage';
6
7
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
7
8
  import type { StorageThreadType } from '@mastra/core/memory';
@@ -93,10 +94,20 @@ declare class ClickhouseStore extends MastraStorage {
93
94
  deleteThread({ threadId }: {
94
95
  threadId: string;
95
96
  }): Promise<void>;
96
- getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]>;
97
- saveMessages({ messages }: {
98
- messages: MessageType[];
99
- }): Promise<MessageType[]>;
97
+ getMessages(args: StorageGetMessagesArg & {
98
+ format?: 'v1';
99
+ }): Promise<MastraMessageV1[]>;
100
+ getMessages(args: StorageGetMessagesArg & {
101
+ format: 'v2';
102
+ }): Promise<MastraMessageV2[]>;
103
+ saveMessages(args: {
104
+ messages: MastraMessageV1[];
105
+ format?: undefined | 'v1';
106
+ }): Promise<MastraMessageV1[]>;
107
+ saveMessages(args: {
108
+ messages: MastraMessageV2[];
109
+ format: 'v2';
110
+ }): Promise<MastraMessageV2[]>;
100
111
  persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
101
112
  workflowName: string;
102
113
  runId: string;
@@ -1,7 +1,8 @@
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/agent';
3
5
  import { MastraStorage } from '@mastra/core/storage';
4
- import type { MessageType } from '@mastra/core/memory';
5
6
  import type { StorageColumn } from '@mastra/core/storage';
6
7
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
7
8
  import type { StorageThreadType } from '@mastra/core/memory';
@@ -93,10 +94,20 @@ declare class ClickhouseStore extends MastraStorage {
93
94
  deleteThread({ threadId }: {
94
95
  threadId: string;
95
96
  }): Promise<void>;
96
- getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]>;
97
- saveMessages({ messages }: {
98
- messages: MessageType[];
99
- }): Promise<MessageType[]>;
97
+ getMessages(args: StorageGetMessagesArg & {
98
+ format?: 'v1';
99
+ }): Promise<MastraMessageV1[]>;
100
+ getMessages(args: StorageGetMessagesArg & {
101
+ format: 'v2';
102
+ }): Promise<MastraMessageV2[]>;
103
+ saveMessages(args: {
104
+ messages: MastraMessageV1[];
105
+ format?: undefined | 'v1';
106
+ }): Promise<MastraMessageV1[]>;
107
+ saveMessages(args: {
108
+ messages: MastraMessageV2[];
109
+ format: 'v2';
110
+ }): Promise<MastraMessageV2[]>;
100
111
  persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
101
112
  workflowName: string;
102
113
  runId: string;
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
@@ -237,7 +238,6 @@ var ClickhouseStore = class extends storage.MastraStorage {
237
238
  ${["id String"].concat(columns)}
238
239
  )
239
240
  ENGINE = ${TABLE_ENGINES[tableName]}
240
- PARTITION BY "createdAt"
241
241
  PRIMARY KEY (createdAt, run_id, workflow_name)
242
242
  ORDER BY (createdAt, run_id, workflow_name)
243
243
  ${rowTtl ? `TTL toDateTime(${rowTtl.ttlKey ?? "createdAt"}) + INTERVAL ${rowTtl.interval} ${rowTtl.unit}` : ""}
@@ -247,7 +247,6 @@ var ClickhouseStore = class extends storage.MastraStorage {
247
247
  ${columns}
248
248
  )
249
249
  ENGINE = ${TABLE_ENGINES[tableName]}
250
- PARTITION BY "createdAt"
251
250
  PRIMARY KEY (createdAt, ${tableName === storage.TABLE_EVALS ? "run_id" : "id"})
252
251
  ORDER BY (createdAt, ${tableName === storage.TABLE_EVALS ? "run_id" : "id"})
253
252
  ${this.ttl?.[tableName]?.row ? `TTL toDateTime(createdAt) + INTERVAL ${this.ttl[tableName].row.interval} ${this.ttl[tableName].row.unit}` : ""}
@@ -492,7 +491,7 @@ var ClickhouseStore = class extends storage.MastraStorage {
492
491
  async deleteThread({ threadId }) {
493
492
  try {
494
493
  await this.db.command({
495
- query: `DELETE FROM "${storage.TABLE_MESSAGES}" WHERE thread_id = '${threadId}';`,
494
+ query: `DELETE FROM "${storage.TABLE_MESSAGES}" WHERE thread_id = {var_thread_id:String};`,
496
495
  query_params: { var_thread_id: threadId },
497
496
  clickhouse_settings: {
498
497
  output_format_json_quote_64bit_integers: 0
@@ -510,7 +509,12 @@ var ClickhouseStore = class extends storage.MastraStorage {
510
509
  throw error;
511
510
  }
512
511
  }
513
- async getMessages({ threadId, selectBy }) {
512
+ async getMessages({
513
+ threadId,
514
+ resourceId,
515
+ selectBy,
516
+ format
517
+ }) {
514
518
  try {
515
519
  const messages = [];
516
520
  const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
@@ -606,16 +610,20 @@ var ClickhouseStore = class extends storage.MastraStorage {
606
610
  }
607
611
  }
608
612
  });
609
- return messages;
613
+ const list = new agent.MessageList({ threadId, resourceId }).add(messages, "memory");
614
+ if (format === `v2`) return list.get.all.v2();
615
+ return list.get.all.v1();
610
616
  } catch (error) {
611
617
  console.error("Error getting messages:", error);
612
618
  throw error;
613
619
  }
614
620
  }
615
- async saveMessages({ messages }) {
621
+ async saveMessages(args) {
622
+ const { messages, format = "v1" } = args;
616
623
  if (messages.length === 0) return messages;
617
624
  try {
618
625
  const threadId = messages[0]?.threadId;
626
+ const resourceId = messages[0]?.resourceId;
619
627
  if (!threadId) {
620
628
  throw new Error("Thread ID is required");
621
629
  }
@@ -632,7 +640,7 @@ var ClickhouseStore = class extends storage.MastraStorage {
632
640
  content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
633
641
  createdAt: message.createdAt.toISOString(),
634
642
  role: message.role,
635
- type: message.type
643
+ type: message.type || "v2"
636
644
  })),
637
645
  clickhouse_settings: {
638
646
  // Allows to insert serialized JS Dates (such as '2023-12-06T10:54:48.000Z')
@@ -641,7 +649,9 @@ var ClickhouseStore = class extends storage.MastraStorage {
641
649
  output_format_json_quote_64bit_integers: 0
642
650
  }
643
651
  });
644
- return messages;
652
+ const list = new agent.MessageList({ threadId, resourceId }).add(messages, "memory");
653
+ if (format === `v2`) return list.get.all.v2();
654
+ return list.get.all.v1();
645
655
  } catch (error) {
646
656
  console.error("Error saving messages:", error);
647
657
  throw error;
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createClient } from '@clickhouse/client';
2
+ import { MessageList } from '@mastra/core/agent';
2
3
  import { TABLE_EVALS, TABLE_THREADS, TABLE_TRACES, TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, MastraStorage, TABLE_SCHEMAS } from '@mastra/core/storage';
3
4
 
4
5
  // src/storage/index.ts
@@ -235,7 +236,6 @@ var ClickhouseStore = class extends MastraStorage {
235
236
  ${["id String"].concat(columns)}
236
237
  )
237
238
  ENGINE = ${TABLE_ENGINES[tableName]}
238
- PARTITION BY "createdAt"
239
239
  PRIMARY KEY (createdAt, run_id, workflow_name)
240
240
  ORDER BY (createdAt, run_id, workflow_name)
241
241
  ${rowTtl ? `TTL toDateTime(${rowTtl.ttlKey ?? "createdAt"}) + INTERVAL ${rowTtl.interval} ${rowTtl.unit}` : ""}
@@ -245,7 +245,6 @@ var ClickhouseStore = class extends MastraStorage {
245
245
  ${columns}
246
246
  )
247
247
  ENGINE = ${TABLE_ENGINES[tableName]}
248
- PARTITION BY "createdAt"
249
248
  PRIMARY KEY (createdAt, ${tableName === TABLE_EVALS ? "run_id" : "id"})
250
249
  ORDER BY (createdAt, ${tableName === TABLE_EVALS ? "run_id" : "id"})
251
250
  ${this.ttl?.[tableName]?.row ? `TTL toDateTime(createdAt) + INTERVAL ${this.ttl[tableName].row.interval} ${this.ttl[tableName].row.unit}` : ""}
@@ -490,7 +489,7 @@ var ClickhouseStore = class extends MastraStorage {
490
489
  async deleteThread({ threadId }) {
491
490
  try {
492
491
  await this.db.command({
493
- query: `DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id = '${threadId}';`,
492
+ query: `DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id = {var_thread_id:String};`,
494
493
  query_params: { var_thread_id: threadId },
495
494
  clickhouse_settings: {
496
495
  output_format_json_quote_64bit_integers: 0
@@ -508,7 +507,12 @@ var ClickhouseStore = class extends MastraStorage {
508
507
  throw error;
509
508
  }
510
509
  }
511
- async getMessages({ threadId, selectBy }) {
510
+ async getMessages({
511
+ threadId,
512
+ resourceId,
513
+ selectBy,
514
+ format
515
+ }) {
512
516
  try {
513
517
  const messages = [];
514
518
  const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
@@ -604,16 +608,20 @@ var ClickhouseStore = class extends MastraStorage {
604
608
  }
605
609
  }
606
610
  });
607
- return messages;
611
+ const list = new MessageList({ threadId, resourceId }).add(messages, "memory");
612
+ if (format === `v2`) return list.get.all.v2();
613
+ return list.get.all.v1();
608
614
  } catch (error) {
609
615
  console.error("Error getting messages:", error);
610
616
  throw error;
611
617
  }
612
618
  }
613
- async saveMessages({ messages }) {
619
+ async saveMessages(args) {
620
+ const { messages, format = "v1" } = args;
614
621
  if (messages.length === 0) return messages;
615
622
  try {
616
623
  const threadId = messages[0]?.threadId;
624
+ const resourceId = messages[0]?.resourceId;
617
625
  if (!threadId) {
618
626
  throw new Error("Thread ID is required");
619
627
  }
@@ -630,7 +638,7 @@ var ClickhouseStore = class extends MastraStorage {
630
638
  content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
631
639
  createdAt: message.createdAt.toISOString(),
632
640
  role: message.role,
633
- type: message.type
641
+ type: message.type || "v2"
634
642
  })),
635
643
  clickhouse_settings: {
636
644
  // Allows to insert serialized JS Dates (such as '2023-12-06T10:54:48.000Z')
@@ -639,7 +647,9 @@ var ClickhouseStore = class extends MastraStorage {
639
647
  output_format_json_quote_64bit_integers: 0
640
648
  }
641
649
  });
642
- return messages;
650
+ const list = new MessageList({ threadId, resourceId }).add(messages, "memory");
651
+ if (format === `v2`) return list.get.all.v2();
652
+ return list.get.all.v1();
643
653
  } catch (error) {
644
654
  console.error("Error saving messages:", error);
645
655
  throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/clickhouse",
3
- "version": "0.0.0-vnext-inngest-20250508122351",
3
+ "version": "0.0.0-vnextAgentNetwork-20250602134426",
4
4
  "description": "Clickhouse provider for Mastra - includes db storage capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,8 +20,7 @@
20
20
  },
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@clickhouse/client": "^1.11.0",
24
- "@mastra/core": "0.0.0-vnext-inngest-20250508122351"
23
+ "@clickhouse/client": "^1.11.0"
25
24
  },
26
25
  "devDependencies": {
27
26
  "@microsoft/api-extractor": "^7.52.5",
@@ -30,7 +29,11 @@
30
29
  "tsup": "^8.4.0",
31
30
  "typescript": "^5.8.2",
32
31
  "vitest": "^3.1.2",
33
- "@internal/lint": "0.0.0-vnext-inngest-20250508122351"
32
+ "@internal/lint": "0.0.0-vnextAgentNetwork-20250602134426",
33
+ "@mastra/core": "0.0.0-vnextAgentNetwork-20250602134426"
34
+ },
35
+ "peerDependencies": {
36
+ "@mastra/core": "^0.10.0-alpha.0"
34
37
  },
35
38
  "scripts": {
36
39
  "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
@@ -1,6 +1,5 @@
1
1
  import { randomUUID } from 'crypto';
2
- import type { WorkflowRunState } from '@mastra/core';
3
- import type { MessageType } from '@mastra/core/memory';
2
+ import type { MastraMessageV1, WorkflowRunState } from '@mastra/core';
4
3
  import { TABLE_THREADS, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
5
4
  import { describe, it, expect, beforeAll, beforeEach, afterAll, vi, afterEach } from 'vitest';
6
5
 
@@ -28,20 +27,27 @@ const TEST_CONFIG: ClickhouseConfig = {
28
27
  // Sample test data factory functions
29
28
  const createSampleThread = () => ({
30
29
  id: `thread-${randomUUID()}`,
31
- resourceId: `resource-${randomUUID()}`,
30
+ resourceId: `clickhouse-test`,
32
31
  title: 'Test Thread',
33
32
  createdAt: new Date(),
34
33
  updatedAt: new Date(),
35
34
  metadata: { key: 'value' },
36
35
  });
37
36
 
38
- const createSampleMessage = (threadId: string, createdAt: Date = new Date()): MessageType => ({
37
+ let role = `user`;
38
+ const getRole = () => {
39
+ if (role === `user`) role = `assistant`;
40
+ else role = `user`;
41
+ return role as 'user' | 'assistant';
42
+ };
43
+
44
+ const createSampleMessage = (threadId: string, createdAt: Date = new Date()): MastraMessageV1 => ({
39
45
  id: `msg-${randomUUID()}`,
40
- resourceId: `resource-${randomUUID()}`,
41
- role: 'user',
46
+ resourceId: `clickhouse-test`,
47
+ role: getRole(),
42
48
  type: 'text',
43
49
  threadId,
44
- content: [{ type: 'text', text: 'Hello' }] as MessageType['content'],
50
+ content: 'Hello',
45
51
  createdAt,
46
52
  });
47
53
 
@@ -60,10 +66,7 @@ const createSampleEval = () => ({
60
66
  createdAt: new Date(),
61
67
  });
62
68
 
63
- const createSampleWorkflowSnapshot = (
64
- status: WorkflowRunState['context']['steps'][string]['status'],
65
- createdAt?: Date,
66
- ) => {
69
+ const createSampleWorkflowSnapshot = (status: WorkflowRunState['context']['steps']['status'], createdAt?: Date) => {
67
70
  const runId = `run-${randomUUID()}`;
68
71
  const stepId = `step-${randomUUID()}`;
69
72
  const timestamp = createdAt || new Date();
@@ -71,21 +74,21 @@ const createSampleWorkflowSnapshot = (
71
74
  result: { success: true },
72
75
  value: {},
73
76
  context: {
74
- steps: {
75
- [stepId]: {
76
- status,
77
- payload: {},
78
- error: undefined,
79
- },
77
+ [stepId]: {
78
+ status,
79
+ payload: {},
80
+ error: undefined,
81
+ startedAt: timestamp.getTime(),
82
+ endedAt: new Date(timestamp.getTime() + 15000).getTime(),
80
83
  },
81
- triggerData: {},
82
- attempts: {},
84
+ input: {},
83
85
  },
86
+ serializedStepGraph: [],
84
87
  activePaths: [],
85
88
  suspendedPaths: {},
86
89
  runId,
87
90
  timestamp: timestamp.getTime(),
88
- };
91
+ } as unknown as WorkflowRunState;
89
92
  return { snapshot, runId, stepId };
90
93
  };
91
94
 
@@ -93,7 +96,7 @@ const checkWorkflowSnapshot = (snapshot: WorkflowRunState | string, stepId: stri
93
96
  if (typeof snapshot === 'string') {
94
97
  throw new Error('Expected WorkflowRunState, got string');
95
98
  }
96
- expect(snapshot.context?.steps[stepId]?.status).toBe(status);
99
+ expect(snapshot.context?.[stepId]?.status).toBe(status);
97
100
  };
98
101
 
99
102
  describe('ClickhouseStore', () => {
@@ -215,24 +218,27 @@ describe('ClickhouseStore', () => {
215
218
  const thread = createSampleThread();
216
219
  await store.saveThread({ thread });
217
220
 
218
- const messages: MessageType[] = [
221
+ const messages: MastraMessageV1[] = [
219
222
  {
220
223
  ...createSampleMessage(thread.id, new Date(Date.now() - 1000 * 3)),
221
224
  content: [{ type: 'text', text: 'First' }],
225
+ role: 'user',
222
226
  },
223
227
  {
224
228
  ...createSampleMessage(thread.id, new Date(Date.now() - 1000 * 2)),
225
229
  content: [{ type: 'text', text: 'Second' }],
230
+ role: 'assistant',
226
231
  },
227
232
  {
228
233
  ...createSampleMessage(thread.id, new Date(Date.now() - 1000 * 1)),
229
234
  content: [{ type: 'text', text: 'Third' }],
235
+ role: 'user',
230
236
  },
231
237
  ];
232
238
 
233
239
  await store.saveMessages({ messages });
234
240
 
235
- const retrievedMessages = await store.getMessages<MessageType>({ threadId: thread.id });
241
+ const retrievedMessages = await store.getMessages({ threadId: thread.id });
236
242
  expect(retrievedMessages).toHaveLength(3);
237
243
 
238
244
  // Verify order is maintained
@@ -371,17 +377,14 @@ describe('ClickhouseStore', () => {
371
377
  const snapshot = {
372
378
  status: 'running',
373
379
  context: {
374
- steps: {},
375
- stepResults: {},
376
- attempts: {},
377
- triggerData: { type: 'manual' },
380
+ input: { type: 'manual' },
378
381
  },
379
382
  value: {},
380
383
  activePaths: [],
381
384
  suspendedPaths: {},
382
385
  runId,
383
386
  timestamp: new Date().getTime(),
384
- };
387
+ } as unknown as WorkflowRunState;
385
388
 
386
389
  await store.persistWorkflowSnapshot({
387
390
  workflowName,
@@ -412,17 +415,14 @@ describe('ClickhouseStore', () => {
412
415
  const initialSnapshot = {
413
416
  status: 'running',
414
417
  context: {
415
- steps: {},
416
- stepResults: {},
417
- attempts: {},
418
- triggerData: { type: 'manual' },
418
+ input: { type: 'manual' },
419
419
  },
420
420
  value: {},
421
421
  activePaths: [],
422
422
  suspendedPaths: {},
423
423
  runId,
424
424
  timestamp: new Date().getTime(),
425
- };
425
+ } as unknown as WorkflowRunState;
426
426
 
427
427
  await store.persistWorkflowSnapshot({
428
428
  workflowName,
@@ -433,19 +433,15 @@ describe('ClickhouseStore', () => {
433
433
  const updatedSnapshot = {
434
434
  status: 'completed',
435
435
  context: {
436
- steps: {},
437
- stepResults: {
438
- 'step-1': { status: 'success', result: { data: 'test' } },
439
- },
440
- attempts: { 'step-1': 1 },
441
- triggerData: { type: 'manual' },
436
+ input: { type: 'manual' },
437
+ 'step-1': { status: 'success', result: { data: 'test' } },
442
438
  },
443
439
  value: {},
444
440
  activePaths: [],
445
441
  suspendedPaths: {},
446
442
  runId,
447
443
  timestamp: new Date().getTime(),
448
- };
444
+ } as unknown as WorkflowRunState;
449
445
 
450
446
  await store.persistWorkflowSnapshot({
451
447
  workflowName,
@@ -467,25 +463,21 @@ describe('ClickhouseStore', () => {
467
463
  const complexSnapshot = {
468
464
  value: { currentState: 'running' },
469
465
  context: {
470
- stepResults: {
471
- 'step-1': {
472
- status: 'success',
473
- result: {
474
- nestedData: {
475
- array: [1, 2, 3],
476
- object: { key: 'value' },
477
- date: new Date().toISOString(),
478
- },
466
+ 'step-1': {
467
+ status: 'success',
468
+ output: {
469
+ nestedData: {
470
+ array: [1, 2, 3],
471
+ object: { key: 'value' },
472
+ date: new Date().toISOString(),
479
473
  },
480
474
  },
481
- 'step-2': {
482
- status: 'waiting',
483
- dependencies: ['step-3', 'step-4'],
484
- },
485
475
  },
486
- steps: {},
487
- attempts: { 'step-1': 1, 'step-2': 0 },
488
- triggerData: {
476
+ 'step-2': {
477
+ status: 'waiting',
478
+ dependencies: ['step-3', 'step-4'],
479
+ },
480
+ input: {
489
481
  type: 'scheduled',
490
482
  metadata: {
491
483
  schedule: '0 0 * * *',
@@ -508,7 +500,7 @@ describe('ClickhouseStore', () => {
508
500
  suspendedPaths: {},
509
501
  runId: runId,
510
502
  timestamp: Date.now(),
511
- };
503
+ } as unknown as WorkflowRunState;
512
504
 
513
505
  await store.persistWorkflowSnapshot({
514
506
  workflowName,
@@ -540,7 +532,7 @@ describe('ClickhouseStore', () => {
540
532
  const workflowName2 = 'default_test_2';
541
533
 
542
534
  const { snapshot: workflow1, runId: runId1, stepId: stepId1 } = createSampleWorkflowSnapshot('success');
543
- const { snapshot: workflow2, runId: runId2, stepId: stepId2 } = createSampleWorkflowSnapshot('waiting');
535
+ const { snapshot: workflow2, runId: runId2, stepId: stepId2 } = createSampleWorkflowSnapshot('suspended');
544
536
 
545
537
  await store.persistWorkflowSnapshot({
546
538
  workflowName: workflowName1,
@@ -561,7 +553,7 @@ describe('ClickhouseStore', () => {
561
553
  expect(runs[1]!.workflowName).toBe(workflowName1);
562
554
  const firstSnapshot = runs[0]!.snapshot;
563
555
  const secondSnapshot = runs[1]!.snapshot;
564
- checkWorkflowSnapshot(firstSnapshot, stepId2, 'waiting');
556
+ checkWorkflowSnapshot(firstSnapshot, stepId2, 'suspended');
565
557
  checkWorkflowSnapshot(secondSnapshot, stepId1, 'success');
566
558
  });
567
559
 
@@ -603,8 +595,8 @@ describe('ClickhouseStore', () => {
603
595
  const workflowName3 = 'date_test_3';
604
596
 
605
597
  const { snapshot: workflow1, runId: runId1 } = createSampleWorkflowSnapshot('success');
606
- const { snapshot: workflow2, runId: runId2, stepId: stepId2 } = createSampleWorkflowSnapshot('waiting');
607
- const { snapshot: workflow3, runId: runId3, stepId: stepId3 } = createSampleWorkflowSnapshot('skipped');
598
+ const { snapshot: workflow2, runId: runId2, stepId: stepId2 } = createSampleWorkflowSnapshot('suspended');
599
+ const { snapshot: workflow3, runId: runId3, stepId: stepId3 } = createSampleWorkflowSnapshot('failed');
608
600
 
609
601
  await store.insert({
610
602
  tableName: TABLE_WORKFLOW_SNAPSHOT,
@@ -647,8 +639,8 @@ describe('ClickhouseStore', () => {
647
639
  expect(runs[1]!.workflowName).toBe(workflowName2);
648
640
  const firstSnapshot = runs[0]!.snapshot;
649
641
  const secondSnapshot = runs[1]!.snapshot;
650
- checkWorkflowSnapshot(firstSnapshot, stepId3, 'skipped');
651
- checkWorkflowSnapshot(secondSnapshot, stepId2, 'waiting');
642
+ checkWorkflowSnapshot(firstSnapshot, stepId3, 'failed');
643
+ checkWorkflowSnapshot(secondSnapshot, stepId2, 'suspended');
652
644
  });
653
645
 
654
646
  it('handles pagination', async () => {
@@ -657,8 +649,8 @@ describe('ClickhouseStore', () => {
657
649
  const workflowName3 = 'page_test_3';
658
650
 
659
651
  const { snapshot: workflow1, runId: runId1, stepId: stepId1 } = createSampleWorkflowSnapshot('success');
660
- const { snapshot: workflow2, runId: runId2, stepId: stepId2 } = createSampleWorkflowSnapshot('waiting');
661
- const { snapshot: workflow3, runId: runId3, stepId: stepId3 } = createSampleWorkflowSnapshot('skipped');
652
+ const { snapshot: workflow2, runId: runId2, stepId: stepId2 } = createSampleWorkflowSnapshot('suspended');
653
+ const { snapshot: workflow3, runId: runId3, stepId: stepId3 } = createSampleWorkflowSnapshot('failed');
662
654
 
663
655
  await store.persistWorkflowSnapshot({
664
656
  workflowName: workflowName1,
@@ -689,8 +681,8 @@ describe('ClickhouseStore', () => {
689
681
  expect(page1.runs[1]!.workflowName).toBe(workflowName2);
690
682
  const firstSnapshot = page1.runs[0]!.snapshot;
691
683
  const secondSnapshot = page1.runs[1]!.snapshot;
692
- checkWorkflowSnapshot(firstSnapshot, stepId3, 'skipped');
693
- checkWorkflowSnapshot(secondSnapshot, stepId2, 'waiting');
684
+ checkWorkflowSnapshot(firstSnapshot, stepId3, 'failed');
685
+ checkWorkflowSnapshot(secondSnapshot, stepId2, 'suspended');
694
686
 
695
687
  // Get second page
696
688
  const page2 = await store.getWorkflowRuns({
@@ -754,7 +746,7 @@ describe('ClickhouseStore', () => {
754
746
  // Insert multiple workflow runs for the same resourceId
755
747
  resourceId = 'resource-shared';
756
748
  for (const status of ['completed', 'running']) {
757
- const sample = createSampleWorkflowSnapshot(status as WorkflowRunState['context']['steps'][string]['status']);
749
+ const sample = createSampleWorkflowSnapshot(status as WorkflowRunState['context']['steps']['status']);
758
750
  runIds.push(sample.runId);
759
751
  await store.insert({
760
752
  tableName: TABLE_WORKFLOW_SNAPSHOT,
@@ -769,7 +761,7 @@ describe('ClickhouseStore', () => {
769
761
  });
770
762
  }
771
763
  // Insert a run with a different resourceId
772
- const other = createSampleWorkflowSnapshot('waiting');
764
+ const other = createSampleWorkflowSnapshot('suspended');
773
765
  await store.insert({
774
766
  tableName: TABLE_WORKFLOW_SNAPSHOT,
775
767
  record: {
@@ -1,7 +1,9 @@
1
1
  import type { ClickHouseClient } from '@clickhouse/client';
2
2
  import { createClient } from '@clickhouse/client';
3
+ import { MessageList } from '@mastra/core/agent';
4
+ import type { MastraMessageV2 } from '@mastra/core/agent';
3
5
  import type { MetricResult, TestInfo } from '@mastra/core/eval';
4
- import type { MessageType, StorageThreadType } from '@mastra/core/memory';
6
+ import type { MastraMessageV1, StorageThreadType } from '@mastra/core/memory';
5
7
  import {
6
8
  MastraStorage,
7
9
  TABLE_EVALS,
@@ -337,7 +339,6 @@ export class ClickhouseStore extends MastraStorage {
337
339
  ${['id String'].concat(columns)}
338
340
  )
339
341
  ENGINE = ${TABLE_ENGINES[tableName]}
340
- PARTITION BY "createdAt"
341
342
  PRIMARY KEY (createdAt, run_id, workflow_name)
342
343
  ORDER BY (createdAt, run_id, workflow_name)
343
344
  ${rowTtl ? `TTL toDateTime(${rowTtl.ttlKey ?? 'createdAt'}) + INTERVAL ${rowTtl.interval} ${rowTtl.unit}` : ''}
@@ -348,7 +349,6 @@ export class ClickhouseStore extends MastraStorage {
348
349
  ${columns}
349
350
  )
350
351
  ENGINE = ${TABLE_ENGINES[tableName]}
351
- PARTITION BY "createdAt"
352
352
  PRIMARY KEY (createdAt, ${tableName === TABLE_EVALS ? 'run_id' : 'id'})
353
353
  ORDER BY (createdAt, ${tableName === TABLE_EVALS ? 'run_id' : 'id'})
354
354
  ${this.ttl?.[tableName]?.row ? `TTL toDateTime(createdAt) + INTERVAL ${this.ttl[tableName].row.interval} ${this.ttl[tableName].row.unit}` : ''}
@@ -627,7 +627,7 @@ export class ClickhouseStore extends MastraStorage {
627
627
  try {
628
628
  // First delete all messages associated with this thread
629
629
  await this.db.command({
630
- query: `DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id = '${threadId}';`,
630
+ query: `DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id = {var_thread_id:String};`,
631
631
  query_params: { var_thread_id: threadId },
632
632
  clickhouse_settings: {
633
633
  output_format_json_quote_64bit_integers: 0,
@@ -648,7 +648,14 @@ export class ClickhouseStore extends MastraStorage {
648
648
  }
649
649
  }
650
650
 
651
- async getMessages<T = unknown>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]> {
651
+ public async getMessages(args: StorageGetMessagesArg & { format?: 'v1' }): Promise<MastraMessageV1[]>;
652
+ public async getMessages(args: StorageGetMessagesArg & { format: 'v2' }): Promise<MastraMessageV2[]>;
653
+ public async getMessages({
654
+ threadId,
655
+ resourceId,
656
+ selectBy,
657
+ format,
658
+ }: StorageGetMessagesArg & { format?: 'v1' | 'v2' }): Promise<MastraMessageV1[] | MastraMessageV2[]> {
652
659
  try {
653
660
  const messages: any[] = [];
654
661
  const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
@@ -755,18 +762,26 @@ export class ClickhouseStore extends MastraStorage {
755
762
  }
756
763
  });
757
764
 
758
- return messages as T[];
765
+ const list = new MessageList({ threadId, resourceId }).add(messages, 'memory');
766
+ if (format === `v2`) return list.get.all.v2();
767
+ return list.get.all.v1();
759
768
  } catch (error) {
760
769
  console.error('Error getting messages:', error);
761
770
  throw error;
762
771
  }
763
772
  }
764
773
 
765
- async saveMessages({ messages }: { messages: MessageType[] }): Promise<MessageType[]> {
774
+ async saveMessages(args: { messages: MastraMessageV1[]; format?: undefined | 'v1' }): Promise<MastraMessageV1[]>;
775
+ async saveMessages(args: { messages: MastraMessageV2[]; format: 'v2' }): Promise<MastraMessageV2[]>;
776
+ async saveMessages(
777
+ args: { messages: MastraMessageV1[]; format?: undefined | 'v1' } | { messages: MastraMessageV2[]; format: 'v2' },
778
+ ): Promise<MastraMessageV2[] | MastraMessageV1[]> {
779
+ const { messages, format = 'v1' } = args;
766
780
  if (messages.length === 0) return messages;
767
781
 
768
782
  try {
769
783
  const threadId = messages[0]?.threadId;
784
+ const resourceId = messages[0]?.resourceId;
770
785
  if (!threadId) {
771
786
  throw new Error('Thread ID is required');
772
787
  }
@@ -786,7 +801,7 @@ export class ClickhouseStore extends MastraStorage {
786
801
  content: typeof message.content === 'string' ? message.content : JSON.stringify(message.content),
787
802
  createdAt: message.createdAt.toISOString(),
788
803
  role: message.role,
789
- type: message.type,
804
+ type: message.type || 'v2',
790
805
  })),
791
806
  clickhouse_settings: {
792
807
  // Allows to insert serialized JS Dates (such as '2023-12-06T10:54:48.000Z')
@@ -796,7 +811,9 @@ export class ClickhouseStore extends MastraStorage {
796
811
  },
797
812
  });
798
813
 
799
- return messages;
814
+ const list = new MessageList({ threadId, resourceId }).add(messages, 'memory');
815
+ if (format === `v2`) return list.get.all.v2();
816
+ return list.get.all.v1();
800
817
  } catch (error) {
801
818
  console.error('Error saving messages:', error);
802
819
  throw error;