@lobehub/chat 0.82.8 → 0.83.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 +42 -0
- package/locales/en_US/error.json +2 -1
- package/locales/en_US/plugin.json +1 -0
- package/locales/en_US/setting.json +2 -1
- package/locales/ru_RU/error.json +2 -1
- package/locales/ru_RU/plugin.json +1 -0
- package/locales/ru_RU/setting.json +2 -1
- package/locales/zh_CN/error.json +1 -0
- package/locales/zh_CN/plugin.json +2 -1
- package/locales/zh_CN/setting.json +2 -1
- package/locales/zh_TW/error.json +2 -1
- package/locales/zh_TW/plugin.json +1 -0
- package/locales/zh_TW/setting.json +2 -1
- package/package.json +6 -5
- package/src/app/chat/{features/Header → (desktop)/features/ChatHeader}/Desktop.tsx +2 -2
- package/src/app/chat/{features/Header → (desktop)/features/ChatHeader}/index.tsx +1 -1
- package/src/app/chat/(desktop)/features/ChatInput/index.tsx +22 -0
- package/src/app/chat/{features/SessionList/Header → (desktop)/features/SessionHeader}/Desktop.tsx +1 -1
- package/src/app/chat/{features/SessionList/Header → (desktop)/features/SessionHeader}/index.tsx +1 -1
- package/src/app/chat/{features → (desktop)/features}/SessionList/Desktop.tsx +1 -1
- package/src/app/chat/(desktop)/features/SessionList/index.tsx +20 -0
- package/src/app/chat/{features/Sidebar → (desktop)/features/SideBar}/Desktop.tsx +4 -4
- package/src/app/chat/(desktop)/features/SideBar/index.tsx +20 -0
- package/src/app/chat/(desktop)/index.tsx +24 -0
- package/src/app/chat/{layout.desktop.tsx → (desktop)/layout/Desktop.tsx} +4 -4
- package/src/app/chat/(desktop)/layout/index.tsx +25 -0
- package/src/app/chat/(mobile)/features/ChatHeader.tsx +1 -0
- package/src/app/chat/(mobile)/features/ChatInput.tsx +14 -0
- package/src/app/chat/(mobile)/features/SessionList.tsx +12 -0
- package/src/app/chat/(mobile)/features/Topics.tsx +12 -0
- package/src/app/chat/(mobile)/index.tsx +20 -0
- package/src/app/chat/(mobile)/layout.tsx +15 -0
- package/src/app/chat/(mobile)/mobile/page.tsx +21 -0
- package/src/app/chat/{features/Header → components/ChatHeader}/Mobile.tsx +2 -1
- package/src/app/chat/{features/Header → components/ChatHeader}/ShareButton/Preview.tsx +3 -3
- package/src/app/chat/{features/Conversation/Input → components/ChatInput}/index.tsx +23 -21
- package/src/app/chat/components/Inspector/index.tsx +17 -0
- package/src/app/chat/{features → components}/SessionList/List/Item/index.tsx +2 -2
- package/src/app/chat/{features → components}/SessionList/Mobile.tsx +1 -1
- package/src/app/chat/{features → components}/SessionList/index.tsx +3 -10
- package/src/app/chat/features/Conversation/index.tsx +8 -4
- package/src/app/chat/features/PageTitle.tsx +19 -0
- package/src/app/chat/layout.tsx +14 -0
- package/src/app/chat/page.tsx +9 -4
- package/src/app/chat/settings/(desktop)/Header/index.tsx +13 -0
- package/src/app/chat/settings/{layout.desktop.tsx → (desktop)/layout.desktop.tsx} +5 -4
- package/src/app/chat/settings/(mobile)/Header.tsx +12 -0
- package/src/app/chat/settings/{layout.mobile.tsx → (mobile)/layout.mobile.tsx} +3 -1
- package/src/app/chat/settings/{features → components}/Header/index.tsx +4 -13
- package/src/app/chat/settings/layout.tsx +14 -0
- package/src/app/chat/settings/page.tsx +36 -5
- package/src/app/home/index.tsx +15 -11
- package/src/app/layout.tsx +4 -1
- package/src/app/metadata.ts +4 -1
- package/src/app/settings/agent/Agent.tsx +3 -3
- package/src/app/settings/agent/index.tsx +1 -0
- package/src/app/settings/common/Common.tsx +109 -117
- package/src/app/settings/features/SideBar/List.tsx +11 -5
- package/src/app/settings/llm/LLM/index.tsx +2 -2
- package/src/app/welcome/page.tsx +2 -6
- package/src/components/PageTitle.tsx +11 -0
- package/src/config/client.ts +13 -0
- package/src/const/locale.ts +9 -0
- package/src/const/settings.ts +1 -1
- package/src/const/url.ts +1 -6
- package/src/helpers/export.ts +2 -2
- package/src/layout/AppMobileLayout.tsx +15 -24
- package/src/layout/GlobalLayout/Locale.tsx +44 -0
- package/src/layout/GlobalLayout/LocaleLoading.tsx +21 -0
- package/src/layout/GlobalLayout/StoreHydration.tsx +28 -0
- package/src/layout/GlobalLayout/index.tsx +29 -41
- package/src/locales/create.ts +43 -26
- package/src/locales/default/setting.ts +2 -1
- package/src/locales/options.ts +6 -5
- package/src/services/agentMarket.ts +6 -4
- package/src/services/pluginMarket.ts +2 -2
- package/src/store/global/hooks/useSwitchSettingsOnInit.ts +5 -2
- package/src/store/global/{selectors.test.ts → selectors/settings.test.ts} +11 -11
- package/src/store/global/selectors/settings.ts +44 -0
- package/src/store/global/selectors.ts +1 -36
- package/src/store/global/slices/common.ts +3 -4
- package/src/types/locale.ts +4 -0
- package/src/types/settings.ts +2 -2
- package/src/utils/env.ts +2 -0
- package/src/utils/responsive.ts +1 -0
- package/src/utils/switchLang.ts +5 -1
- package/src/app/chat/features/Sidebar/index.tsx +0 -29
- package/src/app/chat/index.tsx +0 -54
- package/src/app/chat/layout.mobile.tsx +0 -20
- package/src/app/chat/mobile/index.tsx +0 -38
- package/src/app/chat/mobile/page.tsx +0 -7
- package/src/app/chat/settings/index.tsx +0 -51
- package/src/layout/GlobalLayout/style.ts +0 -18
- /package/src/app/chat/{features/Conversation/Input → (desktop)/features/ChatInput}/Desktop.tsx +0 -0
- /package/src/app/chat/{features/SessionList/Header/Mobile.tsx → (mobile)/features/SessionHeader.tsx} +0 -0
- /package/src/app/chat/{features/Header → components/ChatHeader}/PluginTag/PluginStatus.tsx +0 -0
- /package/src/app/chat/{features/Header → components/ChatHeader}/PluginTag/index.tsx +0 -0
- /package/src/app/chat/{features/Header → components/ChatHeader}/ShareButton/Inner.tsx +0 -0
- /package/src/app/chat/{features/Header → components/ChatHeader}/ShareButton/index.tsx +0 -0
- /package/src/app/chat/{features/Header → components/ChatHeader}/ShareButton/style.ts +0 -0
- /package/src/app/chat/{features/Conversation/Input → components/ChatInput}/ActionBar/ActionLeft.tsx +0 -0
- /package/src/app/chat/{features/Conversation/Input → components/ChatInput}/ActionBar/ActionRight.tsx +0 -0
- /package/src/app/chat/{features/Conversation/Input → components/ChatInput}/ActionBar/Token.tsx +0 -0
- /package/src/app/chat/{features/Conversation/Input → components/ChatInput}/Footer/SaveTopic.tsx +0 -0
- /package/src/app/chat/{features/Conversation/Input → components/ChatInput}/Footer/index.tsx +0 -0
- /package/src/app/chat/{features/Conversation/Input → components/ChatInput}/Mobile.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/Mobile.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/SystemRole/Header.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/SystemRole/index.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/SystemRole/style.ts +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/Topic/DefaultContent.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/Topic/SkeletonList.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/Topic/TopicContent.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/Topic/TopicItem.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/Topic/index.tsx +0 -0
- /package/src/app/chat/{features/Sidebar → components/Inspector}/TopicSearchBar/index.tsx +0 -0
- /package/src/app/chat/{features → components}/SessionList/CollapseGroup/index.tsx +0 -0
- /package/src/app/chat/{features → components}/SessionList/Inbox/index.tsx +0 -0
- /package/src/app/chat/{features → components}/SessionList/List/AddButton.tsx +0 -0
- /package/src/app/chat/{features → components}/SessionList/List/Item/Actions.tsx +0 -0
- /package/src/app/chat/{features → components}/SessionList/List/SkeletonList.tsx +0 -0
- /package/src/app/chat/{features → components}/SessionList/List/index.tsx +0 -0
- /package/src/app/chat/settings/{features → (desktop)}/Header/Desktop.tsx +0 -0
- /package/src/app/chat/settings/{features → components}/Header/Mobile.tsx +0 -0
- /package/src/{components/AppTheme/index.tsx → layout/GlobalLayout/AppTheme.tsx} +0 -0
|
@@ -1,56 +1,44 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { App
|
|
3
|
+
import { App } from 'antd';
|
|
4
|
+
import { createStyles } from 'antd-style';
|
|
4
5
|
import 'antd/dist/reset.css';
|
|
5
|
-
import
|
|
6
|
-
import { useRouter } from 'next/navigation';
|
|
7
|
-
import { PropsWithChildren, memo, useEffect } from 'react';
|
|
6
|
+
import { PropsWithChildren, memo } from 'react';
|
|
8
7
|
|
|
9
|
-
import AppTheme, { AppThemeProps } from '
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import { usePluginStore } from '@/store/plugin';
|
|
13
|
-
import { useOnFinishHydrationSession, useSessionStore } from '@/store/session';
|
|
14
|
-
import { switchLang } from '@/utils/switchLang';
|
|
8
|
+
import AppTheme, { AppThemeProps } from './AppTheme';
|
|
9
|
+
import Locale from './Locale';
|
|
10
|
+
import StoreHydration from './StoreHydration';
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
13
|
+
bg: css`
|
|
14
|
+
overflow-y: scroll;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
align-items: center;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
height: 100%;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const router = useRouter();
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
// refs: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#hashydrated
|
|
27
|
-
useSessionStore.persist.rehydrate();
|
|
28
|
-
useGlobalStore.persist.rehydrate();
|
|
29
|
-
usePluginStore.persist.rehydrate();
|
|
30
|
-
}, []);
|
|
31
|
-
|
|
32
|
-
useOnFinishHydrationGlobal((state) => {
|
|
33
|
-
i18n.then(() => switchLang(state.settings.language));
|
|
34
|
-
});
|
|
21
|
+
background: ${token.colorBgLayout};
|
|
22
|
+
`,
|
|
23
|
+
}));
|
|
35
24
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// add router instance to store
|
|
40
|
-
store.setState({ router });
|
|
41
|
-
});
|
|
25
|
+
const Container = memo<PropsWithChildren>(({ children }) => {
|
|
26
|
+
const { styles } = useStyles();
|
|
42
27
|
|
|
43
|
-
return
|
|
44
|
-
<ConfigProvider locale={Zh_CN}>
|
|
45
|
-
<App className={styles.bg}>{children}</App>
|
|
46
|
-
</ConfigProvider>
|
|
47
|
-
);
|
|
28
|
+
return <App className={styles.bg}>{children}</App>;
|
|
48
29
|
});
|
|
49
30
|
|
|
50
|
-
|
|
31
|
+
interface GlobalLayoutProps extends AppThemeProps {
|
|
32
|
+
defaultLang?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const GlobalLayout = ({ children, defaultLang, ...theme }: GlobalLayoutProps) => (
|
|
51
36
|
<AppTheme {...theme}>
|
|
52
|
-
<
|
|
37
|
+
<Locale lang={defaultLang}>
|
|
38
|
+
<StoreHydration />
|
|
39
|
+
<Container>{children}</Container>
|
|
40
|
+
</Locale>
|
|
53
41
|
</AppTheme>
|
|
54
42
|
);
|
|
55
43
|
|
|
56
|
-
export default
|
|
44
|
+
export default GlobalLayout;
|
package/src/locales/create.ts
CHANGED
|
@@ -1,36 +1,53 @@
|
|
|
1
1
|
import i18n from 'i18next';
|
|
2
2
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
3
|
-
import { isArray } from 'lodash-es';
|
|
4
3
|
import { initReactI18next } from 'react-i18next';
|
|
5
4
|
|
|
5
|
+
import { getClientConfig } from '@/config/client';
|
|
6
|
+
import { DEFAULT_LANG, LOBE_LOCALE_COOKIE } from '@/const/locale';
|
|
7
|
+
import resources from '@/locales/resources';
|
|
6
8
|
import type { Namespaces } from '@/types/locale';
|
|
9
|
+
import { isOnServerSide } from '@/utils/env';
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
const { I18N_DEBUG, I18N_DEBUG_BROWSER, I18N_DEBUG_SERVER } = getClientConfig();
|
|
12
|
+
const debugMode = I18N_DEBUG ?? isOnServerSide ? I18N_DEBUG_SERVER : I18N_DEBUG_BROWSER;
|
|
9
13
|
|
|
10
|
-
const
|
|
14
|
+
export const createI18nNext = (lang?: string) => {
|
|
15
|
+
const ns: Namespaces[] = [
|
|
16
|
+
'error',
|
|
17
|
+
'common',
|
|
18
|
+
'empty',
|
|
19
|
+
'error',
|
|
20
|
+
'market',
|
|
21
|
+
'plugin',
|
|
22
|
+
'setting',
|
|
23
|
+
'welcome',
|
|
24
|
+
];
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
26
|
+
const instance = i18n.use(initReactI18next).use(LanguageDetector);
|
|
27
|
+
// not find a good way to handle suspense loading
|
|
28
|
+
// .use(
|
|
29
|
+
// resourcesToBackend(
|
|
30
|
+
// isDev ? resources : (lng: string, ns: string) => import(`../../locales/${lng}/${ns}.json`),
|
|
31
|
+
// ),
|
|
32
|
+
// )
|
|
14
33
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
resources,
|
|
35
|
-
});
|
|
34
|
+
return {
|
|
35
|
+
init: () =>
|
|
36
|
+
instance.init({
|
|
37
|
+
debug: debugMode,
|
|
38
|
+
defaultNS: ['error', 'common'],
|
|
39
|
+
detection: {
|
|
40
|
+
caches: ['cookie'],
|
|
41
|
+
lookupCookie: LOBE_LOCALE_COOKIE,
|
|
42
|
+
},
|
|
43
|
+
fallbackLng: DEFAULT_LANG,
|
|
44
|
+
interpolation: {
|
|
45
|
+
escapeValue: false,
|
|
46
|
+
},
|
|
47
|
+
lng: lang,
|
|
48
|
+
ns,
|
|
49
|
+
resources,
|
|
50
|
+
}),
|
|
51
|
+
instance,
|
|
52
|
+
};
|
|
36
53
|
};
|
package/src/locales/options.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { SelectProps } from 'antd';
|
|
2
1
|
|
|
3
2
|
import type { Locales } from '@/types/locale';
|
|
4
3
|
|
|
5
|
-
type LocaleOptions =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
type LocaleOptions = {
|
|
5
|
+
label: string;
|
|
6
|
+
value: Locales;
|
|
7
|
+
}[];
|
|
9
8
|
|
|
10
9
|
export const localeOptions: LocaleOptions = [
|
|
11
10
|
{
|
|
@@ -25,3 +24,5 @@ export const localeOptions: LocaleOptions = [
|
|
|
25
24
|
value: 'ru-RU',
|
|
26
25
|
},
|
|
27
26
|
] as LocaleOptions;
|
|
27
|
+
|
|
28
|
+
export const supportLangs: string[] = localeOptions.map((i) => i.value);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useGlobalStore } from '@/store/global';
|
|
1
|
+
import { getAgentJSON } from '@/const/url';
|
|
2
|
+
import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 请求助手列表
|
|
6
6
|
*/
|
|
7
7
|
export const getAgentList = async () => {
|
|
8
|
-
const res = await fetch(
|
|
8
|
+
const res = await fetch(settingsSelectors.currentLanguage(useGlobalStore.getState()));
|
|
9
9
|
|
|
10
10
|
return res.json();
|
|
11
11
|
};
|
|
@@ -15,7 +15,9 @@ export const getAgentList = async () => {
|
|
|
15
15
|
*/
|
|
16
16
|
export const getAgentManifest = async (identifier?: string) => {
|
|
17
17
|
if (!identifier) return;
|
|
18
|
-
const res = await fetch(
|
|
18
|
+
const res = await fetch(
|
|
19
|
+
getAgentJSON(identifier, settingsSelectors.currentLanguage(useGlobalStore.getState())),
|
|
20
|
+
);
|
|
19
21
|
|
|
20
22
|
return res.json();
|
|
21
23
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { getPluginIndexJSON } from '@/const/url';
|
|
2
|
-
import { useGlobalStore } from '@/store/global';
|
|
2
|
+
import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* fetch Plugin Market List
|
|
6
6
|
*/
|
|
7
7
|
export const getPluginList = async () => {
|
|
8
|
-
const url = getPluginIndexJSON(useGlobalStore.getState()
|
|
8
|
+
const url = getPluginIndexJSON(settingsSelectors.currentLanguage(useGlobalStore.getState()));
|
|
9
9
|
|
|
10
10
|
const res = await fetch(url);
|
|
11
11
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { useOnFinishHydrationGlobal } from '@/store/global';
|
|
2
|
+
|
|
1
3
|
import { SettingsTabs } from '../initialState';
|
|
2
|
-
import { useGlobalStore } from '../store';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* 切换设置侧边栏选项
|
|
6
7
|
*/
|
|
7
8
|
export const useSwitchSideBarOnInit = (key: SettingsTabs) => {
|
|
8
|
-
|
|
9
|
+
useOnFinishHydrationGlobal((store) => {
|
|
10
|
+
store.switchSettingTabs(key);
|
|
11
|
+
});
|
|
9
12
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { LanguageModel } from '@/types/llm';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { GlobalStore } from '../store';
|
|
4
|
+
import { settingsSelectors } from './settings';
|
|
5
5
|
|
|
6
|
-
describe('
|
|
6
|
+
describe('settingsSelectors', () => {
|
|
7
7
|
describe('currentSettings', () => {
|
|
8
8
|
it('should merge DEFAULT_SETTINGS and s.settings correctly', () => {
|
|
9
9
|
const s = {
|
|
@@ -36,7 +36,7 @@ describe('globalSelectors', () => {
|
|
|
36
36
|
},
|
|
37
37
|
} as unknown as GlobalStore;
|
|
38
38
|
|
|
39
|
-
const result =
|
|
39
|
+
const result = settingsSelectors.currentSettings(s);
|
|
40
40
|
|
|
41
41
|
expect(result).toEqual({
|
|
42
42
|
avatar: 'avatar.jpg',
|
|
@@ -93,7 +93,7 @@ describe('globalSelectors', () => {
|
|
|
93
93
|
// },
|
|
94
94
|
// };
|
|
95
95
|
//
|
|
96
|
-
// const result =
|
|
96
|
+
// const result = settingsSelectors.defaultAgent(s);
|
|
97
97
|
//
|
|
98
98
|
//
|
|
99
99
|
//
|
|
@@ -114,9 +114,9 @@ describe('globalSelectors', () => {
|
|
|
114
114
|
// },
|
|
115
115
|
// };
|
|
116
116
|
//
|
|
117
|
-
// const result =
|
|
117
|
+
// const result = settingsSelectors.defaultAgentConfig(s);
|
|
118
118
|
//
|
|
119
|
-
// const defaultAgent =
|
|
119
|
+
// const defaultAgent = settingsSelectors.defaultAgent(s);
|
|
120
120
|
// const expected = merge({}, DEFAULT_AGENT_CONFIG, defaultAgent.config);
|
|
121
121
|
//
|
|
122
122
|
// expect(result).toEqual(expected);
|
|
@@ -136,9 +136,9 @@ describe('globalSelectors', () => {
|
|
|
136
136
|
// },
|
|
137
137
|
// };
|
|
138
138
|
//
|
|
139
|
-
// const result =
|
|
139
|
+
// const result = settingsSelectors.defaultAgentMeta(s);
|
|
140
140
|
//
|
|
141
|
-
// const defaultAgent =
|
|
141
|
+
// const defaultAgent = settingsSelectors.defaultAgent(s);
|
|
142
142
|
// const expected = merge({}, DEFAULT_AGENT_META, defaultAgent.meta);
|
|
143
143
|
//
|
|
144
144
|
// expect(result).toEqual(expected);
|
|
@@ -183,7 +183,7 @@ describe('globalSelectors', () => {
|
|
|
183
183
|
// },
|
|
184
184
|
// };
|
|
185
185
|
//
|
|
186
|
-
// const result =
|
|
186
|
+
// const result = settingsSelectors.exportSettings(s);
|
|
187
187
|
//
|
|
188
188
|
// const expected = {
|
|
189
189
|
// avatar: 'avatar.jpg',
|
|
@@ -255,7 +255,7 @@ describe('globalSelectors', () => {
|
|
|
255
255
|
// },
|
|
256
256
|
// };
|
|
257
257
|
//
|
|
258
|
-
// const result =
|
|
258
|
+
// const result = settingsSelectors.exportSettings(s);
|
|
259
259
|
//
|
|
260
260
|
// expect(result).toBeInstanceOf(GlobalSettings);
|
|
261
261
|
// });
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { DEFAULT_AGENT_META } from '@/const/meta';
|
|
2
|
+
import { DEFAULT_AGENT, DEFAULT_AGENT_CONFIG, DEFAULT_SETTINGS } from '@/const/settings';
|
|
3
|
+
import { Locales } from '@/locales/resources';
|
|
4
|
+
import { GlobalSettings } from '@/types/settings';
|
|
5
|
+
import { merge } from '@/utils/merge';
|
|
6
|
+
|
|
7
|
+
import { GlobalStore } from '../store';
|
|
8
|
+
|
|
9
|
+
const currentSettings = (s: GlobalStore) => merge(DEFAULT_SETTINGS, s.settings);
|
|
10
|
+
|
|
11
|
+
const defaultAgent = (s: GlobalStore) => merge(DEFAULT_AGENT, s.settings.defaultAgent);
|
|
12
|
+
|
|
13
|
+
const defaultAgentConfig = (s: GlobalStore) => merge(DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
14
|
+
|
|
15
|
+
const defaultAgentMeta = (s: GlobalStore) => merge(DEFAULT_AGENT_META, defaultAgent(s).meta);
|
|
16
|
+
|
|
17
|
+
const openAIAPIKeySelectors = (s: GlobalStore) =>
|
|
18
|
+
s.settings.languageModel.openAI.OPENAI_API_KEY || s.settings.OPENAI_API_KEY;
|
|
19
|
+
|
|
20
|
+
export const exportSettings = (s: GlobalStore) => {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22
|
+
const { OPENAI_API_KEY: _, password: __, ...settings } = s.settings;
|
|
23
|
+
|
|
24
|
+
return settings as GlobalSettings;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const currentLanguage = (s: GlobalStore) => {
|
|
28
|
+
const locale = s.settings.language;
|
|
29
|
+
if (locale === 'auto') {
|
|
30
|
+
return navigator.language as Locales;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return locale;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const settingsSelectors = {
|
|
37
|
+
currentLanguage,
|
|
38
|
+
currentSettings,
|
|
39
|
+
defaultAgent,
|
|
40
|
+
defaultAgentConfig,
|
|
41
|
+
defaultAgentMeta,
|
|
42
|
+
exportSettings,
|
|
43
|
+
openAIAPI: openAIAPIKeySelectors,
|
|
44
|
+
};
|
|
@@ -1,36 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { DEFAULT_AGENT, DEFAULT_AGENT_CONFIG, DEFAULT_SETTINGS } from '@/const/settings';
|
|
3
|
-
import { GlobalSettings } from '@/types/settings';
|
|
4
|
-
import { merge } from '@/utils/merge';
|
|
5
|
-
|
|
6
|
-
import { GlobalStore } from './store';
|
|
7
|
-
|
|
8
|
-
const currentSettings = (s: GlobalStore) => merge(DEFAULT_SETTINGS, s.settings);
|
|
9
|
-
|
|
10
|
-
const defaultAgent = (s: GlobalStore) => merge(DEFAULT_AGENT, s.settings.defaultAgent);
|
|
11
|
-
|
|
12
|
-
const defaultAgentConfig = (s: GlobalStore) => merge(DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
13
|
-
|
|
14
|
-
const defaultAgentMeta = (s: GlobalStore) => merge(DEFAULT_AGENT_META, defaultAgent(s).meta);
|
|
15
|
-
|
|
16
|
-
const openAIAPIKeySelectors = (s: GlobalStore) =>
|
|
17
|
-
s.settings.languageModel.openAI.OPENAI_API_KEY || s.settings.OPENAI_API_KEY;
|
|
18
|
-
|
|
19
|
-
export const exportSettings = (s: GlobalStore) => {
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
21
|
-
const { OPENAI_API_KEY: _, password: __, ...settings } = s.settings;
|
|
22
|
-
|
|
23
|
-
return settings as GlobalSettings;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const globalSelectors = {
|
|
27
|
-
currentSettings,
|
|
28
|
-
defaultAgent,
|
|
29
|
-
defaultAgentConfig,
|
|
30
|
-
defaultAgentMeta,
|
|
31
|
-
exportSettings,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const settingsSelectors = {
|
|
35
|
-
openAIAPI: openAIAPIKeySelectors,
|
|
36
|
-
};
|
|
1
|
+
export * from './selectors/settings';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { produce } from 'immer';
|
|
2
|
-
import { merge } from 'lodash-es';
|
|
3
2
|
import type { StateCreator } from 'zustand/vanilla';
|
|
4
3
|
|
|
4
|
+
import { merge } from '@/utils/merge';
|
|
5
5
|
import { setNamespace } from '@/utils/storeDebug';
|
|
6
6
|
|
|
7
7
|
import type { GlobalPreference, GlobalState, Guide, SidebarTabKey } from '../initialState';
|
|
@@ -47,14 +47,13 @@ export const createCommonSlice: StateCreator<
|
|
|
47
47
|
},
|
|
48
48
|
updateGuideState: (guide) => {
|
|
49
49
|
const { updatePreference } = get();
|
|
50
|
-
const nextGuide = merge(
|
|
50
|
+
const nextGuide = merge(get().preference.guide, guide);
|
|
51
51
|
updatePreference({ guide: nextGuide });
|
|
52
52
|
},
|
|
53
|
-
|
|
54
53
|
updatePreference: (preference, action) => {
|
|
55
54
|
set(
|
|
56
55
|
produce((draft: GlobalState) => {
|
|
57
|
-
draft.preference = merge(
|
|
56
|
+
draft.preference = merge(draft.preference, preference);
|
|
58
57
|
}),
|
|
59
58
|
false,
|
|
60
59
|
action,
|
package/src/types/locale.ts
CHANGED
package/src/types/settings.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NeutralColors, PrimaryColors } from '@lobehub/ui';
|
|
2
2
|
import type { ThemeMode } from 'antd-style';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import { LocaleMode } from '@/types/locale';
|
|
5
5
|
import type { LobeAgentSession } from '@/types/session';
|
|
6
6
|
|
|
7
7
|
export interface GlobalBaseSettings {
|
|
@@ -36,7 +36,7 @@ export interface GlobalBaseSettings {
|
|
|
36
36
|
* @deprecated
|
|
37
37
|
*/
|
|
38
38
|
historyCount?: number;
|
|
39
|
-
language:
|
|
39
|
+
language: LocaleMode;
|
|
40
40
|
neutralColor?: NeutralColors;
|
|
41
41
|
password: string;
|
|
42
42
|
primaryColor?: PrimaryColors;
|
package/src/utils/env.ts
CHANGED
package/src/utils/responsive.ts
CHANGED
package/src/utils/switchLang.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { changeLanguage } from 'i18next';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { LocaleMode } from '@/types/locale';
|
|
4
|
+
|
|
5
|
+
export const switchLang = (locale: LocaleMode) => {
|
|
6
|
+
const lang = locale === 'auto' ? navigator.language : locale;
|
|
7
|
+
|
|
4
8
|
changeLanguage(lang);
|
|
5
9
|
document.documentElement.lang = lang;
|
|
6
10
|
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useResponsive } from 'antd-style';
|
|
2
|
-
import { memo } from 'react';
|
|
3
|
-
import { Flexbox } from 'react-layout-kit';
|
|
4
|
-
|
|
5
|
-
import Desktop from './Desktop';
|
|
6
|
-
import Mobile from './Mobile';
|
|
7
|
-
import { Topic } from './Topic';
|
|
8
|
-
import TopicSearchBar from './TopicSearchBar';
|
|
9
|
-
|
|
10
|
-
const SideBar = memo(() => {
|
|
11
|
-
const { mobile } = useResponsive();
|
|
12
|
-
|
|
13
|
-
const Render = mobile ? Mobile : Desktop;
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<Render>
|
|
17
|
-
<Flexbox height={'100%'} style={{ overflow: 'hidden' }}>
|
|
18
|
-
<Flexbox padding={16}>
|
|
19
|
-
<TopicSearchBar />
|
|
20
|
-
</Flexbox>
|
|
21
|
-
<Flexbox gap={16} paddingInline={16} style={{ overflowY: 'auto', position: 'relative' }}>
|
|
22
|
-
<Topic />
|
|
23
|
-
</Flexbox>
|
|
24
|
-
</Flexbox>
|
|
25
|
-
</Render>
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
export default SideBar;
|
package/src/app/chat/index.tsx
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useResponsive } from 'antd-style';
|
|
4
|
-
import Head from 'next/head';
|
|
5
|
-
import { memo } from 'react';
|
|
6
|
-
import { Flexbox } from 'react-layout-kit';
|
|
7
|
-
|
|
8
|
-
import { useSessionStore } from '@/store/session';
|
|
9
|
-
import { useEffectAfterSessionHydrated } from '@/store/session/hooks';
|
|
10
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
11
|
-
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
12
|
-
|
|
13
|
-
import Conversation from './features/Conversation';
|
|
14
|
-
import Header from './features/Header';
|
|
15
|
-
import SideBar from './features/Sidebar';
|
|
16
|
-
import DesktopLayout from './layout.desktop';
|
|
17
|
-
import MobileLayout from './layout.mobile';
|
|
18
|
-
|
|
19
|
-
const Chat = memo(() => {
|
|
20
|
-
const { mobile } = useResponsive();
|
|
21
|
-
const [avatar, title] = useSessionStore((s) => [
|
|
22
|
-
agentSelectors.currentAgentAvatar(s),
|
|
23
|
-
agentSelectors.currentAgentTitle(s),
|
|
24
|
-
]);
|
|
25
|
-
const pageTitle = genSiteHeadTitle([avatar, title].filter(Boolean).join(' '));
|
|
26
|
-
const RenderLayout = mobile ? MobileLayout : DesktopLayout;
|
|
27
|
-
|
|
28
|
-
useEffectAfterSessionHydrated(
|
|
29
|
-
(store) => {
|
|
30
|
-
store.setState({ isMobile: mobile });
|
|
31
|
-
},
|
|
32
|
-
[mobile],
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<>
|
|
37
|
-
<Head>
|
|
38
|
-
<title>{pageTitle}</title>
|
|
39
|
-
</Head>
|
|
40
|
-
<RenderLayout>
|
|
41
|
-
{!mobile && (
|
|
42
|
-
<>
|
|
43
|
-
<Header />
|
|
44
|
-
<Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
|
|
45
|
-
<Conversation />
|
|
46
|
-
<SideBar />
|
|
47
|
-
</Flexbox>
|
|
48
|
-
</>
|
|
49
|
-
)}
|
|
50
|
-
</RenderLayout>
|
|
51
|
-
</>
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
export default Chat;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { memo } from 'react';
|
|
2
|
-
|
|
3
|
-
import AppMobileLayout from '@/layout/AppMobileLayout';
|
|
4
|
-
import { useSwitchSideBarOnInit } from '@/store/global';
|
|
5
|
-
import { SidebarTabKey } from '@/store/global/initialState';
|
|
6
|
-
|
|
7
|
-
import { Sessions } from './features/SessionList';
|
|
8
|
-
import Header from './features/SessionList/Header';
|
|
9
|
-
|
|
10
|
-
const ChatMobileLayout = memo(() => {
|
|
11
|
-
useSwitchSideBarOnInit(SidebarTabKey.Chat);
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<AppMobileLayout navBar={<Header />} showTabBar>
|
|
15
|
-
<Sessions />
|
|
16
|
-
</AppMobileLayout>
|
|
17
|
-
);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
export default ChatMobileLayout;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import Head from 'next/head';
|
|
4
|
-
import { memo } from 'react';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
import AppMobileLayout from '@/layout/AppMobileLayout';
|
|
8
|
-
import { useSessionStore } from '@/store/session';
|
|
9
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
10
|
-
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
11
|
-
|
|
12
|
-
import Conversation from '../features/Conversation';
|
|
13
|
-
import Header from '../features/Header';
|
|
14
|
-
import SideBar from '../features/Sidebar';
|
|
15
|
-
|
|
16
|
-
const Chat = memo(() => {
|
|
17
|
-
const [avatar, title] = useSessionStore((s) => [
|
|
18
|
-
agentSelectors.currentAgentAvatar(s),
|
|
19
|
-
agentSelectors.currentAgentTitle(s),
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
const pageTitle = genSiteHeadTitle([avatar, title].filter(Boolean).join(' '));
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<>
|
|
26
|
-
<Head>
|
|
27
|
-
<title>{pageTitle}</title>
|
|
28
|
-
</Head>
|
|
29
|
-
<AppMobileLayout navBar={<Header />}>
|
|
30
|
-
<Flexbox height={'calc(100vh - 44px)'} horizontal>
|
|
31
|
-
<Conversation mobile />
|
|
32
|
-
<SideBar />
|
|
33
|
-
</Flexbox>
|
|
34
|
-
</AppMobileLayout>
|
|
35
|
-
</>
|
|
36
|
-
);
|
|
37
|
-
});
|
|
38
|
-
export default Chat;
|