@mastra/clickhouse 0.10.1 → 0.10.2-alpha.1
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 +8 -8
- package/CHANGELOG.md +19 -0
- package/dist/_tsup-dts-rollup.d.cts +29 -1
- package/dist/_tsup-dts-rollup.d.ts +29 -1
- package/dist/index.cjs +64 -0
- package/dist/index.js +64 -0
- package/package.json +9 -8
- package/src/storage/index.test.ts +229 -75
- package/src/storage/index.ts +89 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/clickhouse@0.10.
|
|
2
|
+
> @mastra/clickhouse@0.10.2-alpha.1 build /home/runner/work/mastra/mastra/stores/clickhouse
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
-
[34mCLI[39m tsup v8.
|
|
7
|
+
[34mCLI[39m tsup v8.5.0
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 8294ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/clickhouse/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/stores/clickhouse/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 11634ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
21
|
-
[32mESM[39m ⚡️ Build success in
|
|
22
|
-
[32mCJS[39m [1mdist/index.cjs [22m[
|
|
23
|
-
[32mCJS[39m ⚡️ Build success in
|
|
20
|
+
[32mESM[39m [1mdist/index.js [22m[32m30.35 KB[39m
|
|
21
|
+
[32mESM[39m ⚡️ Build success in 1068ms
|
|
22
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m30.60 KB[39m
|
|
23
|
+
[32mCJS[39m ⚡️ Build success in 1069ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @mastra/clickhouse
|
|
2
2
|
|
|
3
|
+
## 0.10.2-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 925ab94: added paginated functions to base class and added boilerplate and updated imports
|
|
8
|
+
- Updated dependencies [925ab94]
|
|
9
|
+
- @mastra/core@0.10.4-alpha.3
|
|
10
|
+
|
|
11
|
+
## 0.10.2-alpha.0
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- dffb67b: updated stores to add alter table and change tests
|
|
16
|
+
- Updated dependencies [f6fd25f]
|
|
17
|
+
- Updated dependencies [dffb67b]
|
|
18
|
+
- Updated dependencies [f1309d3]
|
|
19
|
+
- Updated dependencies [f7f8293]
|
|
20
|
+
- @mastra/core@0.10.4-alpha.1
|
|
21
|
+
|
|
3
22
|
## 0.10.1
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { ClickHouseClient } from '@clickhouse/client';
|
|
2
2
|
import type { EvalRow } from '@mastra/core/storage';
|
|
3
3
|
import type { MastraMessageV1 } from '@mastra/core/memory';
|
|
4
|
-
import type { MastraMessageV2 } from '@mastra/core/
|
|
4
|
+
import type { MastraMessageV2 } from '@mastra/core/memory';
|
|
5
5
|
import { MastraStorage } from '@mastra/core/storage';
|
|
6
|
+
import type { PaginationInfo } from '@mastra/core/storage';
|
|
6
7
|
import type { StorageColumn } from '@mastra/core/storage';
|
|
7
8
|
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
9
|
+
import type { StorageGetTracesArg } from '@mastra/core/storage';
|
|
8
10
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
9
11
|
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
10
12
|
import { TABLE_SCHEMAS } from '@mastra/core/storage';
|
|
13
|
+
import type { Trace } from '@mastra/core/telemetry';
|
|
11
14
|
import type { WorkflowRun } from '@mastra/core/storage';
|
|
12
15
|
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
13
16
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
@@ -66,6 +69,18 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
66
69
|
tableName: TABLE_NAMES;
|
|
67
70
|
schema: Record<string, StorageColumn>;
|
|
68
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>;
|
|
69
84
|
clearTable({ tableName }: {
|
|
70
85
|
tableName: TABLE_NAMES;
|
|
71
86
|
}): Promise<void>;
|
|
@@ -131,6 +146,19 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
131
146
|
workflowName?: string;
|
|
132
147
|
}): Promise<WorkflowRun | null>;
|
|
133
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[];
|
|
161
|
+
}>;
|
|
134
162
|
close(): Promise<void>;
|
|
135
163
|
}
|
|
136
164
|
export { ClickhouseStore }
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { ClickHouseClient } from '@clickhouse/client';
|
|
2
2
|
import type { EvalRow } from '@mastra/core/storage';
|
|
3
3
|
import type { MastraMessageV1 } from '@mastra/core/memory';
|
|
4
|
-
import type { MastraMessageV2 } from '@mastra/core/
|
|
4
|
+
import type { MastraMessageV2 } from '@mastra/core/memory';
|
|
5
5
|
import { MastraStorage } from '@mastra/core/storage';
|
|
6
|
+
import type { PaginationInfo } from '@mastra/core/storage';
|
|
6
7
|
import type { StorageColumn } from '@mastra/core/storage';
|
|
7
8
|
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
9
|
+
import type { StorageGetTracesArg } from '@mastra/core/storage';
|
|
8
10
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
9
11
|
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
10
12
|
import { TABLE_SCHEMAS } from '@mastra/core/storage';
|
|
13
|
+
import type { Trace } from '@mastra/core/telemetry';
|
|
11
14
|
import type { WorkflowRun } from '@mastra/core/storage';
|
|
12
15
|
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
13
16
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
@@ -66,6 +69,18 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
66
69
|
tableName: TABLE_NAMES;
|
|
67
70
|
schema: Record<string, StorageColumn>;
|
|
68
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>;
|
|
69
84
|
clearTable({ tableName }: {
|
|
70
85
|
tableName: TABLE_NAMES;
|
|
71
86
|
}): Promise<void>;
|
|
@@ -131,6 +146,19 @@ declare class ClickhouseStore extends MastraStorage {
|
|
|
131
146
|
workflowName?: string;
|
|
132
147
|
}): Promise<WorkflowRun | null>;
|
|
133
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[];
|
|
161
|
+
}>;
|
|
134
162
|
close(): Promise<void>;
|
|
135
163
|
}
|
|
136
164
|
export { ClickhouseStore }
|
package/dist/index.cjs
CHANGED
|
@@ -267,6 +267,61 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
267
267
|
throw error;
|
|
268
268
|
}
|
|
269
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
|
+
}
|
|
270
325
|
async clearTable({ tableName }) {
|
|
271
326
|
try {
|
|
272
327
|
await this.db.query({
|
|
@@ -857,6 +912,15 @@ var ClickhouseStore = class extends storage.MastraStorage {
|
|
|
857
912
|
const columns = await result.json();
|
|
858
913
|
return columns.some((c) => c.name === column);
|
|
859
914
|
}
|
|
915
|
+
async getTracesPaginated(_args) {
|
|
916
|
+
throw new Error("Method not implemented.");
|
|
917
|
+
}
|
|
918
|
+
async getThreadsByResourceIdPaginated(_args) {
|
|
919
|
+
throw new Error("Method not implemented.");
|
|
920
|
+
}
|
|
921
|
+
async getMessagesPaginated(_args) {
|
|
922
|
+
throw new Error("Method not implemented.");
|
|
923
|
+
}
|
|
860
924
|
async close() {
|
|
861
925
|
await this.db.close();
|
|
862
926
|
}
|
package/dist/index.js
CHANGED
|
@@ -265,6 +265,61 @@ var ClickhouseStore = class extends MastraStorage {
|
|
|
265
265
|
throw error;
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
+
getSqlType(type) {
|
|
269
|
+
switch (type) {
|
|
270
|
+
case "text":
|
|
271
|
+
return "String";
|
|
272
|
+
case "timestamp":
|
|
273
|
+
return "DateTime64(3)";
|
|
274
|
+
case "integer":
|
|
275
|
+
case "bigint":
|
|
276
|
+
return "Int64";
|
|
277
|
+
case "jsonb":
|
|
278
|
+
return "String";
|
|
279
|
+
default:
|
|
280
|
+
return super.getSqlType(type);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Alters table schema to add columns if they don't exist
|
|
285
|
+
* @param tableName Name of the table
|
|
286
|
+
* @param schema Schema of the table
|
|
287
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
288
|
+
*/
|
|
289
|
+
async alterTable({
|
|
290
|
+
tableName,
|
|
291
|
+
schema,
|
|
292
|
+
ifNotExists
|
|
293
|
+
}) {
|
|
294
|
+
try {
|
|
295
|
+
const describeSql = `DESCRIBE TABLE ${tableName}`;
|
|
296
|
+
const result = await this.db.query({
|
|
297
|
+
query: describeSql
|
|
298
|
+
});
|
|
299
|
+
const rows = await result.json();
|
|
300
|
+
const existingColumnNames = new Set(rows.data.map((row) => row.name.toLowerCase()));
|
|
301
|
+
for (const columnName of ifNotExists) {
|
|
302
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
303
|
+
const columnDef = schema[columnName];
|
|
304
|
+
let sqlType = this.getSqlType(columnDef.type);
|
|
305
|
+
if (columnDef.nullable !== false) {
|
|
306
|
+
sqlType = `Nullable(${sqlType})`;
|
|
307
|
+
}
|
|
308
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
309
|
+
const alterSql = `ALTER TABLE ${tableName} ADD COLUMN IF NOT EXISTS "${columnName}" ${sqlType} ${defaultValue}`.trim();
|
|
310
|
+
await this.db.query({
|
|
311
|
+
query: alterSql
|
|
312
|
+
});
|
|
313
|
+
this.logger?.debug?.(`Added column ${columnName} to table ${tableName}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
this.logger?.error?.(
|
|
318
|
+
`Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`
|
|
319
|
+
);
|
|
320
|
+
throw new Error(`Failed to alter table ${tableName}: ${error}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
268
323
|
async clearTable({ tableName }) {
|
|
269
324
|
try {
|
|
270
325
|
await this.db.query({
|
|
@@ -855,6 +910,15 @@ var ClickhouseStore = class extends MastraStorage {
|
|
|
855
910
|
const columns = await result.json();
|
|
856
911
|
return columns.some((c) => c.name === column);
|
|
857
912
|
}
|
|
913
|
+
async getTracesPaginated(_args) {
|
|
914
|
+
throw new Error("Method not implemented.");
|
|
915
|
+
}
|
|
916
|
+
async getThreadsByResourceIdPaginated(_args) {
|
|
917
|
+
throw new Error("Method not implemented.");
|
|
918
|
+
}
|
|
919
|
+
async getMessagesPaginated(_args) {
|
|
920
|
+
throw new Error("Method not implemented.");
|
|
921
|
+
}
|
|
858
922
|
async close() {
|
|
859
923
|
await this.db.close();
|
|
860
924
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/clickhouse",
|
|
3
|
-
"version": "0.10.1",
|
|
3
|
+
"version": "0.10.2-alpha.1",
|
|
4
4
|
"description": "Clickhouse provider for Mastra - includes db storage capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,14 +23,15 @@
|
|
|
23
23
|
"@clickhouse/client": "^1.11.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@microsoft/api-extractor": "^7.52.
|
|
27
|
-
"@types/node": "^20.17.
|
|
28
|
-
"eslint": "^9.
|
|
29
|
-
"tsup": "^8.
|
|
26
|
+
"@microsoft/api-extractor": "^7.52.8",
|
|
27
|
+
"@types/node": "^20.17.57",
|
|
28
|
+
"eslint": "^9.28.0",
|
|
29
|
+
"tsup": "^8.5.0",
|
|
30
30
|
"typescript": "^5.8.2",
|
|
31
|
-
"vitest": "^3.
|
|
32
|
-
"@
|
|
33
|
-
"@internal/
|
|
31
|
+
"vitest": "^3.2.2",
|
|
32
|
+
"@internal/lint": "0.0.10",
|
|
33
|
+
"@internal/storage-test-utils": "0.0.6",
|
|
34
|
+
"@mastra/core": "0.10.4-alpha.3"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
37
|
"@mastra/core": "^0.10.2-alpha.0"
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
createSampleMessageV1,
|
|
4
|
+
createSampleThread,
|
|
5
|
+
createSampleWorkflowSnapshot,
|
|
6
|
+
checkWorkflowSnapshot,
|
|
7
|
+
} from '@internal/storage-test-utils';
|
|
8
|
+
import type { MastraMessageV1, StorageColumn, WorkflowRunState } from '@mastra/core';
|
|
9
|
+
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
3
10
|
import { TABLE_THREADS, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
|
|
4
11
|
import { describe, it, expect, beforeAll, beforeEach, afterAll, vi, afterEach } from 'vitest';
|
|
5
12
|
|
|
6
|
-
import { ClickhouseStore } from '.';
|
|
13
|
+
import { ClickhouseStore, TABLE_ENGINES } from '.';
|
|
7
14
|
import type { ClickhouseConfig } from '.';
|
|
8
15
|
|
|
9
16
|
vi.setConfig({ testTimeout: 60_000, hookTimeout: 60_000 });
|
|
@@ -24,33 +31,6 @@ const TEST_CONFIG: ClickhouseConfig = {
|
|
|
24
31
|
},
|
|
25
32
|
};
|
|
26
33
|
|
|
27
|
-
// Sample test data factory functions
|
|
28
|
-
const createSampleThread = () => ({
|
|
29
|
-
id: `thread-${randomUUID()}`,
|
|
30
|
-
resourceId: `clickhouse-test`,
|
|
31
|
-
title: 'Test Thread',
|
|
32
|
-
createdAt: new Date(),
|
|
33
|
-
updatedAt: new Date(),
|
|
34
|
-
metadata: { key: 'value' },
|
|
35
|
-
});
|
|
36
|
-
|
|
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 => ({
|
|
45
|
-
id: `msg-${randomUUID()}`,
|
|
46
|
-
resourceId: `clickhouse-test`,
|
|
47
|
-
role: getRole(),
|
|
48
|
-
type: 'text',
|
|
49
|
-
threadId,
|
|
50
|
-
content: 'Hello',
|
|
51
|
-
createdAt,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
34
|
const createSampleTrace = () => ({
|
|
55
35
|
id: `trace-${randomUUID()}`,
|
|
56
36
|
name: 'Test Trace',
|
|
@@ -66,39 +46,6 @@ const createSampleEval = () => ({
|
|
|
66
46
|
createdAt: new Date(),
|
|
67
47
|
});
|
|
68
48
|
|
|
69
|
-
const createSampleWorkflowSnapshot = (status: WorkflowRunState['context']['steps']['status'], createdAt?: Date) => {
|
|
70
|
-
const runId = `run-${randomUUID()}`;
|
|
71
|
-
const stepId = `step-${randomUUID()}`;
|
|
72
|
-
const timestamp = createdAt || new Date();
|
|
73
|
-
const snapshot = {
|
|
74
|
-
result: { success: true },
|
|
75
|
-
value: {},
|
|
76
|
-
context: {
|
|
77
|
-
[stepId]: {
|
|
78
|
-
status,
|
|
79
|
-
payload: {},
|
|
80
|
-
error: undefined,
|
|
81
|
-
startedAt: timestamp.getTime(),
|
|
82
|
-
endedAt: new Date(timestamp.getTime() + 15000).getTime(),
|
|
83
|
-
},
|
|
84
|
-
input: {},
|
|
85
|
-
},
|
|
86
|
-
serializedStepGraph: [],
|
|
87
|
-
activePaths: [],
|
|
88
|
-
suspendedPaths: {},
|
|
89
|
-
runId,
|
|
90
|
-
timestamp: timestamp.getTime(),
|
|
91
|
-
} as unknown as WorkflowRunState;
|
|
92
|
-
return { snapshot, runId, stepId };
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const checkWorkflowSnapshot = (snapshot: WorkflowRunState | string, stepId: string, status: string) => {
|
|
96
|
-
if (typeof snapshot === 'string') {
|
|
97
|
-
throw new Error('Expected WorkflowRunState, got string');
|
|
98
|
-
}
|
|
99
|
-
expect(snapshot.context?.[stepId]?.status).toBe(status);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
49
|
describe('ClickhouseStore', () => {
|
|
103
50
|
let store: ClickhouseStore;
|
|
104
51
|
|
|
@@ -171,7 +118,10 @@ describe('ClickhouseStore', () => {
|
|
|
171
118
|
await store.saveThread({ thread });
|
|
172
119
|
|
|
173
120
|
// Add some messages
|
|
174
|
-
const messages = [
|
|
121
|
+
const messages = [
|
|
122
|
+
createSampleMessageV1({ threadId: thread.id, resourceId: 'clickhouse-test' }),
|
|
123
|
+
createSampleMessageV1({ threadId: thread.id, resourceId: 'clickhouse-test' }),
|
|
124
|
+
];
|
|
175
125
|
await store.saveMessages({ messages });
|
|
176
126
|
|
|
177
127
|
await store.deleteThread({ threadId: thread.id });
|
|
@@ -191,8 +141,12 @@ describe('ClickhouseStore', () => {
|
|
|
191
141
|
await store.saveThread({ thread });
|
|
192
142
|
|
|
193
143
|
const messages = [
|
|
194
|
-
|
|
195
|
-
|
|
144
|
+
createSampleMessageV1({
|
|
145
|
+
threadId: thread.id,
|
|
146
|
+
createdAt: new Date(Date.now() - 1000 * 60 * 60 * 24),
|
|
147
|
+
resourceId: 'clickhouse-test',
|
|
148
|
+
}),
|
|
149
|
+
createSampleMessageV1({ threadId: thread.id, resourceId: 'clickhouse-test' }),
|
|
196
150
|
];
|
|
197
151
|
|
|
198
152
|
// Save messages
|
|
@@ -218,23 +172,35 @@ describe('ClickhouseStore', () => {
|
|
|
218
172
|
const thread = createSampleThread();
|
|
219
173
|
await store.saveThread({ thread });
|
|
220
174
|
|
|
221
|
-
const messages
|
|
175
|
+
const messages = [
|
|
222
176
|
{
|
|
223
|
-
...
|
|
224
|
-
|
|
177
|
+
...createSampleMessageV1({
|
|
178
|
+
threadId: thread.id,
|
|
179
|
+
createdAt: new Date(Date.now() - 1000 * 3),
|
|
180
|
+
content: 'First',
|
|
181
|
+
resourceId: 'clickhouse-test',
|
|
182
|
+
}),
|
|
225
183
|
role: 'user',
|
|
226
184
|
},
|
|
227
185
|
{
|
|
228
|
-
...
|
|
229
|
-
|
|
186
|
+
...createSampleMessageV1({
|
|
187
|
+
threadId: thread.id,
|
|
188
|
+
createdAt: new Date(Date.now() - 1000 * 2),
|
|
189
|
+
content: 'Second',
|
|
190
|
+
resourceId: 'clickhouse-test',
|
|
191
|
+
}),
|
|
230
192
|
role: 'assistant',
|
|
231
193
|
},
|
|
232
194
|
{
|
|
233
|
-
...
|
|
234
|
-
|
|
195
|
+
...createSampleMessageV1({
|
|
196
|
+
threadId: thread.id,
|
|
197
|
+
createdAt: new Date(Date.now() - 1000 * 1),
|
|
198
|
+
content: 'Third',
|
|
199
|
+
resourceId: 'clickhouse-test',
|
|
200
|
+
}),
|
|
235
201
|
role: 'user',
|
|
236
202
|
},
|
|
237
|
-
];
|
|
203
|
+
] as MastraMessageV1[];
|
|
238
204
|
|
|
239
205
|
await store.saveMessages({ messages });
|
|
240
206
|
|
|
@@ -248,13 +214,107 @@ describe('ClickhouseStore', () => {
|
|
|
248
214
|
});
|
|
249
215
|
}, 10e3);
|
|
250
216
|
|
|
217
|
+
// it('should retrieve messages w/ next/prev messages by message id + resource id', async () => {
|
|
218
|
+
// const messages: MastraMessageV2[] = [
|
|
219
|
+
// createSampleMessageV2({ threadId: 'thread-one', content: 'First', resourceId: 'cross-thread-resource' }),
|
|
220
|
+
// createSampleMessageV2({ threadId: 'thread-one', content: 'Second', resourceId: 'cross-thread-resource' }),
|
|
221
|
+
// createSampleMessageV2({ threadId: 'thread-one', content: 'Third', resourceId: 'cross-thread-resource' }),
|
|
222
|
+
|
|
223
|
+
// createSampleMessageV2({ threadId: 'thread-two', content: 'Fourth', resourceId: 'cross-thread-resource' }),
|
|
224
|
+
// createSampleMessageV2({ threadId: 'thread-two', content: 'Fifth', resourceId: 'cross-thread-resource' }),
|
|
225
|
+
// createSampleMessageV2({ threadId: 'thread-two', content: 'Sixth', resourceId: 'cross-thread-resource' }),
|
|
226
|
+
|
|
227
|
+
// createSampleMessageV2({ threadId: 'thread-three', content: 'Seventh', resourceId: 'other-resource' }),
|
|
228
|
+
// createSampleMessageV2({ threadId: 'thread-three', content: 'Eighth', resourceId: 'other-resource' }),
|
|
229
|
+
// ];
|
|
230
|
+
|
|
231
|
+
// await store.saveMessages({ messages: messages, format: 'v2' });
|
|
232
|
+
|
|
233
|
+
// const retrievedMessages = await store.getMessages({ threadId: 'thread-one', format: 'v2' });
|
|
234
|
+
// expect(retrievedMessages).toHaveLength(3);
|
|
235
|
+
// expect(retrievedMessages.map((m: any) => m.content.parts[0].text)).toEqual(['First', 'Second', 'Third']);
|
|
236
|
+
|
|
237
|
+
// const retrievedMessages2 = await store.getMessages({ threadId: 'thread-two', format: 'v2' });
|
|
238
|
+
// expect(retrievedMessages2).toHaveLength(3);
|
|
239
|
+
// expect(retrievedMessages2.map((m: any) => m.content.parts[0].text)).toEqual(['Fourth', 'Fifth', 'Sixth']);
|
|
240
|
+
|
|
241
|
+
// const retrievedMessages3 = await store.getMessages({ threadId: 'thread-three', format: 'v2' });
|
|
242
|
+
// expect(retrievedMessages3).toHaveLength(2);
|
|
243
|
+
// expect(retrievedMessages3.map((m: any) => m.content.parts[0].text)).toEqual(['Seventh', 'Eighth']);
|
|
244
|
+
|
|
245
|
+
// const crossThreadMessages = await store.getMessages({
|
|
246
|
+
// threadId: 'thread-doesnt-exist',
|
|
247
|
+
// resourceId: 'cross-thread-resource',
|
|
248
|
+
// format: 'v2',
|
|
249
|
+
// selectBy: {
|
|
250
|
+
// last: 0,
|
|
251
|
+
// include: [
|
|
252
|
+
// {
|
|
253
|
+
// id: messages[1].id,
|
|
254
|
+
// withNextMessages: 2,
|
|
255
|
+
// withPreviousMessages: 2,
|
|
256
|
+
// },
|
|
257
|
+
// {
|
|
258
|
+
// id: messages[4].id,
|
|
259
|
+
// withPreviousMessages: 2,
|
|
260
|
+
// withNextMessages: 2,
|
|
261
|
+
// },
|
|
262
|
+
// ],
|
|
263
|
+
// },
|
|
264
|
+
// });
|
|
265
|
+
|
|
266
|
+
// expect(crossThreadMessages).toHaveLength(6);
|
|
267
|
+
// expect(crossThreadMessages.filter(m => m.threadId === `thread-one`)).toHaveLength(3);
|
|
268
|
+
// expect(crossThreadMessages.filter(m => m.threadId === `thread-two`)).toHaveLength(3);
|
|
269
|
+
|
|
270
|
+
// const crossThreadMessages2 = await store.getMessages({
|
|
271
|
+
// threadId: 'thread-one',
|
|
272
|
+
// resourceId: 'cross-thread-resource',
|
|
273
|
+
// format: 'v2',
|
|
274
|
+
// selectBy: {
|
|
275
|
+
// last: 0,
|
|
276
|
+
// include: [
|
|
277
|
+
// {
|
|
278
|
+
// id: messages[4].id,
|
|
279
|
+
// withPreviousMessages: 1,
|
|
280
|
+
// withNextMessages: 30,
|
|
281
|
+
// },
|
|
282
|
+
// ],
|
|
283
|
+
// },
|
|
284
|
+
// });
|
|
285
|
+
|
|
286
|
+
// expect(crossThreadMessages2).toHaveLength(3);
|
|
287
|
+
// expect(crossThreadMessages2.filter(m => m.threadId === `thread-one`)).toHaveLength(0);
|
|
288
|
+
// expect(crossThreadMessages2.filter(m => m.threadId === `thread-two`)).toHaveLength(3);
|
|
289
|
+
|
|
290
|
+
// const crossThreadMessages3 = await store.getMessages({
|
|
291
|
+
// threadId: 'thread-two',
|
|
292
|
+
// resourceId: 'cross-thread-resource',
|
|
293
|
+
// format: 'v2',
|
|
294
|
+
// selectBy: {
|
|
295
|
+
// last: 0,
|
|
296
|
+
// include: [
|
|
297
|
+
// {
|
|
298
|
+
// id: messages[1].id,
|
|
299
|
+
// withNextMessages: 1,
|
|
300
|
+
// withPreviousMessages: 1,
|
|
301
|
+
// },
|
|
302
|
+
// ],
|
|
303
|
+
// },
|
|
304
|
+
// });
|
|
305
|
+
|
|
306
|
+
// expect(crossThreadMessages3).toHaveLength(3);
|
|
307
|
+
// expect(crossThreadMessages3.filter(m => m.threadId === `thread-one`)).toHaveLength(3);
|
|
308
|
+
// expect(crossThreadMessages3.filter(m => m.threadId === `thread-two`)).toHaveLength(0);
|
|
309
|
+
// });
|
|
310
|
+
|
|
251
311
|
// it('should rollback on error during message save', async () => {
|
|
252
312
|
// const thread = createSampleThread();
|
|
253
313
|
// await store.saveThread({ thread });
|
|
254
314
|
|
|
255
315
|
// const messages = [
|
|
256
|
-
//
|
|
257
|
-
// { ...
|
|
316
|
+
// createSampleMessageV1({ threadId: thread.id }),
|
|
317
|
+
// { ...createSampleMessageV1({ threadId: thread.id }), id: null }, // This will cause an error
|
|
258
318
|
// ];
|
|
259
319
|
|
|
260
320
|
// await expect(store.saveMessages({ messages })).rejects.toThrow();
|
|
@@ -842,6 +902,100 @@ describe('ClickhouseStore', () => {
|
|
|
842
902
|
});
|
|
843
903
|
});
|
|
844
904
|
|
|
905
|
+
describe('alterTable', () => {
|
|
906
|
+
const TEST_TABLE = 'test_alter_table';
|
|
907
|
+
const BASE_SCHEMA = {
|
|
908
|
+
id: { type: 'integer', primaryKey: true, nullable: false },
|
|
909
|
+
name: { type: 'text', nullable: true },
|
|
910
|
+
createdAt: { type: 'timestamp', nullable: false },
|
|
911
|
+
updatedAt: { type: 'timestamp', nullable: false },
|
|
912
|
+
} as Record<string, StorageColumn>;
|
|
913
|
+
|
|
914
|
+
TABLE_ENGINES[TEST_TABLE] = 'MergeTree()';
|
|
915
|
+
|
|
916
|
+
beforeEach(async () => {
|
|
917
|
+
await store.createTable({ tableName: TEST_TABLE as TABLE_NAMES, schema: BASE_SCHEMA });
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
afterEach(async () => {
|
|
921
|
+
await store.clearTable({ tableName: TEST_TABLE as TABLE_NAMES });
|
|
922
|
+
});
|
|
923
|
+
|
|
924
|
+
it('adds a new column to an existing table', async () => {
|
|
925
|
+
await store.alterTable({
|
|
926
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
927
|
+
schema: { ...BASE_SCHEMA, age: { type: 'integer', nullable: true } },
|
|
928
|
+
ifNotExists: ['age'],
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
await store.insert({
|
|
932
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
933
|
+
record: { id: 1, name: 'Alice', age: 42, createdAt: new Date(), updatedAt: new Date() },
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
const row = await store.load<{ id: string; name: string; age?: number }>({
|
|
937
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
938
|
+
keys: { id: '1' },
|
|
939
|
+
});
|
|
940
|
+
expect(row?.age).toBe(42);
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
it('is idempotent when adding an existing column', async () => {
|
|
944
|
+
await store.alterTable({
|
|
945
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
946
|
+
schema: { ...BASE_SCHEMA, foo: { type: 'text', nullable: true } },
|
|
947
|
+
ifNotExists: ['foo'],
|
|
948
|
+
});
|
|
949
|
+
// Add the column again (should not throw)
|
|
950
|
+
await expect(
|
|
951
|
+
store.alterTable({
|
|
952
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
953
|
+
schema: { ...BASE_SCHEMA, foo: { type: 'text', nullable: true } },
|
|
954
|
+
ifNotExists: ['foo'],
|
|
955
|
+
}),
|
|
956
|
+
).resolves.not.toThrow();
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
it('should add a default value to a column when using not null', async () => {
|
|
960
|
+
await store.insert({
|
|
961
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
962
|
+
record: { id: 1, name: 'Bob', createdAt: new Date(), updatedAt: new Date() },
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
await expect(
|
|
966
|
+
store.alterTable({
|
|
967
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
968
|
+
schema: { ...BASE_SCHEMA, text_column: { type: 'text', nullable: false } },
|
|
969
|
+
ifNotExists: ['text_column'],
|
|
970
|
+
}),
|
|
971
|
+
).resolves.not.toThrow();
|
|
972
|
+
|
|
973
|
+
await expect(
|
|
974
|
+
store.alterTable({
|
|
975
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
976
|
+
schema: { ...BASE_SCHEMA, timestamp_column: { type: 'timestamp', nullable: false } },
|
|
977
|
+
ifNotExists: ['timestamp_column'],
|
|
978
|
+
}),
|
|
979
|
+
).resolves.not.toThrow();
|
|
980
|
+
|
|
981
|
+
await expect(
|
|
982
|
+
store.alterTable({
|
|
983
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
984
|
+
schema: { ...BASE_SCHEMA, bigint_column: { type: 'bigint', nullable: false } },
|
|
985
|
+
ifNotExists: ['bigint_column'],
|
|
986
|
+
}),
|
|
987
|
+
).resolves.not.toThrow();
|
|
988
|
+
|
|
989
|
+
await expect(
|
|
990
|
+
store.alterTable({
|
|
991
|
+
tableName: TEST_TABLE as TABLE_NAMES,
|
|
992
|
+
schema: { ...BASE_SCHEMA, jsonb_column: { type: 'jsonb', nullable: false } },
|
|
993
|
+
ifNotExists: ['jsonb_column'],
|
|
994
|
+
}),
|
|
995
|
+
).resolves.not.toThrow();
|
|
996
|
+
});
|
|
997
|
+
});
|
|
998
|
+
|
|
845
999
|
afterAll(async () => {
|
|
846
1000
|
await store.close();
|
|
847
1001
|
});
|
package/src/storage/index.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { ClickHouseClient } from '@clickhouse/client';
|
|
2
2
|
import { createClient } from '@clickhouse/client';
|
|
3
3
|
import { MessageList } from '@mastra/core/agent';
|
|
4
|
-
import type { MastraMessageV2 } from '@mastra/core/agent';
|
|
5
4
|
import type { MetricResult, TestInfo } from '@mastra/core/eval';
|
|
6
|
-
import type { MastraMessageV1, StorageThreadType } from '@mastra/core/memory';
|
|
5
|
+
import type { MastraMessageV1, MastraMessageV2, StorageThreadType } from '@mastra/core/memory';
|
|
7
6
|
import {
|
|
8
7
|
MastraStorage,
|
|
9
8
|
TABLE_EVALS,
|
|
@@ -15,12 +14,15 @@ import {
|
|
|
15
14
|
} from '@mastra/core/storage';
|
|
16
15
|
import type {
|
|
17
16
|
EvalRow,
|
|
17
|
+
PaginationInfo,
|
|
18
18
|
StorageColumn,
|
|
19
19
|
StorageGetMessagesArg,
|
|
20
20
|
TABLE_NAMES,
|
|
21
21
|
WorkflowRun,
|
|
22
22
|
WorkflowRuns,
|
|
23
|
+
StorageGetTracesArg,
|
|
23
24
|
} from '@mastra/core/storage';
|
|
25
|
+
import type { Trace } from '@mastra/core/telemetry';
|
|
24
26
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
25
27
|
|
|
26
28
|
function safelyParseJSON(jsonString: string): any {
|
|
@@ -371,6 +373,73 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
371
373
|
}
|
|
372
374
|
}
|
|
373
375
|
|
|
376
|
+
protected getSqlType(type: StorageColumn['type']): string {
|
|
377
|
+
switch (type) {
|
|
378
|
+
case 'text':
|
|
379
|
+
return 'String';
|
|
380
|
+
case 'timestamp':
|
|
381
|
+
return 'DateTime64(3)';
|
|
382
|
+
case 'integer':
|
|
383
|
+
case 'bigint':
|
|
384
|
+
return 'Int64';
|
|
385
|
+
case 'jsonb':
|
|
386
|
+
return 'String';
|
|
387
|
+
default:
|
|
388
|
+
return super.getSqlType(type); // fallback to base implementation
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Alters table schema to add columns if they don't exist
|
|
394
|
+
* @param tableName Name of the table
|
|
395
|
+
* @param schema Schema of the table
|
|
396
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
397
|
+
*/
|
|
398
|
+
async alterTable({
|
|
399
|
+
tableName,
|
|
400
|
+
schema,
|
|
401
|
+
ifNotExists,
|
|
402
|
+
}: {
|
|
403
|
+
tableName: TABLE_NAMES;
|
|
404
|
+
schema: Record<string, StorageColumn>;
|
|
405
|
+
ifNotExists: string[];
|
|
406
|
+
}): Promise<void> {
|
|
407
|
+
try {
|
|
408
|
+
// 1. Get existing columns
|
|
409
|
+
const describeSql = `DESCRIBE TABLE ${tableName}`;
|
|
410
|
+
const result = await this.db.query({
|
|
411
|
+
query: describeSql,
|
|
412
|
+
});
|
|
413
|
+
const rows = await result.json();
|
|
414
|
+
const existingColumnNames = new Set(rows.data.map((row: any) => row.name.toLowerCase()));
|
|
415
|
+
|
|
416
|
+
// 2. Add missing columns
|
|
417
|
+
for (const columnName of ifNotExists) {
|
|
418
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
419
|
+
const columnDef = schema[columnName];
|
|
420
|
+
let sqlType = this.getSqlType(columnDef.type);
|
|
421
|
+
if (columnDef.nullable !== false) {
|
|
422
|
+
sqlType = `Nullable(${sqlType})`;
|
|
423
|
+
}
|
|
424
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : '';
|
|
425
|
+
// Use backticks or double quotes as needed for identifiers
|
|
426
|
+
const alterSql =
|
|
427
|
+
`ALTER TABLE ${tableName} ADD COLUMN IF NOT EXISTS "${columnName}" ${sqlType} ${defaultValue}`.trim();
|
|
428
|
+
|
|
429
|
+
await this.db.query({
|
|
430
|
+
query: alterSql,
|
|
431
|
+
});
|
|
432
|
+
this.logger?.debug?.(`Added column ${columnName} to table ${tableName}`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
} catch (error) {
|
|
436
|
+
this.logger?.error?.(
|
|
437
|
+
`Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
438
|
+
);
|
|
439
|
+
throw new Error(`Failed to alter table ${tableName}: ${error}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
374
443
|
async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
|
|
375
444
|
try {
|
|
376
445
|
await this.db.query({
|
|
@@ -1069,6 +1138,24 @@ export class ClickhouseStore extends MastraStorage {
|
|
|
1069
1138
|
return columns.some(c => c.name === column);
|
|
1070
1139
|
}
|
|
1071
1140
|
|
|
1141
|
+
async getTracesPaginated(_args: StorageGetTracesArg): Promise<PaginationInfo & { traces: Trace[] }> {
|
|
1142
|
+
throw new Error('Method not implemented.');
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
async getThreadsByResourceIdPaginated(_args: {
|
|
1146
|
+
resourceId: string;
|
|
1147
|
+
page?: number;
|
|
1148
|
+
perPage?: number;
|
|
1149
|
+
}): Promise<PaginationInfo & { threads: StorageThreadType[] }> {
|
|
1150
|
+
throw new Error('Method not implemented.');
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
async getMessagesPaginated(
|
|
1154
|
+
_args: StorageGetMessagesArg,
|
|
1155
|
+
): Promise<PaginationInfo & { messages: MastraMessageV1[] | MastraMessageV2[] }> {
|
|
1156
|
+
throw new Error('Method not implemented.');
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1072
1159
|
async close(): Promise<void> {
|
|
1073
1160
|
await this.db.close();
|
|
1074
1161
|
}
|