@lobehub/chat 1.42.6 → 1.43.0
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 +33 -0
- package/changelog/v1.json +12 -0
- package/docs/.cdn.cache.json +1 -0
- package/docs/changelog/2025-01-03-user-profile.mdx +27 -0
- package/docs/changelog/2025-01-03-user-profile.zh-CN.mdx +26 -0
- package/docs/self-hosting/advanced/auth/next-auth/wechat.mdx +3 -1
- package/docs/self-hosting/advanced/auth/next-auth/wechat.zh-CN.mdx +2 -2
- package/locales/ar/auth.json +76 -4
- package/locales/bg-BG/auth.json +75 -3
- package/locales/de-DE/auth.json +78 -6
- package/locales/en-US/auth.json +78 -6
- package/locales/es-ES/auth.json +75 -3
- package/locales/fa-IR/auth.json +77 -5
- package/locales/fr-FR/auth.json +78 -6
- package/locales/it-IT/auth.json +76 -4
- package/locales/ja-JP/auth.json +76 -4
- package/locales/ko-KR/auth.json +75 -3
- package/locales/nl-NL/auth.json +76 -4
- package/locales/pl-PL/auth.json +76 -4
- package/locales/pt-BR/auth.json +76 -4
- package/locales/ru-RU/auth.json +75 -3
- package/locales/tr-TR/auth.json +74 -3
- package/locales/vi-VN/auth.json +75 -3
- package/locales/zh-CN/auth.json +75 -3
- package/locales/zh-TW/auth.json +75 -3
- package/package.json +4 -3
- package/src/app/(main)/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +4 -0
- package/src/app/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -46
- package/src/app/(main)/(mobile)/me/(home)/features/UserBanner.tsx +11 -14
- package/src/app/(main)/(mobile)/me/(home)/features/useCategory.tsx +6 -21
- package/src/app/(main)/(mobile)/me/profile/features/Category.tsx +38 -21
- package/src/app/(main)/(mobile)/me/profile/layout.tsx +0 -3
- package/src/app/(main)/(mobile)/me/profile/page.tsx +3 -3
- package/src/app/(main)/chat/loading.tsx +2 -2
- package/src/app/(main)/discover/loading.tsx +2 -8
- package/src/app/(main)/files/loading.tsx +2 -2
- package/src/app/(main)/profile/(home)/Client.tsx +53 -0
- package/src/app/(main)/profile/(home)/[[...slugs]]/page.tsx +38 -0
- package/src/app/(main)/profile/@category/default.tsx +9 -0
- package/src/app/(main)/profile/@category/features/CategoryContent.tsx +38 -0
- package/src/app/(main)/profile/_layout/Desktop/Header.tsx +85 -0
- package/src/app/(main)/profile/_layout/Desktop/SideBar.tsx +42 -0
- package/src/app/(main)/profile/_layout/Desktop/index.tsx +48 -0
- package/src/app/(main)/profile/_layout/Mobile/Header.tsx +23 -5
- package/src/app/(main)/profile/_layout/Mobile/index.tsx +12 -5
- package/src/app/(main)/profile/_layout/type.ts +6 -0
- package/src/app/(main)/profile/error.tsx +5 -0
- package/src/app/(main)/profile/features/ClerkProfile.tsx +72 -0
- package/src/app/(main)/profile/hooks/useCategory.tsx +51 -0
- package/src/app/(main)/profile/layout.tsx +7 -17
- package/src/app/(main)/profile/loading.tsx +2 -22
- package/src/app/(main)/profile/not-found.tsx +3 -0
- package/src/app/(main)/profile/security/page.tsx +34 -0
- package/src/app/(main)/profile/stats/Client.tsx +52 -0
- package/src/app/(main)/profile/stats/features/AiHeatmaps.tsx +130 -0
- package/src/app/(main)/profile/stats/features/AssistantsRank.tsx +115 -0
- package/src/app/(main)/profile/stats/features/ModelsRank.tsx +84 -0
- package/src/app/(main)/profile/stats/features/ShareButton/Preview.tsx +159 -0
- package/src/app/(main)/profile/stats/features/ShareButton/ShareModal.tsx +87 -0
- package/src/app/(main)/profile/stats/features/ShareButton/TotalCard.tsx +39 -0
- package/src/app/(main)/profile/stats/features/ShareButton/index.tsx +26 -0
- package/src/app/(main)/profile/stats/features/TimeLabel.tsx +30 -0
- package/src/app/(main)/profile/stats/features/TopicsRank.tsx +103 -0
- package/src/app/(main)/profile/stats/features/TotalAssistants.tsx +56 -0
- package/src/app/(main)/profile/stats/features/TotalMessages.tsx +56 -0
- package/src/app/(main)/profile/stats/features/TotalTopics.tsx +53 -0
- package/src/app/(main)/profile/stats/features/TotalWords.tsx +54 -0
- package/src/app/(main)/profile/stats/features/Welcome.tsx +86 -0
- package/src/app/(main)/profile/{[[...slugs]] → stats}/page.tsx +4 -5
- package/src/app/(main)/repos/[id]/evals/dataset/page.tsx +2 -2
- package/src/app/(main)/repos/[id]/evals/evaluation/page.tsx +2 -2
- package/src/app/(main)/settings/@category/features/CategoryContent.tsx +1 -1
- package/src/app/(main)/settings/_layout/Desktop/index.tsx +1 -1
- package/src/app/(main)/settings/_layout/Mobile/Header.tsx +1 -1
- package/src/app/(main)/settings/_layout/Mobile/index.tsx +2 -0
- package/src/app/(main)/settings/common/features/Theme/index.tsx +2 -17
- package/src/app/(main)/settings/loading.tsx +2 -2
- package/src/components/Loading/BrandTextLoading/index.tsx +2 -2
- package/src/components/Statistic/index.tsx +15 -0
- package/src/components/StatisticCard/TitleWithPercentage.tsx +80 -0
- package/src/components/StatisticCard/growthPercentage.tsx +8 -0
- package/src/components/StatisticCard/index.tsx +209 -0
- package/src/const/url.ts +3 -3
- package/src/database/server/models/__tests__/message.test.ts +346 -35
- package/src/database/server/models/__tests__/session.test.ts +185 -2
- package/src/database/server/models/__tests__/topic.test.ts +136 -0
- package/src/database/server/models/__tests__/user.test.ts +140 -1
- package/src/database/server/models/message.ts +109 -14
- package/src/database/server/models/session.ts +75 -4
- package/src/database/server/models/topic.ts +43 -3
- package/src/database/server/models/user.ts +22 -0
- package/src/database/utils/genWhere.ts +39 -0
- package/src/features/ShareModal/ShareImage/index.tsx +11 -24
- package/src/features/ShareModal/ShareImage/type.ts +1 -6
- package/src/features/User/DataStatistics.tsx +21 -14
- package/src/features/User/UserPanel/PanelContent.tsx +12 -16
- package/src/features/User/UserPanel/useMenu.tsx +4 -6
- package/src/features/User/__tests__/PanelContent.test.tsx +4 -0
- package/src/features/User/__tests__/useMenu.test.tsx +1 -21
- package/src/hooks/useActiveTabKey.ts +34 -1
- package/src/{features/ShareModal/ShareImage → hooks}/useScreenshot.ts +51 -6
- package/src/locales/default/auth.ts +74 -2
- package/src/server/ld.test.ts +1 -1
- package/src/server/modules/AssistantStore/index.ts +3 -2
- package/src/server/routers/lambda/message.ts +35 -6
- package/src/server/routers/lambda/session.ts +17 -3
- package/src/server/routers/lambda/topic.ts +17 -3
- package/src/server/routers/lambda/user.ts +4 -0
- package/src/server/services/changelog/index.ts +1 -1
- package/src/services/message/_deprecated.ts +16 -0
- package/src/services/message/client.test.ts +0 -18
- package/src/services/message/client.ts +12 -9
- package/src/services/message/server.ts +12 -4
- package/src/services/message/type.ts +15 -3
- package/src/services/session/_deprecated.ts +5 -0
- package/src/services/session/client.ts +6 -2
- package/src/services/session/server.ts +6 -2
- package/src/services/session/type.ts +7 -1
- package/src/services/topic/_deprecated.ts +5 -0
- package/src/services/topic/client.ts +6 -2
- package/src/services/topic/server.ts +7 -1
- package/src/services/topic/type.ts +7 -2
- package/src/services/user/_deprecated.ts +4 -0
- package/src/services/user/client.ts +4 -0
- package/src/services/user/server.ts +4 -0
- package/src/services/user/type.ts +5 -0
- package/src/store/global/initialState.ts +6 -0
- package/src/store/user/slices/auth/action.test.ts +1 -33
- package/src/store/user/slices/auth/action.ts +0 -9
- package/src/store/user/slices/common/action.test.ts +2 -2
- package/src/types/message/index.ts +5 -0
- package/src/types/session/index.ts +8 -0
- package/src/types/topic/topic.ts +7 -0
- package/src/utils/format.ts +1 -1
- package/src/utils/time.ts +23 -0
- package/src/app/(main)/profile/[[...slugs]]/Client.tsx +0 -76
- package/src/components/Loading/BrandTextLoading/LobeChatText/SVG.tsx +0 -44
- package/src/components/Loading/BrandTextLoading/LobeChatText/index.tsx +0 -6
- package/src/components/Loading/BrandTextLoading/LobeChatText/style.css +0 -32
- package/src/hooks/useActiveSettingsKey.ts +0 -20
@@ -1,8 +1,80 @@
|
|
1
1
|
export default {
|
2
|
+
date: {
|
3
|
+
prevMonth: '上个月',
|
4
|
+
recent30Days: '最近30天',
|
5
|
+
},
|
6
|
+
header: {
|
7
|
+
desc: '管理您的账户信息。',
|
8
|
+
title: '账户',
|
9
|
+
},
|
10
|
+
heatmaps: {
|
11
|
+
legend: {
|
12
|
+
less: '不活跃',
|
13
|
+
more: '活跃',
|
14
|
+
},
|
15
|
+
months: {
|
16
|
+
apr: '四月',
|
17
|
+
aug: '八月',
|
18
|
+
dec: '十二月',
|
19
|
+
feb: '二月',
|
20
|
+
jan: '一月',
|
21
|
+
jul: '七月',
|
22
|
+
jun: '六月',
|
23
|
+
mar: '三月',
|
24
|
+
may: '五月',
|
25
|
+
nov: '十一月',
|
26
|
+
oct: '十月',
|
27
|
+
sep: '九月',
|
28
|
+
},
|
29
|
+
tooltip: '{{date}} 当日发送 {{count}} 条消息',
|
30
|
+
totalCount: '过去一年共发送 {{count}} 条消息',
|
31
|
+
},
|
2
32
|
login: '登录',
|
3
33
|
loginOrSignup: '登录 / 注册',
|
4
|
-
profile:
|
5
|
-
|
34
|
+
profile: {
|
35
|
+
avatar: '头像',
|
36
|
+
email: '电子邮件地址',
|
37
|
+
username: '用户名',
|
38
|
+
},
|
6
39
|
signout: '退出登录',
|
7
40
|
signup: '注册',
|
41
|
+
stats: {
|
42
|
+
aiheatmaps: 'AI 指数',
|
43
|
+
assistants: '助手数',
|
44
|
+
assistantsRank: {
|
45
|
+
left: '助手名称',
|
46
|
+
right: '话题数',
|
47
|
+
title: '助手使用率',
|
48
|
+
},
|
49
|
+
createdAt: '用户创建于',
|
50
|
+
days: '天',
|
51
|
+
empty: {
|
52
|
+
desc: '请积累更多聊天数据后查看',
|
53
|
+
title: '暂无数据',
|
54
|
+
},
|
55
|
+
lastYearActivity: '过去一年活跃度',
|
56
|
+
messages: '消息数',
|
57
|
+
modelsRank: {
|
58
|
+
left: '模型名称',
|
59
|
+
right: '消息数',
|
60
|
+
title: '模型使用率',
|
61
|
+
},
|
62
|
+
share: {
|
63
|
+
title: '我的 AI 活跃指数',
|
64
|
+
},
|
65
|
+
topics: '话题数',
|
66
|
+
topicsRank: {
|
67
|
+
left: '话题名称',
|
68
|
+
right: '消息数',
|
69
|
+
title: '话题内容量',
|
70
|
+
},
|
71
|
+
updatedAt: '数据更新至',
|
72
|
+
welcome: '{{username}}, 这是你和 {{appName}} 相伴的第 <span>{{days}}</span> 天',
|
73
|
+
words: '累计字数',
|
74
|
+
},
|
75
|
+
tab: {
|
76
|
+
profile: '个人资料',
|
77
|
+
security: '安全',
|
78
|
+
stats: '数据统计',
|
79
|
+
},
|
8
80
|
};
|
package/src/server/ld.test.ts
CHANGED
@@ -36,7 +36,7 @@ export class AssistantStore {
|
|
36
36
|
}
|
37
37
|
|
38
38
|
if (!res.ok) {
|
39
|
-
console.
|
39
|
+
console.warn('fetch agent index error:', await res.text());
|
40
40
|
return [];
|
41
41
|
}
|
42
42
|
|
@@ -55,7 +55,8 @@ export class AssistantStore {
|
|
55
55
|
|
56
56
|
return data;
|
57
57
|
} catch (e) {
|
58
|
-
console.error('fetch agent index error:'
|
58
|
+
console.error('[AgentIndexFetchError] failed to fetch agent index, error detail:');
|
59
|
+
console.error(e);
|
59
60
|
|
60
61
|
throw e;
|
61
62
|
}
|
@@ -27,12 +27,33 @@ export const messageRouter = router({
|
|
27
27
|
return { added: data.rowCount as number, ids: [], skips: [], success: true };
|
28
28
|
}),
|
29
29
|
|
30
|
-
count: messageProcedure
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
count: messageProcedure
|
31
|
+
.input(
|
32
|
+
z
|
33
|
+
.object({
|
34
|
+
endDate: z.string().optional(),
|
35
|
+
range: z.tuple([z.string(), z.string()]).optional(),
|
36
|
+
startDate: z.string().optional(),
|
37
|
+
})
|
38
|
+
.optional(),
|
39
|
+
)
|
40
|
+
.query(async ({ ctx, input }) => {
|
41
|
+
return ctx.messageModel.count(input);
|
42
|
+
}),
|
43
|
+
|
44
|
+
countWords: messageProcedure
|
45
|
+
.input(
|
46
|
+
z
|
47
|
+
.object({
|
48
|
+
endDate: z.string().optional(),
|
49
|
+
range: z.tuple([z.string(), z.string()]).optional(),
|
50
|
+
startDate: z.string().optional(),
|
51
|
+
})
|
52
|
+
.optional(),
|
53
|
+
)
|
54
|
+
.query(async ({ ctx, input }) => {
|
55
|
+
return ctx.messageModel.countWords(input);
|
56
|
+
}),
|
36
57
|
|
37
58
|
createMessage: messageProcedure
|
38
59
|
.input(z.object({}).passthrough().partial())
|
@@ -56,6 +77,10 @@ export const messageRouter = router({
|
|
56
77
|
return ctx.messageModel.queryBySessionId(input.sessionId);
|
57
78
|
}),
|
58
79
|
|
80
|
+
getHeatmaps: messageProcedure.query(async ({ ctx }) => {
|
81
|
+
return ctx.messageModel.getHeatmaps();
|
82
|
+
}),
|
83
|
+
|
59
84
|
// TODO: 未来这部分方法也需要使用 authedProcedure
|
60
85
|
getMessages: publicProcedure
|
61
86
|
.input(
|
@@ -74,6 +99,10 @@ export const messageRouter = router({
|
|
74
99
|
return messageModel.query(input, { postProcessUrl: (path) => getFullFileUrl(path) });
|
75
100
|
}),
|
76
101
|
|
102
|
+
rankModels: messageProcedure.query(async ({ ctx }) => {
|
103
|
+
return ctx.messageModel.rankModels();
|
104
|
+
}),
|
105
|
+
|
77
106
|
removeAllMessages: messageProcedure.mutation(async ({ ctx }) => {
|
78
107
|
return ctx.messageModel.deleteAllMessages();
|
79
108
|
}),
|
@@ -57,9 +57,19 @@ export const sessionRouter = router({
|
|
57
57
|
return data?.id;
|
58
58
|
}),
|
59
59
|
|
60
|
-
countSessions: sessionProcedure
|
61
|
-
|
62
|
-
|
60
|
+
countSessions: sessionProcedure
|
61
|
+
.input(
|
62
|
+
z
|
63
|
+
.object({
|
64
|
+
endDate: z.string().optional(),
|
65
|
+
range: z.tuple([z.string(), z.string()]).optional(),
|
66
|
+
startDate: z.string().optional(),
|
67
|
+
})
|
68
|
+
.optional(),
|
69
|
+
)
|
70
|
+
.query(async ({ ctx, input }) => {
|
71
|
+
return ctx.sessionModel.count(input);
|
72
|
+
}),
|
63
73
|
|
64
74
|
createSession: sessionProcedure
|
65
75
|
.input(
|
@@ -103,6 +113,10 @@ export const sessionRouter = router({
|
|
103
113
|
return ctx.sessionModel.query({ current, pageSize });
|
104
114
|
}),
|
105
115
|
|
116
|
+
rankSessions: sessionProcedure.input(z.number().optional()).query(async ({ ctx, input }) => {
|
117
|
+
return ctx.sessionModel.rank(input);
|
118
|
+
}),
|
119
|
+
|
106
120
|
removeAllSessions: sessionProcedure.mutation(async ({ ctx }) => {
|
107
121
|
return ctx.sessionModel.deleteAll();
|
108
122
|
}),
|
@@ -56,9 +56,19 @@ export const topicRouter = router({
|
|
56
56
|
return data.topic.id;
|
57
57
|
}),
|
58
58
|
|
59
|
-
countTopics: topicProcedure
|
60
|
-
|
61
|
-
|
59
|
+
countTopics: topicProcedure
|
60
|
+
.input(
|
61
|
+
z
|
62
|
+
.object({
|
63
|
+
endDate: z.string().optional(),
|
64
|
+
range: z.tuple([z.string(), z.string()]).optional(),
|
65
|
+
startDate: z.string().optional(),
|
66
|
+
})
|
67
|
+
.optional(),
|
68
|
+
)
|
69
|
+
.query(async ({ ctx, input }) => {
|
70
|
+
return ctx.topicModel.count(input);
|
71
|
+
}),
|
62
72
|
|
63
73
|
createTopic: topicProcedure
|
64
74
|
.input(
|
@@ -100,6 +110,10 @@ export const topicRouter = router({
|
|
100
110
|
return (await ctx.topicModel.count()) === 0;
|
101
111
|
}),
|
102
112
|
|
113
|
+
rankTopics: topicProcedure.input(z.number().optional()).query(async ({ ctx, input }) => {
|
114
|
+
return ctx.topicModel.rank(input);
|
115
|
+
}),
|
116
|
+
|
103
117
|
removeAllTopics: topicProcedure.mutation(async ({ ctx }) => {
|
104
118
|
return ctx.topicModel.deleteAll();
|
105
119
|
}),
|
@@ -20,6 +20,10 @@ const userProcedure = authedProcedure.use(async (opts) => {
|
|
20
20
|
});
|
21
21
|
|
22
22
|
export const userRouter = router({
|
23
|
+
getUserRegistrationDuration: userProcedure.query(async ({ ctx }) => {
|
24
|
+
return ctx.userModel.getUserRegistrationDuration();
|
25
|
+
}),
|
26
|
+
|
23
27
|
getUserState: userProcedure.query(async ({ ctx }): Promise<UserInitializationState> => {
|
24
28
|
let state: Awaited<ReturnType<UserModel['getUserState']>> | undefined;
|
25
29
|
|
@@ -54,7 +54,7 @@ export class ChangelogService {
|
|
54
54
|
return this.mergeChangelogs(data.cloud, data.community).slice(0, 5);
|
55
55
|
} catch (e) {
|
56
56
|
const cause = (e as Error).cause as { code: string };
|
57
|
-
if (cause
|
57
|
+
if (cause?.code.includes('ETIMEDOUT')) {
|
58
58
|
console.warn(
|
59
59
|
'[ChangelogFetchTimeout] fail to fetch changelog lists due to network timeout. Please check your network connection.',
|
60
60
|
);
|
@@ -10,6 +10,7 @@ import {
|
|
10
10
|
ChatTTS,
|
11
11
|
ChatTranslate,
|
12
12
|
CreateMessageParams,
|
13
|
+
ModelRankItem,
|
13
14
|
} from '@/types/message';
|
14
15
|
|
15
16
|
import { IMessageService } from './type';
|
@@ -56,6 +57,21 @@ export class ClientService implements IMessageService {
|
|
56
57
|
return MessageModel.count();
|
57
58
|
}
|
58
59
|
|
60
|
+
// @ts-ignore
|
61
|
+
async rankModels(): Promise<ModelRankItem[]> {
|
62
|
+
throw new Error('Method not implemented.');
|
63
|
+
}
|
64
|
+
|
65
|
+
// @ts-ignore
|
66
|
+
async countWords(): Promise<number> {
|
67
|
+
throw new Error('Method not implemented.');
|
68
|
+
}
|
69
|
+
|
70
|
+
// @ts-ignore
|
71
|
+
async getHeatmaps() {
|
72
|
+
throw new Error('Method not implemented.');
|
73
|
+
}
|
74
|
+
|
59
75
|
async countTodayMessages() {
|
60
76
|
const topics = await MessageModel.queryAll();
|
61
77
|
return topics.filter(
|
@@ -350,24 +350,6 @@ describe('MessageClientService', () => {
|
|
350
350
|
});
|
351
351
|
});
|
352
352
|
|
353
|
-
describe('countTodayMessages', () => {
|
354
|
-
it('should count the number of messages created today', async () => {
|
355
|
-
// Setup
|
356
|
-
const mockMessages = [
|
357
|
-
{ ...mockMessage, id: undefined, createdAt: new Date(), userId },
|
358
|
-
{ ...mockMessage, id: undefined, createdAt: new Date(), userId },
|
359
|
-
{ ...mockMessage, id: undefined, createdAt: new Date('2023-01-01'), userId },
|
360
|
-
];
|
361
|
-
await clientDB.insert(messages).values(mockMessages);
|
362
|
-
|
363
|
-
// Execute
|
364
|
-
const count = await messageService.countTodayMessages();
|
365
|
-
|
366
|
-
// Assert
|
367
|
-
expect(count).toBe(2);
|
368
|
-
});
|
369
|
-
});
|
370
|
-
|
371
353
|
describe('updateMessageTTS', () => {
|
372
354
|
it('should update the TTS field of a message', async () => {
|
373
355
|
// Setup
|
@@ -1,5 +1,3 @@
|
|
1
|
-
import dayjs from 'dayjs';
|
2
|
-
|
3
1
|
import { INBOX_SESSION_ID } from '@/const/session';
|
4
2
|
import { clientDB } from '@/database/client/db';
|
5
3
|
import { MessageModel } from '@/database/server/models/message';
|
@@ -52,15 +50,20 @@ export class ClientService extends BaseClientService implements IMessageService
|
|
52
50
|
return data as unknown as ChatMessage[];
|
53
51
|
};
|
54
52
|
|
55
|
-
countMessages: IMessageService['countMessages'] = async () => {
|
56
|
-
return this.messageModel.count();
|
53
|
+
countMessages: IMessageService['countMessages'] = async (params) => {
|
54
|
+
return this.messageModel.count(params);
|
55
|
+
};
|
56
|
+
|
57
|
+
countWords: IMessageService['countWords'] = async (params) => {
|
58
|
+
return this.messageModel.countWords(params);
|
59
|
+
};
|
60
|
+
|
61
|
+
rankModels: IMessageService['rankModels'] = async () => {
|
62
|
+
return this.messageModel.rankModels();
|
57
63
|
};
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
return topics.filter(
|
62
|
-
(item) => dayjs(item.createdAt).format('YYYY-MM-DD') === dayjs().format('YYYY-MM-DD'),
|
63
|
-
).length;
|
65
|
+
getHeatmaps: IMessageService['getHeatmaps'] = async () => {
|
66
|
+
return this.messageModel.getHeatmaps();
|
64
67
|
};
|
65
68
|
|
66
69
|
getAllMessagesInSession: IMessageService['getAllMessagesInSession'] = async (sessionId) => {
|
@@ -36,12 +36,20 @@ export class ServerService implements IMessageService {
|
|
36
36
|
});
|
37
37
|
};
|
38
38
|
|
39
|
-
countMessages: IMessageService['countMessages'] = async () => {
|
40
|
-
return lambdaClient.message.count.query();
|
39
|
+
countMessages: IMessageService['countMessages'] = async (params) => {
|
40
|
+
return lambdaClient.message.count.query(params);
|
41
41
|
};
|
42
42
|
|
43
|
-
|
44
|
-
return lambdaClient.message.
|
43
|
+
countWords: IMessageService['countWords'] = async (params) => {
|
44
|
+
return lambdaClient.message.countWords.query(params);
|
45
|
+
};
|
46
|
+
|
47
|
+
rankModels: IMessageService['rankModels'] = async () => {
|
48
|
+
return lambdaClient.message.rankModels.query();
|
49
|
+
};
|
50
|
+
|
51
|
+
getHeatmaps: IMessageService['getHeatmaps'] = async () => {
|
52
|
+
return lambdaClient.message.getHeatmaps.query();
|
45
53
|
};
|
46
54
|
|
47
55
|
updateMessageError: IMessageService['updateMessageError'] = async (id, error) => {
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import type { HeatmapsProps } from '@lobehub/charts';
|
2
|
+
|
1
3
|
import { MessageItem } from '@/database/schemas';
|
2
4
|
import {
|
3
5
|
ChatMessage,
|
@@ -5,6 +7,7 @@ import {
|
|
5
7
|
ChatTTS,
|
6
8
|
ChatTranslate,
|
7
9
|
CreateMessageParams,
|
10
|
+
ModelRankItem,
|
8
11
|
} from '@/types/message';
|
9
12
|
|
10
13
|
/* eslint-disable typescript-sort-keys/interface */
|
@@ -16,9 +19,18 @@ export interface IMessageService {
|
|
16
19
|
getMessages(sessionId: string, topicId?: string): Promise<ChatMessage[]>;
|
17
20
|
getAllMessages(): Promise<ChatMessage[]>;
|
18
21
|
getAllMessagesInSession(sessionId: string): Promise<ChatMessage[]>;
|
19
|
-
countMessages(
|
20
|
-
|
21
|
-
|
22
|
+
countMessages(params?: {
|
23
|
+
endDate?: string;
|
24
|
+
range?: [string, string];
|
25
|
+
startDate?: string;
|
26
|
+
}): Promise<number>;
|
27
|
+
countWords(params?: {
|
28
|
+
endDate?: string;
|
29
|
+
range?: [string, string];
|
30
|
+
startDate?: string;
|
31
|
+
}): Promise<number>;
|
32
|
+
rankModels(): Promise<ModelRankItem[]>;
|
33
|
+
getHeatmaps(): Promise<HeatmapsProps['data']>;
|
22
34
|
updateMessageError(id: string, error: ChatMessageError): Promise<any>;
|
23
35
|
updateMessage(id: string, message: Partial<MessageItem>): Promise<any>;
|
24
36
|
updateMessageTTS(id: string, tts: Partial<ChatTTS> | false): Promise<any>;
|
@@ -82,6 +82,11 @@ export class ClientService implements ISessionService {
|
|
82
82
|
return SessionModel.count();
|
83
83
|
}
|
84
84
|
|
85
|
+
// @ts-ignore
|
86
|
+
async rankSessions() {
|
87
|
+
throw new Error('Method not implemented.');
|
88
|
+
}
|
89
|
+
|
85
90
|
async hasSessions() {
|
86
91
|
return (await this.countSessions()) !== 0;
|
87
92
|
}
|
@@ -74,8 +74,12 @@ export class ClientService extends BaseClientService implements ISessionService
|
|
74
74
|
}
|
75
75
|
};
|
76
76
|
|
77
|
-
countSessions: ISessionService['countSessions'] = async () => {
|
78
|
-
return this.sessionModel.count();
|
77
|
+
countSessions: ISessionService['countSessions'] = async (params) => {
|
78
|
+
return this.sessionModel.count(params);
|
79
|
+
};
|
80
|
+
|
81
|
+
rankSessions: ISessionService['rankSessions'] = async (limit) => {
|
82
|
+
return this.sessionModel.rank(limit);
|
79
83
|
};
|
80
84
|
|
81
85
|
searchSessions: ISessionService['searchSessions'] = async (keyword) => {
|
@@ -36,8 +36,12 @@ export class ServerService implements ISessionService {
|
|
36
36
|
return lambdaClient.session.getGroupedSessions.query();
|
37
37
|
};
|
38
38
|
|
39
|
-
countSessions: ISessionService['countSessions'] = () => {
|
40
|
-
return lambdaClient.session.countSessions.query();
|
39
|
+
countSessions: ISessionService['countSessions'] = async (params) => {
|
40
|
+
return lambdaClient.session.countSessions.query(params);
|
41
|
+
};
|
42
|
+
|
43
|
+
rankSessions: ISessionService['rankSessions'] = async (limit) => {
|
44
|
+
return lambdaClient.session.rankSessions.query(limit);
|
41
45
|
};
|
42
46
|
|
43
47
|
updateSession: ISessionService['updateSession'] = (id, data) => {
|
@@ -11,6 +11,7 @@ import {
|
|
11
11
|
LobeSessions,
|
12
12
|
SessionGroupItem,
|
13
13
|
SessionGroups,
|
14
|
+
SessionRankItem,
|
14
15
|
UpdateSessionParams,
|
15
16
|
} from '@/types/session';
|
16
17
|
|
@@ -31,7 +32,12 @@ export interface ISessionService {
|
|
31
32
|
* @deprecated
|
32
33
|
*/
|
33
34
|
getSessionsByType(type?: 'agent' | 'group' | 'all'): Promise<LobeSessions>;
|
34
|
-
countSessions(
|
35
|
+
countSessions(params?: {
|
36
|
+
endDate?: string;
|
37
|
+
range?: [string, string];
|
38
|
+
startDate?: string;
|
39
|
+
}): Promise<number>;
|
40
|
+
rankSessions(limit?: number): Promise<SessionRankItem[]>;
|
35
41
|
searchSessions(keyword: string): Promise<LobeSessions>;
|
36
42
|
|
37
43
|
updateSession(id: string, data: Partial<UpdateSessionParams>): Promise<any>;
|
@@ -38,6 +38,11 @@ export class ClientService implements ITopicService {
|
|
38
38
|
return TopicModel.count();
|
39
39
|
}
|
40
40
|
|
41
|
+
// @ts-ignore
|
42
|
+
async rankTopics() {
|
43
|
+
throw new Error('Method not implemented.');
|
44
|
+
}
|
45
|
+
|
41
46
|
async updateTopicFavorite(id: string, favorite?: boolean) {
|
42
47
|
return this.updateTopic(id, { favorite });
|
43
48
|
}
|
@@ -55,8 +55,12 @@ export class ClientService extends BaseClientService implements ITopicService {
|
|
55
55
|
return data as unknown as Promise<ChatTopic[]>;
|
56
56
|
};
|
57
57
|
|
58
|
-
countTopics: ITopicService['countTopics'] = async () => {
|
59
|
-
return this.topicModel.count();
|
58
|
+
countTopics: ITopicService['countTopics'] = async (params) => {
|
59
|
+
return this.topicModel.count(params);
|
60
|
+
};
|
61
|
+
|
62
|
+
rankTopics: ITopicService['rankTopics'] = async (limit) => {
|
63
|
+
return this.topicModel.rank(limit);
|
60
64
|
};
|
61
65
|
|
62
66
|
updateTopic: ITopicService['updateTopic'] = async (id, data) => {
|
@@ -24,7 +24,13 @@ export class ServerService implements ITopicService {
|
|
24
24
|
getAllTopics: ITopicService['getAllTopics'] = () =>
|
25
25
|
lambdaClient.topic.getAllTopics.query() as any;
|
26
26
|
|
27
|
-
countTopics: ITopicService['countTopics'] = async () =>
|
27
|
+
countTopics: ITopicService['countTopics'] = async (params) => {
|
28
|
+
return lambdaClient.topic.countTopics.query(params);
|
29
|
+
};
|
30
|
+
|
31
|
+
rankTopics: ITopicService['rankTopics'] = async (limit) => {
|
32
|
+
return lambdaClient.topic.rankTopics.query(limit);
|
33
|
+
};
|
28
34
|
|
29
35
|
searchTopics: ITopicService['searchTopics'] = (keywords, sessionId) =>
|
30
36
|
lambdaClient.topic.searchTopics.query({
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* eslint-disable typescript-sort-keys/interface */
|
2
2
|
import { BatchTaskResult } from '@/types/service';
|
3
|
-
import { ChatTopic } from '@/types/topic';
|
3
|
+
import { ChatTopic, TopicRankItem } from '@/types/topic';
|
4
4
|
|
5
5
|
export interface CreateTopicParams {
|
6
6
|
favorite?: boolean;
|
@@ -22,7 +22,12 @@ export interface ITopicService {
|
|
22
22
|
|
23
23
|
getTopics(params: QueryTopicParams): Promise<ChatTopic[]>;
|
24
24
|
getAllTopics(): Promise<ChatTopic[]>;
|
25
|
-
countTopics(
|
25
|
+
countTopics(params?: {
|
26
|
+
endDate?: string;
|
27
|
+
range?: [string, string];
|
28
|
+
startDate?: string;
|
29
|
+
}): Promise<number>;
|
30
|
+
rankTopics(limit?: number): Promise<TopicRankItem[]>;
|
26
31
|
searchTopics(keyword: string, sessionId?: string): Promise<ChatTopic[]>;
|
27
32
|
|
28
33
|
updateTopic(id: string, data: Partial<ChatTopic>): Promise<any>;
|
@@ -16,6 +16,10 @@ export class ClientService implements IUserService {
|
|
16
16
|
this.preferenceStorage = new AsyncLocalStorage('LOBE_PREFERENCE');
|
17
17
|
}
|
18
18
|
|
19
|
+
getUserRegistrationDuration = async () => {
|
20
|
+
throw new Error('Method not implemented.');
|
21
|
+
};
|
22
|
+
|
19
23
|
async getUserState(): Promise<UserInitializationState> {
|
20
24
|
const user = await UserModel.getUser();
|
21
25
|
const messageCount = await MessageModel.count();
|
@@ -27,6 +27,10 @@ export class ClientService extends BaseClientService implements IUserService {
|
|
27
27
|
this.preferenceStorage = new AsyncLocalStorage('LOBE_PREFERENCE');
|
28
28
|
}
|
29
29
|
|
30
|
+
getUserRegistrationDuration: IUserService['getUserRegistrationDuration'] = async () => {
|
31
|
+
return this.userModel.getUserRegistrationDuration();
|
32
|
+
};
|
33
|
+
|
30
34
|
getUserState: IUserService['getUserState'] = async () => {
|
31
35
|
// if user not exist in the db, create one to make sure the user exist
|
32
36
|
await this.makeSureUserExist();
|
@@ -2,6 +2,10 @@ import { lambdaClient } from '@/libs/trpc/client';
|
|
2
2
|
import { IUserService } from '@/services/user/type';
|
3
3
|
|
4
4
|
export class ServerService implements IUserService {
|
5
|
+
getUserRegistrationDuration: IUserService['getUserRegistrationDuration'] = async () => {
|
6
|
+
return lambdaClient.user.getUserRegistrationDuration.query();
|
7
|
+
};
|
8
|
+
|
5
9
|
getUserState: IUserService['getUserState'] = async () => {
|
6
10
|
return lambdaClient.user.getUserState.query();
|
7
11
|
};
|
@@ -4,6 +4,11 @@ import { UserGuide, UserInitializationState, UserPreference } from '@/types/user
|
|
4
4
|
import { UserSettings } from '@/types/user/settings';
|
5
5
|
|
6
6
|
export interface IUserService {
|
7
|
+
getUserRegistrationDuration: () => Promise<{
|
8
|
+
createdAt: string;
|
9
|
+
duration: number;
|
10
|
+
updatedAt: string;
|
11
|
+
}>;
|
7
12
|
getUserState: () => Promise<UserInitializationState>;
|
8
13
|
resetUserSettings: () => Promise<any>;
|
9
14
|
updateGuide: (guide: Partial<UserGuide>) => Promise<any>;
|
@@ -31,6 +31,12 @@ export enum SettingsTabs {
|
|
31
31
|
TTS = 'tts',
|
32
32
|
}
|
33
33
|
|
34
|
+
export enum ProfileTabs {
|
35
|
+
Profile = 'profile',
|
36
|
+
Security = 'security',
|
37
|
+
Stats = 'stats',
|
38
|
+
}
|
39
|
+
|
34
40
|
export interface SystemStatus {
|
35
41
|
// which sessionGroup should expand
|
36
42
|
expandSessionGroupKeys: string[];
|
@@ -1,11 +1,8 @@
|
|
1
|
-
import { act, renderHook
|
1
|
+
import { act, renderHook } from '@testing-library/react';
|
2
2
|
import { mutate } from 'swr';
|
3
3
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
4
|
-
import { withSWR } from '~test-utils';
|
5
4
|
|
6
|
-
import { userService } from '@/services/user';
|
7
5
|
import { useUserStore } from '@/store/user';
|
8
|
-
import { switchLang } from '@/utils/client/switchLang';
|
9
6
|
|
10
7
|
vi.mock('zustand/traditional');
|
11
8
|
|
@@ -170,33 +167,4 @@ describe('createAuthSlice', () => {
|
|
170
167
|
expect(signIn).not.toHaveBeenCalled();
|
171
168
|
});
|
172
169
|
});
|
173
|
-
|
174
|
-
describe('openUserProfile', () => {
|
175
|
-
it('should call clerkOpenUserProfile when Clerk is enabled', async () => {
|
176
|
-
enableClerk = true;
|
177
|
-
|
178
|
-
const clerkOpenUserProfileMock = vi.fn();
|
179
|
-
useUserStore.setState({ clerkOpenUserProfile: clerkOpenUserProfileMock });
|
180
|
-
|
181
|
-
const { result } = renderHook(() => useUserStore());
|
182
|
-
|
183
|
-
await act(async () => {
|
184
|
-
await result.current.openUserProfile();
|
185
|
-
});
|
186
|
-
|
187
|
-
expect(clerkOpenUserProfileMock).toHaveBeenCalled();
|
188
|
-
});
|
189
|
-
it('should not call clerkOpenUserProfile when Clerk is disabled', async () => {
|
190
|
-
const clerkOpenUserProfileMock = vi.fn();
|
191
|
-
useUserStore.setState({ clerkOpenUserProfile: clerkOpenUserProfileMock });
|
192
|
-
|
193
|
-
const { result } = renderHook(() => useUserStore());
|
194
|
-
|
195
|
-
await act(async () => {
|
196
|
-
await result.current.openUserProfile();
|
197
|
-
});
|
198
|
-
|
199
|
-
expect(clerkOpenUserProfileMock).not.toHaveBeenCalled();
|
200
|
-
});
|
201
|
-
});
|
202
170
|
});
|