@lobehub/chat 1.113.0 → 1.113.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/CHANGELOG.md +25 -0
- package/changelog/v1.json +5 -0
- package/package.json +2 -2
- package/src/app/(backend)/api/webhooks/casdoor/route.ts +2 -1
- package/src/app/(backend)/api/webhooks/clerk/route.ts +2 -1
- package/src/app/(backend)/api/webhooks/logto/route.ts +2 -1
- package/src/app/(backend)/webapi/user/avatar/[id]/[image]/route.ts +2 -1
- package/src/database/server/models/ragEval/dataset.ts +9 -7
- package/src/database/server/models/ragEval/datasetRecord.ts +12 -10
- package/src/database/server/models/ragEval/evaluation.ts +10 -8
- package/src/database/server/models/ragEval/evaluationRecord.ts +11 -9
- package/src/server/routers/async/file.ts +1 -1
- package/src/server/routers/async/ragEval.ts +4 -4
- package/src/server/routers/lambda/chunk.ts +1 -1
- package/src/server/routers/lambda/ragEval.ts +4 -4
- package/src/server/routers/lambda/user.ts +1 -1
- package/src/server/services/chunk/index.ts +2 -2
- package/src/server/services/nextAuthUser/index.test.ts +1 -1
- package/src/server/services/nextAuthUser/index.ts +6 -4
- package/src/server/services/user/index.test.ts +3 -1
- package/src/server/services/user/index.ts +14 -8
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.113.1](https://github.com/lobehub/lobe-chat/compare/v1.113.0...v1.113.1)
|
6
|
+
|
7
|
+
<sup>Released on **2025-08-17**</sup>
|
8
|
+
|
9
|
+
#### 🐛 Bug Fixes
|
10
|
+
|
11
|
+
- **db**: Desktop local db can't vectorization.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's fixed
|
19
|
+
|
20
|
+
- **db**: Desktop local db can't vectorization, closes [#8830](https://github.com/lobehub/lobe-chat/issues/8830) ([a00fd9d](https://github.com/lobehub/lobe-chat/commit/a00fd9d))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
## [Version 1.113.0](https://github.com/lobehub/lobe-chat/compare/v1.112.5...v1.113.0)
|
6
31
|
|
7
32
|
<sup>Released on **2025-08-17**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.113.
|
3
|
+
"version": "1.113.1",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -121,7 +121,7 @@
|
|
121
121
|
"dependencies": {
|
122
122
|
"@ant-design/icons": "^5.6.1",
|
123
123
|
"@ant-design/pro-components": "^2.8.10",
|
124
|
-
"@anthropic-ai/sdk": "^0.
|
124
|
+
"@anthropic-ai/sdk": "^0.60.0",
|
125
125
|
"@auth/core": "^0.40.0",
|
126
126
|
"@aws-sdk/client-s3": "^3.862.0",
|
127
127
|
"@aws-sdk/s3-request-presigner": "^3.862.0",
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { NextResponse } from 'next/server';
|
2
2
|
|
3
3
|
import { authEnv } from '@/config/auth';
|
4
|
+
import { serverDB } from '@/database/server';
|
4
5
|
import { pino } from '@/libs/logger';
|
5
6
|
import { NextAuthUserService } from '@/server/services/nextAuthUser';
|
6
7
|
|
@@ -18,7 +19,7 @@ export const POST = async (req: Request): Promise<NextResponse> => {
|
|
18
19
|
|
19
20
|
const { action, object } = payload;
|
20
21
|
|
21
|
-
const nextAuthUserService = new NextAuthUserService();
|
22
|
+
const nextAuthUserService = new NextAuthUserService(serverDB);
|
22
23
|
switch (action) {
|
23
24
|
case 'update-user': {
|
24
25
|
return nextAuthUserService.safeUpdateUser(
|
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server';
|
|
2
2
|
|
3
3
|
import { authEnv } from '@/config/auth';
|
4
4
|
import { isServerMode } from '@/const/version';
|
5
|
+
import { serverDB } from '@/database/server';
|
5
6
|
import { pino } from '@/libs/logger';
|
6
7
|
import { UserService } from '@/server/services/user';
|
7
8
|
|
@@ -25,7 +26,7 @@ export const POST = async (req: Request): Promise<NextResponse> => {
|
|
25
26
|
|
26
27
|
pino.trace(`clerk webhook payload: ${{ data, type }}`);
|
27
28
|
|
28
|
-
const userService = new UserService();
|
29
|
+
const userService = new UserService(serverDB);
|
29
30
|
switch (type) {
|
30
31
|
case 'user.created': {
|
31
32
|
pino.info('creating user due to clerk webhook');
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { NextResponse } from 'next/server';
|
2
2
|
|
3
3
|
import { authEnv } from '@/config/auth';
|
4
|
+
import { serverDB } from '@/database/server';
|
4
5
|
import { pino } from '@/libs/logger';
|
5
6
|
import { NextAuthUserService } from '@/server/services/nextAuthUser';
|
6
7
|
|
@@ -20,7 +21,7 @@ export const POST = async (req: Request): Promise<NextResponse> => {
|
|
20
21
|
|
21
22
|
pino.trace(`logto webhook payload: ${{ data, event }}`);
|
22
23
|
|
23
|
-
const nextAuthUserService = new NextAuthUserService();
|
24
|
+
const nextAuthUserService = new NextAuthUserService(serverDB);
|
24
25
|
switch (event) {
|
25
26
|
case 'User.Data.Updated': {
|
26
27
|
return nextAuthUserService.safeUpdateUser(
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { serverDB } from '@/database/server';
|
1
2
|
import { UserService } from '@/server/services/user';
|
2
3
|
|
3
4
|
export const runtime = 'nodejs';
|
@@ -31,7 +32,7 @@ export const GET = async (req: Request, segmentData: { params: Params }) => {
|
|
31
32
|
try {
|
32
33
|
const params = await segmentData.params;
|
33
34
|
const type = getContentType(params.image);
|
34
|
-
const userService = new UserService();
|
35
|
+
const userService = new UserService(serverDB);
|
35
36
|
|
36
37
|
const userAvatar = await userService.getUserAvatar(params.id, params.image);
|
37
38
|
if (!userAvatar) {
|
@@ -1,18 +1,20 @@
|
|
1
1
|
import { and, desc, eq } from 'drizzle-orm';
|
2
2
|
|
3
3
|
import { NewEvalDatasetsItem, evalDatasets } from '@/database/schemas';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
import { RAGEvalDataSetItem } from '@/types/eval';
|
6
6
|
|
7
7
|
export class EvalDatasetModel {
|
8
8
|
private userId: string;
|
9
|
+
private db: LobeChatDatabase;
|
9
10
|
|
10
|
-
constructor(userId: string) {
|
11
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
12
|
+
this.db = db;
|
11
13
|
this.userId = userId;
|
12
14
|
}
|
13
15
|
|
14
16
|
create = async (params: NewEvalDatasetsItem) => {
|
15
|
-
const [result] = await
|
17
|
+
const [result] = await this.db
|
16
18
|
.insert(evalDatasets)
|
17
19
|
.values({ ...params, userId: this.userId })
|
18
20
|
.returning();
|
@@ -20,13 +22,13 @@ export class EvalDatasetModel {
|
|
20
22
|
};
|
21
23
|
|
22
24
|
delete = async (id: number) => {
|
23
|
-
return
|
25
|
+
return this.db
|
24
26
|
.delete(evalDatasets)
|
25
27
|
.where(and(eq(evalDatasets.id, id), eq(evalDatasets.userId, this.userId)));
|
26
28
|
};
|
27
29
|
|
28
30
|
query = async (knowledgeBaseId: string): Promise<RAGEvalDataSetItem[]> => {
|
29
|
-
return
|
31
|
+
return this.db
|
30
32
|
.select({
|
31
33
|
createdAt: evalDatasets.createdAt,
|
32
34
|
description: evalDatasets.description,
|
@@ -45,13 +47,13 @@ export class EvalDatasetModel {
|
|
45
47
|
};
|
46
48
|
|
47
49
|
findById = async (id: number) => {
|
48
|
-
return
|
50
|
+
return this.db.query.evalDatasets.findFirst({
|
49
51
|
where: and(eq(evalDatasets.id, id), eq(evalDatasets.userId, this.userId)),
|
50
52
|
});
|
51
53
|
};
|
52
54
|
|
53
55
|
update = async (id: number, value: Partial<NewEvalDatasetsItem>) => {
|
54
|
-
return
|
56
|
+
return this.db
|
55
57
|
.update(evalDatasets)
|
56
58
|
.set({ ...value, updatedAt: new Date() })
|
57
59
|
.where(and(eq(evalDatasets.id, id), eq(evalDatasets.userId, this.userId)));
|
@@ -1,18 +1,20 @@
|
|
1
1
|
import { and, eq, inArray } from 'drizzle-orm';
|
2
2
|
|
3
3
|
import { NewEvalDatasetRecordsItem, evalDatasetRecords, files } from '@/database/schemas';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
import { EvalDatasetRecordRefFile } from '@/types/eval';
|
6
6
|
|
7
7
|
export class EvalDatasetRecordModel {
|
8
8
|
private userId: string;
|
9
|
+
private db: LobeChatDatabase;
|
9
10
|
|
10
|
-
constructor(userId: string) {
|
11
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
12
|
+
this.db = db;
|
11
13
|
this.userId = userId;
|
12
14
|
}
|
13
15
|
|
14
16
|
create = async (params: NewEvalDatasetRecordsItem) => {
|
15
|
-
const [result] = await
|
17
|
+
const [result] = await this.db
|
16
18
|
.insert(evalDatasetRecords)
|
17
19
|
.values({ ...params, userId: this.userId })
|
18
20
|
.returning();
|
@@ -20,7 +22,7 @@ export class EvalDatasetRecordModel {
|
|
20
22
|
};
|
21
23
|
|
22
24
|
batchCreate = async (params: NewEvalDatasetRecordsItem[]) => {
|
23
|
-
const [result] = await
|
25
|
+
const [result] = await this.db
|
24
26
|
.insert(evalDatasetRecords)
|
25
27
|
.values(params.map((item) => ({ ...item, userId: this.userId })))
|
26
28
|
.returning();
|
@@ -29,13 +31,13 @@ export class EvalDatasetRecordModel {
|
|
29
31
|
};
|
30
32
|
|
31
33
|
delete = async (id: number) => {
|
32
|
-
return
|
34
|
+
return this.db
|
33
35
|
.delete(evalDatasetRecords)
|
34
36
|
.where(and(eq(evalDatasetRecords.id, id), eq(evalDatasetRecords.userId, this.userId)));
|
35
37
|
};
|
36
38
|
|
37
39
|
query = async (datasetId: number) => {
|
38
|
-
const list = await
|
40
|
+
const list = await this.db.query.evalDatasetRecords.findMany({
|
39
41
|
where: and(
|
40
42
|
eq(evalDatasetRecords.datasetId, datasetId),
|
41
43
|
eq(evalDatasetRecords.userId, this.userId),
|
@@ -43,7 +45,7 @@ export class EvalDatasetRecordModel {
|
|
43
45
|
});
|
44
46
|
const fileList = list.flatMap((item) => item.referenceFiles).filter(Boolean) as string[];
|
45
47
|
|
46
|
-
const fileItems = await
|
48
|
+
const fileItems = await this.db
|
47
49
|
.select({ fileType: files.fileType, id: files.id, name: files.name })
|
48
50
|
.from(files)
|
49
51
|
.where(and(inArray(files.id, fileList), eq(files.userId, this.userId)));
|
@@ -59,7 +61,7 @@ export class EvalDatasetRecordModel {
|
|
59
61
|
};
|
60
62
|
|
61
63
|
findByDatasetId = async (datasetId: number) => {
|
62
|
-
return
|
64
|
+
return this.db.query.evalDatasetRecords.findMany({
|
63
65
|
where: and(
|
64
66
|
eq(evalDatasetRecords.datasetId, datasetId),
|
65
67
|
eq(evalDatasetRecords.userId, this.userId),
|
@@ -68,13 +70,13 @@ export class EvalDatasetRecordModel {
|
|
68
70
|
};
|
69
71
|
|
70
72
|
findById = async (id: number) => {
|
71
|
-
return
|
73
|
+
return this.db.query.evalDatasetRecords.findFirst({
|
72
74
|
where: and(eq(evalDatasetRecords.id, id), eq(evalDatasetRecords.userId, this.userId)),
|
73
75
|
});
|
74
76
|
};
|
75
77
|
|
76
78
|
update = async (id: number, value: Partial<NewEvalDatasetRecordsItem>) => {
|
77
|
-
return
|
79
|
+
return this.db
|
78
80
|
.update(evalDatasetRecords)
|
79
81
|
.set(value)
|
80
82
|
.where(and(eq(evalDatasetRecords.id, id), eq(evalDatasetRecords.userId, this.userId)));
|
@@ -6,18 +6,20 @@ import {
|
|
6
6
|
evalEvaluation,
|
7
7
|
evaluationRecords,
|
8
8
|
} from '@/database/schemas';
|
9
|
-
import {
|
9
|
+
import { LobeChatDatabase } from '@/database/type';
|
10
10
|
import { EvalEvaluationStatus, RAGEvalEvaluationItem } from '@/types/eval';
|
11
11
|
|
12
12
|
export class EvalEvaluationModel {
|
13
13
|
private userId: string;
|
14
|
+
private db: LobeChatDatabase;
|
14
15
|
|
15
|
-
constructor(userId: string) {
|
16
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
17
|
+
this.db = db;
|
16
18
|
this.userId = userId;
|
17
19
|
}
|
18
20
|
|
19
21
|
create = async (params: NewEvalEvaluationItem) => {
|
20
|
-
const [result] = await
|
22
|
+
const [result] = await this.db
|
21
23
|
.insert(evalEvaluation)
|
22
24
|
.values({ ...params, userId: this.userId })
|
23
25
|
.returning();
|
@@ -25,13 +27,13 @@ export class EvalEvaluationModel {
|
|
25
27
|
};
|
26
28
|
|
27
29
|
delete = async (id: number) => {
|
28
|
-
return
|
30
|
+
return this.db
|
29
31
|
.delete(evalEvaluation)
|
30
32
|
.where(and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)));
|
31
33
|
};
|
32
34
|
|
33
35
|
queryByKnowledgeBaseId = async (knowledgeBaseId: string) => {
|
34
|
-
const evaluations = await
|
36
|
+
const evaluations = await this.db
|
35
37
|
.select({
|
36
38
|
createdAt: evalEvaluation.createdAt,
|
37
39
|
dataset: {
|
@@ -57,7 +59,7 @@ export class EvalEvaluationModel {
|
|
57
59
|
// 然后查询每个评估的记录统计
|
58
60
|
const evaluationIds = evaluations.map((evals) => evals.id);
|
59
61
|
|
60
|
-
const recordStats = await
|
62
|
+
const recordStats = await this.db
|
61
63
|
.select({
|
62
64
|
evaluationId: evaluationRecords.evaluationId,
|
63
65
|
success: count(evaluationRecords.status).if(
|
@@ -82,13 +84,13 @@ export class EvalEvaluationModel {
|
|
82
84
|
};
|
83
85
|
|
84
86
|
findById = async (id: number) => {
|
85
|
-
return
|
87
|
+
return this.db.query.evalEvaluation.findFirst({
|
86
88
|
where: and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)),
|
87
89
|
});
|
88
90
|
};
|
89
91
|
|
90
92
|
update = async (id: number, value: Partial<NewEvalEvaluationItem>) => {
|
91
|
-
return
|
93
|
+
return this.db
|
92
94
|
.update(evalEvaluation)
|
93
95
|
.set(value)
|
94
96
|
.where(and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)));
|
@@ -1,17 +1,19 @@
|
|
1
1
|
import { and, eq } from 'drizzle-orm';
|
2
2
|
|
3
3
|
import { NewEvaluationRecordsItem, evaluationRecords } from '@/database/schemas';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
|
6
6
|
export class EvaluationRecordModel {
|
7
7
|
private userId: string;
|
8
|
+
private db: LobeChatDatabase;
|
8
9
|
|
9
|
-
constructor(userId: string) {
|
10
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
11
|
+
this.db = db;
|
10
12
|
this.userId = userId;
|
11
13
|
}
|
12
14
|
|
13
15
|
create = async (params: NewEvaluationRecordsItem) => {
|
14
|
-
const [result] = await
|
16
|
+
const [result] = await this.db
|
15
17
|
.insert(evaluationRecords)
|
16
18
|
.values({ ...params, userId: this.userId })
|
17
19
|
.returning();
|
@@ -19,20 +21,20 @@ export class EvaluationRecordModel {
|
|
19
21
|
};
|
20
22
|
|
21
23
|
batchCreate = async (params: NewEvaluationRecordsItem[]) => {
|
22
|
-
return
|
24
|
+
return this.db
|
23
25
|
.insert(evaluationRecords)
|
24
26
|
.values(params.map((item) => ({ ...item, userId: this.userId })))
|
25
27
|
.returning();
|
26
28
|
};
|
27
29
|
|
28
30
|
delete = async (id: number) => {
|
29
|
-
return
|
31
|
+
return this.db
|
30
32
|
.delete(evaluationRecords)
|
31
33
|
.where(and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)));
|
32
34
|
};
|
33
35
|
|
34
36
|
query = async (reportId: number) => {
|
35
|
-
return
|
37
|
+
return this.db.query.evaluationRecords.findMany({
|
36
38
|
where: and(
|
37
39
|
eq(evaluationRecords.evaluationId, reportId),
|
38
40
|
eq(evaluationRecords.userId, this.userId),
|
@@ -41,13 +43,13 @@ export class EvaluationRecordModel {
|
|
41
43
|
};
|
42
44
|
|
43
45
|
findById = async (id: number) => {
|
44
|
-
return
|
46
|
+
return this.db.query.evaluationRecords.findFirst({
|
45
47
|
where: and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)),
|
46
48
|
});
|
47
49
|
};
|
48
50
|
|
49
51
|
findByEvaluationId = async (evaluationId: number) => {
|
50
|
-
return
|
52
|
+
return this.db.query.evaluationRecords.findMany({
|
51
53
|
where: and(
|
52
54
|
eq(evaluationRecords.evaluationId, evaluationId),
|
53
55
|
eq(evaluationRecords.userId, this.userId),
|
@@ -56,7 +58,7 @@ export class EvaluationRecordModel {
|
|
56
58
|
};
|
57
59
|
|
58
60
|
update = async (id: number, value: Partial<NewEvaluationRecordsItem>) => {
|
59
|
-
return
|
61
|
+
return this.db
|
60
62
|
.update(evaluationRecords)
|
61
63
|
.set(value)
|
62
64
|
.where(and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)));
|
@@ -32,7 +32,7 @@ const fileProcedure = asyncAuthedProcedure.use(async (opts) => {
|
|
32
32
|
ctx: {
|
33
33
|
asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
|
34
34
|
chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
|
35
|
-
chunkService: new ChunkService(ctx.userId),
|
35
|
+
chunkService: new ChunkService(ctx.serverDB, ctx.userId),
|
36
36
|
embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
|
37
37
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
38
38
|
fileService: new FileService(ctx.serverDB, ctx.userId),
|
@@ -25,11 +25,11 @@ const ragEvalProcedure = asyncAuthedProcedure.use(async (opts) => {
|
|
25
25
|
return opts.next({
|
26
26
|
ctx: {
|
27
27
|
chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
|
28
|
-
chunkService: new ChunkService(ctx.userId),
|
29
|
-
datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
|
28
|
+
chunkService: new ChunkService(ctx.serverDB, ctx.userId),
|
29
|
+
datasetRecordModel: new EvalDatasetRecordModel(ctx.serverDB, ctx.userId),
|
30
30
|
embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
|
31
|
-
evalRecordModel: new EvaluationRecordModel(ctx.userId),
|
32
|
-
evaluationModel: new EvalEvaluationModel(ctx.userId),
|
31
|
+
evalRecordModel: new EvaluationRecordModel(ctx.serverDB, ctx.userId),
|
32
|
+
evaluationModel: new EvalEvaluationModel(ctx.serverDB, ctx.userId),
|
33
33
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
34
34
|
},
|
35
35
|
});
|
@@ -26,7 +26,7 @@ const chunkProcedure = authedProcedure
|
|
26
26
|
ctx: {
|
27
27
|
asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
|
28
28
|
chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
|
29
|
-
chunkService: new ChunkService(ctx.userId),
|
29
|
+
chunkService: new ChunkService(ctx.serverDB, ctx.userId),
|
30
30
|
embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
|
31
31
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
32
32
|
messageModel: new MessageModel(ctx.serverDB, ctx.userId),
|
@@ -35,11 +35,11 @@ const ragEvalProcedure = authedProcedure
|
|
35
35
|
|
36
36
|
return opts.next({
|
37
37
|
ctx: {
|
38
|
-
datasetModel: new EvalDatasetModel(ctx.userId),
|
38
|
+
datasetModel: new EvalDatasetModel(ctx.serverDB, ctx.userId),
|
39
39
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
40
|
-
datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
|
41
|
-
evaluationModel: new EvalEvaluationModel(ctx.userId),
|
42
|
-
evaluationRecordModel: new EvaluationRecordModel(ctx.userId),
|
40
|
+
datasetRecordModel: new EvalDatasetRecordModel(ctx.serverDB, ctx.userId),
|
41
|
+
evaluationModel: new EvalEvaluationModel(ctx.serverDB, ctx.userId),
|
42
|
+
evaluationRecordModel: new EvaluationRecordModel(ctx.serverDB, ctx.userId),
|
43
43
|
fileService: new FileService(ctx.serverDB, ctx.userId),
|
44
44
|
},
|
45
45
|
});
|
@@ -58,7 +58,7 @@ export const userRouter = router({
|
|
58
58
|
if (enableClerk) {
|
59
59
|
const user = await ctx.clerkAuth.getCurrentUser();
|
60
60
|
if (user) {
|
61
|
-
const userService = new UserService();
|
61
|
+
const userService = new UserService(ctx.serverDB);
|
62
62
|
|
63
63
|
await userService.createUser(user.id, {
|
64
64
|
created_at: user.createdAt,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { ClientSecretPayload } from '@/const/auth';
|
2
2
|
import { AsyncTaskModel } from '@/database/models/asyncTask';
|
3
3
|
import { FileModel } from '@/database/models/file';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
import { ChunkContentParams, ContentChunk } from '@/server/modules/ContentChunk';
|
6
6
|
import { createAsyncCaller } from '@/server/routers/async';
|
7
7
|
import {
|
@@ -17,7 +17,7 @@ export class ChunkService {
|
|
17
17
|
private fileModel: FileModel;
|
18
18
|
private asyncTaskModel: AsyncTaskModel;
|
19
19
|
|
20
|
-
constructor(userId: string) {
|
20
|
+
constructor(serverDB: LobeChatDatabase, userId: string) {
|
21
21
|
this.userId = userId;
|
22
22
|
|
23
23
|
this.chunkClient = new ContentChunk();
|
@@ -2,15 +2,17 @@ import { NextResponse } from 'next/server';
|
|
2
2
|
|
3
3
|
import { UserModel } from '@/database/models/user';
|
4
4
|
import { UserItem } from '@/database/schemas';
|
5
|
-
import {
|
5
|
+
import { LobeChatDatabase } from '@/database/type';
|
6
6
|
import { pino } from '@/libs/logger';
|
7
7
|
import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter';
|
8
8
|
|
9
9
|
export class NextAuthUserService {
|
10
10
|
adapter;
|
11
|
+
private db: LobeChatDatabase;
|
11
12
|
|
12
|
-
constructor() {
|
13
|
-
this.
|
13
|
+
constructor(db: LobeChatDatabase) {
|
14
|
+
this.db = db;
|
15
|
+
this.adapter = LobeNextAuthDbAdapter(db);
|
14
16
|
}
|
15
17
|
|
16
18
|
safeUpdateUser = async (
|
@@ -27,7 +29,7 @@ export class NextAuthUserService {
|
|
27
29
|
|
28
30
|
// 2. If found, Update user data from provider
|
29
31
|
if (user?.id) {
|
30
|
-
const userModel = new UserModel(
|
32
|
+
const userModel = new UserModel(this.db, user.id);
|
31
33
|
|
32
34
|
// Perform update
|
33
35
|
await userModel.updateUser({
|
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
4
4
|
import { UserModel } from '@/database/models/user';
|
5
5
|
import { UserItem } from '@/database/schemas';
|
6
|
+
import { LobeChatDatabase } from '@/database/type';
|
6
7
|
import { pino } from '@/libs/logger';
|
7
8
|
import { AgentService } from '@/server/services/agent';
|
8
9
|
|
@@ -46,6 +47,7 @@ vi.mock('@/server/services/agent', () => ({
|
|
46
47
|
|
47
48
|
let service: UserService;
|
48
49
|
const mockUserId = 'test-user-id';
|
50
|
+
const mockDB = {} as LobeChatDatabase;
|
49
51
|
|
50
52
|
// Mock user data
|
51
53
|
const mockUserJSON: UserJSON = {
|
@@ -62,7 +64,7 @@ const mockUserJSON: UserJSON = {
|
|
62
64
|
} as unknown as UserJSON;
|
63
65
|
|
64
66
|
beforeEach(() => {
|
65
|
-
service = new UserService();
|
67
|
+
service = new UserService(mockDB);
|
66
68
|
vi.clearAllMocks();
|
67
69
|
});
|
68
70
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { UserJSON } from '@clerk/backend';
|
2
2
|
|
3
3
|
import { UserModel } from '@/database/models/user';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
import { initializeServerAnalytics } from '@/libs/analytics';
|
6
6
|
import { pino } from '@/libs/logger';
|
7
7
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
@@ -9,9 +9,15 @@ import { S3 } from '@/server/modules/S3';
|
|
9
9
|
import { AgentService } from '@/server/services/agent';
|
10
10
|
|
11
11
|
export class UserService {
|
12
|
+
private db: LobeChatDatabase;
|
13
|
+
|
14
|
+
constructor(db: LobeChatDatabase) {
|
15
|
+
this.db = db;
|
16
|
+
}
|
17
|
+
|
12
18
|
createUser = async (id: string, params: UserJSON) => {
|
13
19
|
// Check if user already exists
|
14
|
-
const res = await UserModel.findById(
|
20
|
+
const res = await UserModel.findById(this.db, id);
|
15
21
|
|
16
22
|
// If user already exists, skip creating a new user
|
17
23
|
if (res)
|
@@ -33,7 +39,7 @@ export class UserService {
|
|
33
39
|
/* ↑ cloud slot ↑ */
|
34
40
|
|
35
41
|
// 2. create user in database
|
36
|
-
await UserModel.createUser(
|
42
|
+
await UserModel.createUser(this.db, {
|
37
43
|
avatar: params.image_url,
|
38
44
|
clerkCreatedAt: new Date(params.created_at),
|
39
45
|
email: email?.email_address,
|
@@ -45,7 +51,7 @@ export class UserService {
|
|
45
51
|
});
|
46
52
|
|
47
53
|
// 3. Create an inbox session for the user
|
48
|
-
const agentService = new AgentService(
|
54
|
+
const agentService = new AgentService(this.db, id);
|
49
55
|
await agentService.createInbox();
|
50
56
|
|
51
57
|
/* ↓ cloud slot ↓ */
|
@@ -73,14 +79,14 @@ export class UserService {
|
|
73
79
|
};
|
74
80
|
|
75
81
|
deleteUser = async (id: string) => {
|
76
|
-
await UserModel.deleteUser(
|
82
|
+
await UserModel.deleteUser(this.db, id);
|
77
83
|
};
|
78
84
|
|
79
85
|
updateUser = async (id: string, params: UserJSON) => {
|
80
|
-
const userModel = new UserModel(
|
86
|
+
const userModel = new UserModel(this.db, id);
|
81
87
|
|
82
88
|
// Check if user already exists
|
83
|
-
const res = await UserModel.findById(
|
89
|
+
const res = await UserModel.findById(this.db, id);
|
84
90
|
|
85
91
|
// If user not exists, skip update the user
|
86
92
|
if (!res)
|
@@ -111,7 +117,7 @@ export class UserService {
|
|
111
117
|
};
|
112
118
|
|
113
119
|
getUserApiKeys = async (id: string) => {
|
114
|
-
return UserModel.getUserApiKeys(
|
120
|
+
return UserModel.getUserApiKeys(this.db, id, KeyVaultsGateKeeper.getUserKeyVaults);
|
115
121
|
};
|
116
122
|
|
117
123
|
getUserAvatar = async (id: string, image: string) => {
|