@lobehub/chat 1.36.38 → 1.36.40
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 +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/common.json +7 -3
- package/locales/bg-BG/common.json +7 -3
- package/locales/de-DE/common.json +7 -3
- package/locales/en-US/common.json +7 -3
- package/locales/es-ES/common.json +7 -3
- package/locales/fa-IR/common.json +7 -3
- package/locales/fr-FR/common.json +7 -3
- package/locales/it-IT/common.json +7 -3
- package/locales/ja-JP/common.json +7 -3
- package/locales/ko-KR/common.json +7 -3
- package/locales/nl-NL/common.json +7 -3
- package/locales/pl-PL/common.json +7 -3
- package/locales/pt-BR/common.json +7 -3
- package/locales/ru-RU/common.json +7 -3
- package/locales/tr-TR/common.json +7 -3
- package/locales/vi-VN/common.json +7 -3
- package/locales/zh-CN/common.json +8 -4
- package/locales/zh-TW/common.json +7 -3
- package/package.json +1 -2
- package/src/app/(main)/(mobile)/me/(home)/page.tsx +2 -2
- package/src/app/(main)/(mobile)/me/data/page.tsx +2 -2
- package/src/app/(main)/(mobile)/me/profile/page.tsx +2 -2
- package/src/app/(main)/(mobile)/me/settings/page.tsx +2 -2
- package/src/app/(main)/chat/(workspace)/@conversation/default.tsx +3 -3
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/index.tsx +1 -3
- package/src/app/(main)/chat/(workspace)/@portal/default.tsx +2 -2
- package/src/app/(main)/chat/(workspace)/@topic/default.tsx +2 -2
- package/src/app/(main)/chat/(workspace)/page.tsx +1 -1
- package/src/app/(main)/discover/(detail)/assistant/[slug]/page.tsx +1 -1
- package/src/app/(main)/discover/(detail)/model/[...slugs]/page.tsx +1 -1
- package/src/app/(main)/discover/(detail)/plugin/[slug]/page.tsx +1 -1
- package/src/app/(main)/discover/(detail)/provider/[slug]/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/assistants/[slug]/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/assistants/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/models/[slug]/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/models/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/plugins/[slug]/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/plugins/page.tsx +1 -1
- package/src/app/(main)/discover/(list)/providers/page.tsx +1 -1
- package/src/app/(main)/discover/search/page.tsx +1 -1
- package/src/app/(main)/profile/[[...slugs]]/page.tsx +3 -2
- package/src/app/(main)/profile/layout.tsx +3 -2
- package/src/app/(main)/profile/loading.tsx +2 -2
- package/src/app/(main)/settings/about/page.tsx +2 -2
- package/src/app/(main)/settings/sync/page.tsx +3 -3
- package/src/app/@modal/(.)settings/modal/page.tsx +3 -3
- package/src/app/layout.tsx +2 -2
- package/src/components/server/ServerLayout.tsx +2 -2
- package/src/database/schemas/user.ts +1 -0
- package/src/database/server/models/__tests__/user.test.ts +23 -19
- package/src/database/server/models/session.ts +3 -1
- package/src/database/server/models/user.ts +25 -58
- package/src/layout/GlobalProvider/index.tsx +1 -1
- package/src/locales/default/common.ts +6 -3
- package/src/server/modules/KeyVaultsEncrypt/index.ts +23 -0
- package/src/server/routers/lambda/user.ts +19 -2
- package/src/server/services/user/index.ts +5 -0
- package/src/utils/server/responsive.ts +4 -5
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "准备启动",
|
13
14
|
"appInitializing": "应用启动中...",
|
15
|
+
"failed": "很抱歉,应用初始化失败,请查看详情进行排查",
|
14
16
|
"finished": "数据库初始化完成",
|
15
17
|
"goToChat": "对话页面加载中...",
|
16
18
|
"initAuth": "鉴权服务初始化...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "初始化依赖...",
|
20
22
|
"loadingWasm": "加载 WASM 模块...",
|
21
23
|
"migrating": "执行数据表迁移...",
|
22
|
-
"ready": "数据库已就绪"
|
24
|
+
"ready": "数据库已就绪",
|
25
|
+
"showDetail": "查看详情"
|
23
26
|
},
|
24
27
|
"autoGenerate": "自动补全",
|
25
28
|
"autoGenerateTooltip": "基于提示词自动补全助手描述",
|
@@ -36,12 +39,13 @@
|
|
36
39
|
"title": "初始化 PGlite 数据库"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "非常抱歉,Pglite
|
42
|
+
"desc": "非常抱歉,Pglite 数据库初始化过程发生异常。请点击按钮重试。如多次重试后仍重复出错,请 <1>提交问题</1> ,我们将会第一时间帮你排查",
|
43
|
+
"detail": "错误原因:[{{type}}] {{message}},明细如下:",
|
40
44
|
"retry": "重试",
|
41
|
-
"title": "
|
45
|
+
"title": "数据库初始化失败"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
|
-
"error": "
|
48
|
+
"error": "数据库初始化出错,点击查看详情",
|
45
49
|
"idle": "等待初始化...",
|
46
50
|
"initializing": "正在初始化...",
|
47
51
|
"loadingDependencies": "加载依赖中...",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "準備啟動",
|
13
14
|
"appInitializing": "應用啟動中...",
|
15
|
+
"failed": "很抱歉,應用初始化失敗,請查看詳情進行排查",
|
14
16
|
"finished": "資料庫初始化完成",
|
15
17
|
"goToChat": "對話頁面加載中...",
|
16
18
|
"initAuth": "鑑權服務初始化...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "初始化依賴...",
|
20
22
|
"loadingWasm": "加載 WASM 模組...",
|
21
23
|
"migrating": "執行資料表遷移...",
|
22
|
-
"ready": "資料庫已就緒"
|
24
|
+
"ready": "資料庫已就緒",
|
25
|
+
"showDetail": "查看詳情"
|
23
26
|
},
|
24
27
|
"autoGenerate": "自動生成",
|
25
28
|
"autoGenerateTooltip": "基於提示詞自動生成助手描述",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "初始化 PGlite 數據庫"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "非常抱歉,Pglite
|
42
|
+
"desc": "非常抱歉,Pglite 資料庫初始化過程發生異常。請點擊按鈕重試。如多次重試後仍重複出錯,請 <1>提交問題</1> ,我們將會第一時間幫你排查",
|
43
|
+
"detail": "錯誤原因:[{{type}}] {{message}},明細如下:",
|
40
44
|
"retry": "重試",
|
41
|
-
"title": "
|
45
|
+
"title": "資料庫初始化失敗"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "發生錯誤,請重試",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.36.
|
3
|
+
"version": "1.36.40",
|
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",
|
@@ -162,7 +162,6 @@
|
|
162
162
|
"i18next-resources-to-backend": "^1.2.1",
|
163
163
|
"idb-keyval": "^6.2.1",
|
164
164
|
"immer": "^10.1.1",
|
165
|
-
"ip": "^2.0.1",
|
166
165
|
"jose": "^5.9.4",
|
167
166
|
"js-sha256": "^0.11.0",
|
168
167
|
"jsonl-parse-stringify": "^1.0.3",
|
@@ -6,14 +6,14 @@ import ChatList from './features/ChatList';
|
|
6
6
|
import ThreadHydration from './features/ThreadHydration';
|
7
7
|
import ZenModeToast from './features/ZenModeToast';
|
8
8
|
|
9
|
-
const ChatConversation = () => {
|
10
|
-
const mobile = isMobileDevice();
|
9
|
+
const ChatConversation = async () => {
|
10
|
+
const mobile = await isMobileDevice();
|
11
11
|
|
12
12
|
return (
|
13
13
|
<>
|
14
14
|
<ZenModeToast />
|
15
15
|
<ChatList mobile={mobile} />
|
16
|
-
<ChatInput />
|
16
|
+
<ChatInput mobile={mobile} />
|
17
17
|
<ChatHydration />
|
18
18
|
<ThreadHydration />
|
19
19
|
</>
|
@@ -1,10 +1,8 @@
|
|
1
1
|
import MobileChatInput from '@/features/ChatInput/Mobile';
|
2
|
-
import { isMobileDevice } from '@/utils/server/responsive';
|
3
2
|
|
4
3
|
import DesktopChatInput from './Desktop';
|
5
4
|
|
6
|
-
const ChatInput = () => {
|
7
|
-
const mobile = isMobileDevice();
|
5
|
+
const ChatInput = ({ mobile }: { mobile: boolean }) => {
|
8
6
|
const Input = mobile ? MobileChatInput : DesktopChatInput;
|
9
7
|
|
10
8
|
return <Input />;
|
@@ -8,8 +8,8 @@ import Mobile from './_layout/Mobile';
|
|
8
8
|
|
9
9
|
const PortalBody = lazy(() => import('@/features/Portal/router'));
|
10
10
|
|
11
|
-
const Inspector = () => {
|
12
|
-
const mobile = isMobileDevice();
|
11
|
+
const Inspector = async () => {
|
12
|
+
const mobile = await isMobileDevice();
|
13
13
|
|
14
14
|
const Layout = mobile ? Mobile : Desktop;
|
15
15
|
|
@@ -10,8 +10,8 @@ import SystemRole from './features/SystemRole';
|
|
10
10
|
|
11
11
|
const TopicContent = lazy(() => import('./features/TopicListContent'));
|
12
12
|
|
13
|
-
const Topic = () => {
|
14
|
-
const mobile = isMobileDevice();
|
13
|
+
const Topic = async () => {
|
14
|
+
const mobile = await isMobileDevice();
|
15
15
|
|
16
16
|
const Layout = mobile ? Mobile : Desktop;
|
17
17
|
|
@@ -18,7 +18,7 @@ export const generateMetadata = async () => {
|
|
18
18
|
};
|
19
19
|
|
20
20
|
const Page = async () => {
|
21
|
-
const mobile = isMobileDevice();
|
21
|
+
const mobile = await isMobileDevice();
|
22
22
|
const { t } = await translation('metadata');
|
23
23
|
const ld = ldModule.generate({
|
24
24
|
description: t('chat.title', { appName: BRANDING_NAME }),
|
@@ -62,7 +62,7 @@ const Page = async (props: DiscoverPageProps) => {
|
|
62
62
|
|
63
63
|
const { slug: identifier } = params;
|
64
64
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
65
|
-
const mobile = isMobileDevice();
|
65
|
+
const mobile = await isMobileDevice();
|
66
66
|
|
67
67
|
const discoverService = new DiscoverService();
|
68
68
|
const data = await discoverService.getAssistantById(locale, identifier);
|
@@ -72,7 +72,7 @@ const Page = async (props: Props) => {
|
|
72
72
|
const identifier = decodeURIComponent(slugs.join('/'));
|
73
73
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
74
74
|
const { t: td } = await translation('models', searchParams?.hl);
|
75
|
-
const mobile = isMobileDevice();
|
75
|
+
const mobile = await isMobileDevice();
|
76
76
|
|
77
77
|
const discoverService = new DiscoverService();
|
78
78
|
const data = await discoverService.getModelById(locale, identifier);
|
@@ -64,7 +64,7 @@ const Page = async (props: DiscoverPageProps) => {
|
|
64
64
|
|
65
65
|
const { slug: identifier } = params;
|
66
66
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
67
|
-
const mobile = isMobileDevice();
|
67
|
+
const mobile = await isMobileDevice();
|
68
68
|
|
69
69
|
const discoverService = new DiscoverService();
|
70
70
|
const data = await discoverService.getPluginById(locale, identifier, true);
|
@@ -62,7 +62,7 @@ const Page = async (props: DiscoverPageProps) => {
|
|
62
62
|
const { slug: identifier } = params;
|
63
63
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
64
64
|
const { t: td } = await translation('models', searchParams?.hl);
|
65
|
-
const mobile = isMobileDevice();
|
65
|
+
const mobile = await isMobileDevice();
|
66
66
|
|
67
67
|
const discoverService = new DiscoverService();
|
68
68
|
const data = await discoverService.getProviderById(locale, identifier);
|
@@ -32,7 +32,7 @@ const Page = async (props: DiscoverPageProps<AssistantCategory>) => {
|
|
32
32
|
|
33
33
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
34
34
|
const { t: td } = await translation('discover', searchParams?.hl);
|
35
|
-
const mobile = isMobileDevice();
|
35
|
+
const mobile = await isMobileDevice();
|
36
36
|
|
37
37
|
const discoverService = new DiscoverService();
|
38
38
|
const items = await discoverService.getAssistantCategory(locale, params.slug);
|
@@ -25,7 +25,7 @@ export const generateMetadata = async (props: Props) => {
|
|
25
25
|
const Page = async (props: Props) => {
|
26
26
|
const searchParams = await props.searchParams;
|
27
27
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
28
|
-
const mobile = isMobileDevice();
|
28
|
+
const mobile = await isMobileDevice();
|
29
29
|
|
30
30
|
const discoverService = new DiscoverService();
|
31
31
|
const items = await discoverService.getAssistantList(locale);
|
@@ -35,7 +35,7 @@ const Page = async (props: DiscoverPageProps) => {
|
|
35
35
|
const searchParams = await props.searchParams;
|
36
36
|
|
37
37
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
38
|
-
const mobile = isMobileDevice();
|
38
|
+
const mobile = await isMobileDevice();
|
39
39
|
|
40
40
|
const discoverService = new DiscoverService();
|
41
41
|
const list = await discoverService.getProviderList(locale);
|
@@ -29,7 +29,7 @@ const Page = async (props: Props) => {
|
|
29
29
|
const searchParams = await props.searchParams;
|
30
30
|
|
31
31
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
32
|
-
const mobile = isMobileDevice();
|
32
|
+
const mobile = await isMobileDevice();
|
33
33
|
|
34
34
|
const discoverService = new DiscoverService();
|
35
35
|
const items = await discoverService.getModelList(locale);
|
@@ -32,7 +32,7 @@ const Page = async (props: DiscoverPageProps<PluginCategory>) => {
|
|
32
32
|
|
33
33
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
34
34
|
const { t: td } = await translation('discover', searchParams?.hl);
|
35
|
-
const mobile = isMobileDevice();
|
35
|
+
const mobile = await isMobileDevice();
|
36
36
|
|
37
37
|
const discoverService = new DiscoverService();
|
38
38
|
const items = await discoverService.getPluginCategory(locale, params.slug);
|
@@ -26,7 +26,7 @@ export const generateMetadata = async (props: Props) => {
|
|
26
26
|
const Page = async (props: Props) => {
|
27
27
|
const searchParams = await props.searchParams;
|
28
28
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
29
|
-
const mobile = isMobileDevice();
|
29
|
+
const mobile = await isMobileDevice();
|
30
30
|
|
31
31
|
const discoverService = new DiscoverService();
|
32
32
|
const items = await discoverService.getPluginList(locale);
|
@@ -26,7 +26,7 @@ export const generateMetadata = async (props: Props) => {
|
|
26
26
|
const Page = async (props: Props) => {
|
27
27
|
const searchParams = await props.searchParams;
|
28
28
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
29
|
-
const mobile = isMobileDevice();
|
29
|
+
const mobile = await isMobileDevice();
|
30
30
|
|
31
31
|
const discoverService = new DiscoverService();
|
32
32
|
const items = await discoverService.getProviderList(locale);
|
@@ -56,7 +56,7 @@ const Page = async (props: Props) => {
|
|
56
56
|
const keywords = decodeURIComponent(q);
|
57
57
|
|
58
58
|
const { t, locale } = await translation('metadata', searchParams?.hl);
|
59
|
-
const mobile = isMobileDevice();
|
59
|
+
const mobile = await isMobileDevice();
|
60
60
|
|
61
61
|
const ld = ldModule.generate({
|
62
62
|
description: t('discover.description'),
|
@@ -6,10 +6,11 @@ import { isMobileDevice } from '@/utils/server/responsive';
|
|
6
6
|
|
7
7
|
import MobileLayout from './_layout/Mobile';
|
8
8
|
|
9
|
-
const Layout = ({ children }: PropsWithChildren) => {
|
9
|
+
const Layout = async ({ children }: PropsWithChildren) => {
|
10
10
|
if (!enableClerk) return notFound();
|
11
11
|
|
12
|
-
const mobile = isMobileDevice();
|
12
|
+
const mobile = await isMobileDevice();
|
13
|
+
|
13
14
|
if (mobile) return <MobileLayout>{children}</MobileLayout>;
|
14
15
|
|
15
16
|
return children;
|
@@ -3,8 +3,8 @@ import { Flexbox } from 'react-layout-kit';
|
|
3
3
|
import SkeletonLoading from '@/components/SkeletonLoading';
|
4
4
|
import { isMobileDevice } from '@/utils/server/responsive';
|
5
5
|
|
6
|
-
const Loading = () => {
|
7
|
-
const mobile = isMobileDevice();
|
6
|
+
const Loading = async () => {
|
7
|
+
const mobile = await isMobileDevice();
|
8
8
|
if (mobile) return <SkeletonLoading paragraph={{ rows: 8 }} />;
|
9
9
|
return (
|
10
10
|
<Flexbox horizontal style={{ position: 'relative' }} width={'100%'}>
|
@@ -15,12 +15,12 @@ export const generateMetadata = async () => {
|
|
15
15
|
url: '/settings/sync',
|
16
16
|
});
|
17
17
|
};
|
18
|
-
export default () => {
|
18
|
+
export default async () => {
|
19
19
|
const enableWebrtc = serverFeatureFlags().enableWebrtc;
|
20
20
|
if (!enableWebrtc) return notFound();
|
21
21
|
|
22
|
-
const isMobile = isMobileDevice();
|
23
|
-
const { os, browser } = gerServerDeviceInfo();
|
22
|
+
const isMobile = await isMobileDevice();
|
23
|
+
const { os, browser } = await gerServerDeviceInfo();
|
24
24
|
|
25
25
|
return <Page browser={browser} mobile={isMobile} os={os} />;
|
26
26
|
};
|
@@ -7,9 +7,9 @@ import SettingsModal from './index';
|
|
7
7
|
* @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
|
8
8
|
*/
|
9
9
|
|
10
|
-
const Page = () => {
|
11
|
-
const isMobile = isMobileDevice();
|
12
|
-
const { os, browser } = gerServerDeviceInfo();
|
10
|
+
const Page = async () => {
|
11
|
+
const isMobile = await isMobileDevice();
|
12
|
+
const { os, browser } = await gerServerDeviceInfo();
|
13
13
|
|
14
14
|
return <SettingsModal browser={browser} mobile={isMobile} os={os} />;
|
15
15
|
};
|
package/src/app/layout.tsx
CHANGED
@@ -25,7 +25,7 @@ const RootLayout = async ({ children, modal }: RootLayoutProps) => {
|
|
25
25
|
const locale = lang?.value || DEFAULT_LANG;
|
26
26
|
|
27
27
|
const direction = isRtlLang(locale) ? 'rtl' : 'ltr';
|
28
|
-
const mobile = isMobileDevice();
|
28
|
+
const mobile = await isMobileDevice();
|
29
29
|
|
30
30
|
return (
|
31
31
|
<html dir={direction} lang={locale} suppressHydrationWarning>
|
@@ -49,7 +49,7 @@ export default RootLayout;
|
|
49
49
|
export { generateMetadata } from './metadata';
|
50
50
|
|
51
51
|
export const generateViewport = async (): ResolvingViewport => {
|
52
|
-
const isMobile = isMobileDevice();
|
52
|
+
const isMobile = await isMobileDevice();
|
53
53
|
|
54
54
|
const dynamicScale = isMobile ? { maximumScale: 1, userScalable: false } : {};
|
55
55
|
|
@@ -9,8 +9,8 @@ interface ServerLayoutProps<T> {
|
|
9
9
|
|
10
10
|
const ServerLayout =
|
11
11
|
<T extends PropsWithChildren>({ Desktop, Mobile }: ServerLayoutProps<T>): FC<T> =>
|
12
|
-
(props: T) => {
|
13
|
-
const mobile = isMobileDevice();
|
12
|
+
async (props: T) => {
|
13
|
+
const mobile = await isMobileDevice();
|
14
14
|
return mobile ? <Mobile {...props} /> : <Desktop {...props} />;
|
15
15
|
};
|
16
16
|
|
@@ -46,6 +46,7 @@ export const userSettings = pgTable('user_settings', {
|
|
46
46
|
defaultAgent: jsonb('default_agent'),
|
47
47
|
tool: jsonb('tool'),
|
48
48
|
});
|
49
|
+
export type UserSettingsItem = typeof userSettings.$inferSelect;
|
49
50
|
|
50
51
|
export const installedPlugins = pgTable(
|
51
52
|
'user_installed_plugins',
|
@@ -7,7 +7,7 @@ import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
7
7
|
import { UserGuide, UserPreference } from '@/types/user';
|
8
8
|
import { UserSettings } from '@/types/user/settings';
|
9
9
|
|
10
|
-
import { userSettings, users } from '../../../schemas';
|
10
|
+
import { UserSettingsItem, userSettings, users } from '../../../schemas';
|
11
11
|
import { SessionModel } from '../session';
|
12
12
|
import { UserModel } from '../user';
|
13
13
|
|
@@ -101,7 +101,7 @@ describe('UserModel', () => {
|
|
101
101
|
keyVaults: encryptedKeyVaults,
|
102
102
|
});
|
103
103
|
|
104
|
-
const state = await userModel.getUserState();
|
104
|
+
const state = await userModel.getUserState(KeyVaultsGateKeeper.getUserKeyVaults);
|
105
105
|
|
106
106
|
expect(state.userId).toBe(userId);
|
107
107
|
expect(state.preference).toEqual(preference);
|
@@ -111,7 +111,9 @@ describe('UserModel', () => {
|
|
111
111
|
it('should throw an error if user not found', async () => {
|
112
112
|
const userModel = new UserModel(serverDB, 'invalid-user-id');
|
113
113
|
|
114
|
-
await expect(userModel.getUserState()).rejects.toThrow(
|
114
|
+
await expect(userModel.getUserState(KeyVaultsGateKeeper.getUserKeyVaults)).rejects.toThrow(
|
115
|
+
'user not found',
|
116
|
+
);
|
115
117
|
});
|
116
118
|
});
|
117
119
|
|
@@ -144,11 +146,10 @@ describe('UserModel', () => {
|
|
144
146
|
});
|
145
147
|
|
146
148
|
describe('updateSetting', () => {
|
147
|
-
it('should update user settings with
|
149
|
+
it('should update user settings with new item', async () => {
|
148
150
|
const settings = {
|
149
151
|
general: { language: 'en-US' },
|
150
|
-
|
151
|
-
} as UserSettings;
|
152
|
+
} as UserSettingsItem;
|
152
153
|
await serverDB.insert(users).values({ id: userId });
|
153
154
|
|
154
155
|
await userModel.updateSetting(settings);
|
@@ -157,23 +158,18 @@ describe('UserModel', () => {
|
|
157
158
|
where: eq(users.id, userId),
|
158
159
|
});
|
159
160
|
expect(updatedSettings?.general).toEqual(settings.general);
|
160
|
-
expect(updatedSettings?.keyVaults).not.toBe(JSON.stringify(settings.keyVaults));
|
161
|
-
|
162
|
-
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
|
163
|
-
const { plaintext } = await gateKeeper.decrypt(updatedSettings!.keyVaults!);
|
164
|
-
expect(JSON.parse(plaintext)).toEqual(settings.keyVaults);
|
165
161
|
});
|
166
162
|
|
167
|
-
it('should update user settings with
|
163
|
+
it('should update user settings with exist item', async () => {
|
168
164
|
const settings = {
|
169
165
|
general: { language: 'en-US' },
|
170
|
-
} as
|
166
|
+
} as UserSettingsItem;
|
171
167
|
await serverDB.insert(users).values({ id: userId });
|
172
168
|
await serverDB.insert(userSettings).values({ ...settings, keyVaults: '', id: userId });
|
173
169
|
|
174
170
|
const newSettings = {
|
175
171
|
general: { fontSize: 16, language: 'zh-CN', themeMode: 'dark' },
|
176
|
-
} as
|
172
|
+
} as UserSettingsItem;
|
177
173
|
await userModel.updateSetting(newSettings);
|
178
174
|
|
179
175
|
const updatedSettings = await serverDB.query.userSettings.findFirst({
|
@@ -229,14 +225,18 @@ describe('UserModel', () => {
|
|
229
225
|
keyVaults: encryptedKeyVaults,
|
230
226
|
});
|
231
227
|
|
232
|
-
const result = await UserModel.getUserApiKeys(
|
228
|
+
const result = await UserModel.getUserApiKeys(
|
229
|
+
serverDB,
|
230
|
+
userId,
|
231
|
+
KeyVaultsGateKeeper.getUserKeyVaults,
|
232
|
+
);
|
233
233
|
expect(result).toEqual(keyVaults);
|
234
234
|
});
|
235
235
|
|
236
236
|
it('should throw error when user not found', async () => {
|
237
|
-
await expect(
|
238
|
-
|
239
|
-
);
|
237
|
+
await expect(
|
238
|
+
UserModel.getUserApiKeys(serverDB, 'non-existent-id', KeyVaultsGateKeeper.getUserKeyVaults),
|
239
|
+
).rejects.toThrow('user not found');
|
240
240
|
});
|
241
241
|
|
242
242
|
it('should handle decrypt failure and return empty object', async () => {
|
@@ -249,7 +249,11 @@ describe('UserModel', () => {
|
|
249
249
|
keyVaults: invalidEncryptedData,
|
250
250
|
});
|
251
251
|
|
252
|
-
const result = await UserModel.getUserApiKeys(
|
252
|
+
const result = await UserModel.getUserApiKeys(
|
253
|
+
serverDB,
|
254
|
+
userId,
|
255
|
+
KeyVaultsGateKeeper.getUserKeyVaults,
|
256
|
+
);
|
253
257
|
expect(result).toEqual({});
|
254
258
|
});
|
255
259
|
});
|
@@ -301,7 +301,9 @@ export class SessionModel {
|
|
301
301
|
try {
|
302
302
|
// @ts-expect-error
|
303
303
|
return results.map((item) => item.agentsToSessions[0].session);
|
304
|
-
} catch {
|
304
|
+
} catch (e) {
|
305
|
+
console.error('findSessionsByKeywords error:', e);
|
306
|
+
}
|
305
307
|
return [];
|
306
308
|
};
|
307
309
|
}
|