@lobehub/chat 0.72.4 → 0.73.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 +25 -0
- package/next.config.mjs +6 -2
- package/package.json +5 -10
- package/src/config/server.ts +2 -0
- package/src/const/fetch.ts +15 -2
- package/src/const/llm.ts +17 -0
- package/src/const/settings.ts +16 -8
- package/src/locales/default/setting.ts +59 -13
- package/src/pages/api/{openai.ts → createChatCompletion.ts} +7 -36
- package/src/pages/api/openai/chat.api.ts +43 -0
- package/src/pages/api/openai/createAzureOpenai.ts +26 -0
- package/src/pages/api/openai/createOpenai.ts +17 -0
- package/src/pages/api/openai/models.api.ts +17 -0
- package/src/pages/settings/features/Settings/Common.tsx +2 -26
- package/src/pages/settings/features/Settings/LLM/Checker.tsx +85 -0
- package/src/pages/settings/features/Settings/LLM/ModelList.tsx +51 -0
- package/src/pages/settings/features/Settings/LLM/getModelList.ts +9 -0
- package/src/pages/settings/features/Settings/LLM/index.tsx +152 -0
- package/src/pages/settings/features/Settings/index.tsx +13 -12
- package/src/services/_header.ts +33 -0
- package/src/services/_url.ts +17 -0
- package/src/services/chatModel.ts +4 -10
- package/src/services/modelList.ts +15 -0
- package/src/services/plugin.ts +1 -1
- package/src/services/pluginMarket.ts +1 -1
- package/src/store/global/hooks/index.ts +1 -0
- package/src/store/global/hooks/useEffectAfterHydrated.ts +22 -0
- package/src/store/global/initialState.ts +4 -0
- package/src/store/global/selectors.test.ts +264 -0
- package/src/store/global/selectors.ts +4 -5
- package/src/store/global/slices/settings.ts +16 -4
- package/src/store/global/store.ts +34 -5
- package/src/types/settings.ts +45 -8
- package/src/utils/fetch.ts +4 -12
- package/src/pages/api/openai.api.ts +0 -24
- package/src/services/url.ts +0 -8
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Form, Markdown } from '@lobehub/ui';
|
|
2
|
+
import { Form as AntForm, AutoComplete, Input, Switch } from 'antd';
|
|
3
|
+
import { createStyles } from 'antd-style';
|
|
4
|
+
import { debounce } from 'lodash-es';
|
|
5
|
+
import { Webhook } from 'lucide-react';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
import { memo } from 'react';
|
|
8
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
9
|
+
import { Flexbox } from 'react-layout-kit';
|
|
10
|
+
|
|
11
|
+
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
12
|
+
import { globalSelectors, useEffectAfterGlobalHydrated, useGlobalStore } from '@/store/global';
|
|
13
|
+
|
|
14
|
+
import Checker from './Checker';
|
|
15
|
+
|
|
16
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
17
|
+
markdown: css`
|
|
18
|
+
a {
|
|
19
|
+
font-size: 12px !important;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
p {
|
|
23
|
+
font-size: 12px !important;
|
|
24
|
+
color: ${token.colorTextDescription} !important;
|
|
25
|
+
}
|
|
26
|
+
`,
|
|
27
|
+
plan: css`
|
|
28
|
+
color: ${token.colorTextDescription};
|
|
29
|
+
`,
|
|
30
|
+
tip: css`
|
|
31
|
+
font-size: 12px;
|
|
32
|
+
color: ${token.colorTextDescription};
|
|
33
|
+
`,
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
const configKey = 'languageModel';
|
|
37
|
+
|
|
38
|
+
const LLM = memo(() => {
|
|
39
|
+
const { t } = useTranslation('setting');
|
|
40
|
+
const [form] = AntForm.useForm();
|
|
41
|
+
const { styles } = useStyles();
|
|
42
|
+
const [setSettings] = useGlobalStore((s) => [s.setSettings]);
|
|
43
|
+
|
|
44
|
+
useEffectAfterGlobalHydrated((store) => {
|
|
45
|
+
const settings = globalSelectors.currentSettings(store.getState());
|
|
46
|
+
|
|
47
|
+
form.setFieldsValue(settings);
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
const useAzure = useGlobalStore((s) => s.settings.languageModel.openAI.useAzure);
|
|
51
|
+
|
|
52
|
+
const openAI = {
|
|
53
|
+
children: [
|
|
54
|
+
{
|
|
55
|
+
children: (
|
|
56
|
+
<Input.Password
|
|
57
|
+
placeholder={
|
|
58
|
+
useAzure ? t('llm.AzureOpenAI.token.placeholder') : t('llm.OpenAI.token.placeholder')
|
|
59
|
+
}
|
|
60
|
+
/>
|
|
61
|
+
),
|
|
62
|
+
desc: useAzure ? t('llm.AzureOpenAI.token.desc') : t('llm.OpenAI.token.desc'),
|
|
63
|
+
label: useAzure ? t('llm.AzureOpenAI.token.title') : t('llm.OpenAI.token.title'),
|
|
64
|
+
name: [configKey, 'openAI', 'OPENAI_API_KEY'],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
children: (
|
|
68
|
+
<Input
|
|
69
|
+
allowClear
|
|
70
|
+
placeholder={
|
|
71
|
+
useAzure
|
|
72
|
+
? t('llm.AzureOpenAI.endpoint.placeholder')
|
|
73
|
+
: t('llm.OpenAI.endpoint.placeholder')
|
|
74
|
+
}
|
|
75
|
+
/>
|
|
76
|
+
),
|
|
77
|
+
desc: useAzure ? t('llm.AzureOpenAI.endpoint.desc') : t('llm.OpenAI.endpoint.desc'),
|
|
78
|
+
|
|
79
|
+
label: useAzure ? t('llm.AzureOpenAI.endpoint.title') : t('llm.OpenAI.endpoint.title'),
|
|
80
|
+
|
|
81
|
+
name: [configKey, 'openAI', 'endpoint'],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
children: <Switch />,
|
|
85
|
+
desc: t('llm.OpenAI.useAzure.desc'),
|
|
86
|
+
label: t('llm.OpenAI.useAzure.title'),
|
|
87
|
+
name: [configKey, 'openAI', 'useAzure'],
|
|
88
|
+
valuePropName: 'checked',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
children: (
|
|
92
|
+
<AutoComplete
|
|
93
|
+
options={[
|
|
94
|
+
'2023-08-01-preview',
|
|
95
|
+
'2023-07-01-preview',
|
|
96
|
+
'2023-06-01-preview',
|
|
97
|
+
'2023-05-15',
|
|
98
|
+
'2023-03-15-preview',
|
|
99
|
+
].map((i) => ({
|
|
100
|
+
label: i,
|
|
101
|
+
value: i,
|
|
102
|
+
}))}
|
|
103
|
+
placeholder={'20XX-XX-XX'}
|
|
104
|
+
/>
|
|
105
|
+
),
|
|
106
|
+
desc: (
|
|
107
|
+
<Markdown className={styles.markdown}>{t('llm.OpenAI.azureApiVersion.desc')}</Markdown>
|
|
108
|
+
),
|
|
109
|
+
hidden: !useAzure,
|
|
110
|
+
label: t('llm.OpenAI.azureApiVersion.title'),
|
|
111
|
+
name: [configKey, 'openAI', 'azureApiVersion'],
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
children: <Checker checkModel={!useAzure} />,
|
|
115
|
+
desc: t('llm.OpenAI.check.desc'),
|
|
116
|
+
label: t('llm.OpenAI.check.title'),
|
|
117
|
+
},
|
|
118
|
+
// {
|
|
119
|
+
// children: useAzure ? <Flexbox>{t('llm.OpenAI.models.notSupport')}</Flexbox> : <ModelList />,
|
|
120
|
+
// desc: useAzure ? t('llm.OpenAI.models.notSupportTip') : t('llm.OpenAI.models.desc'),
|
|
121
|
+
// label: t('llm.OpenAI.models.title'),
|
|
122
|
+
// name: [configKey, 'openAI', 'models'],
|
|
123
|
+
// },
|
|
124
|
+
],
|
|
125
|
+
icon: Webhook,
|
|
126
|
+
title: t('llm.OpenAI.title'),
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Flexbox align={'center'} gap={24} width={'100%'}>
|
|
131
|
+
<Form
|
|
132
|
+
form={form}
|
|
133
|
+
items={[openAI]}
|
|
134
|
+
onValuesChange={debounce(setSettings, 100)}
|
|
135
|
+
{...FORM_STYLE}
|
|
136
|
+
/>
|
|
137
|
+
<Flexbox align={'center'} className={styles.plan}>
|
|
138
|
+
<div>
|
|
139
|
+
<Trans i18nKey="llm.waitingForMore" ns={'setting'}>
|
|
140
|
+
更多模型正在
|
|
141
|
+
<Link href="https://github.com/lobehub/lobe-chat/issues/151" target="_blank">
|
|
142
|
+
计划接入
|
|
143
|
+
</Link>
|
|
144
|
+
中 ,敬请期待 ✨
|
|
145
|
+
</Trans>
|
|
146
|
+
</div>
|
|
147
|
+
</Flexbox>
|
|
148
|
+
</Flexbox>
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export default LLM;
|
|
@@ -2,13 +2,16 @@ import { GridBackground, Icon, Logo, TabsNav } from '@lobehub/ui';
|
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
3
|
import { PackageCheck } from 'lucide-react';
|
|
4
4
|
import { rgba } from 'polished';
|
|
5
|
-
import { memo
|
|
5
|
+
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
|
+
import { useGlobalStore } from '@/store/global';
|
|
10
|
+
|
|
9
11
|
import pkg from '../../../../../package.json';
|
|
10
12
|
import Agent from './Agent';
|
|
11
13
|
import Common from './Common';
|
|
14
|
+
import LLM from './LLM';
|
|
12
15
|
|
|
13
16
|
const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
14
17
|
background: css`
|
|
@@ -55,16 +58,12 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
|
55
58
|
`,
|
|
56
59
|
}));
|
|
57
60
|
|
|
58
|
-
enum Tabs {
|
|
59
|
-
agent = 'agent',
|
|
60
|
-
common = 'common',
|
|
61
|
-
}
|
|
62
|
-
|
|
63
61
|
const Settings = memo(() => {
|
|
64
|
-
const [tab, setTab] = useState<Tabs>(Tabs.common);
|
|
65
62
|
const { styles, theme } = useStyles();
|
|
66
63
|
const { t } = useTranslation('setting');
|
|
67
64
|
|
|
65
|
+
const [tab, setTab] = useGlobalStore((s) => [s.settingsTab, s.switchSettingTabs]);
|
|
66
|
+
|
|
68
67
|
return (
|
|
69
68
|
<Center gap={16} width={'100%'}>
|
|
70
69
|
<Flexbox align={'flex-end'} className={styles.tabs} horizontal justify={'center'}>
|
|
@@ -78,10 +77,11 @@ const Settings = memo(() => {
|
|
|
78
77
|
<TabsNav
|
|
79
78
|
activeKey={tab}
|
|
80
79
|
items={[
|
|
81
|
-
{ key:
|
|
82
|
-
{ key:
|
|
80
|
+
{ key: 'common', label: t('tab.common') },
|
|
81
|
+
{ key: 'llm', label: t('tab.llm') },
|
|
82
|
+
{ key: 'agent', label: t('tab.agent') },
|
|
83
83
|
]}
|
|
84
|
-
onChange={(e) => setTab(e as
|
|
84
|
+
onChange={(e) => setTab(e as any)}
|
|
85
85
|
/>
|
|
86
86
|
<div className={styles.logo}>
|
|
87
87
|
<Logo extra={'Chat'} type={'text'} />
|
|
@@ -91,8 +91,9 @@ const Settings = memo(() => {
|
|
|
91
91
|
<div>{`${pkg.version}`}</div>
|
|
92
92
|
</Flexbox>
|
|
93
93
|
</Flexbox>
|
|
94
|
-
{tab ===
|
|
95
|
-
{tab ===
|
|
94
|
+
{tab === 'common' && <Common />}
|
|
95
|
+
{tab === 'llm' && <LLM />}
|
|
96
|
+
{tab === 'agent' && <Agent />}
|
|
96
97
|
</Center>
|
|
97
98
|
);
|
|
98
99
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AZURE_OPENAI_API_VERSION,
|
|
3
|
+
LOBE_CHAT_ACCESS_CODE,
|
|
4
|
+
OPENAI_API_KEY_HEADER_KEY,
|
|
5
|
+
OPENAI_END_POINT,
|
|
6
|
+
USE_AZURE_OPENAI,
|
|
7
|
+
} from '@/const/fetch';
|
|
8
|
+
import { useGlobalStore } from '@/store/global';
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line no-undef
|
|
11
|
+
export const createHeaderWithOpenAI = (header?: HeadersInit): HeadersInit => {
|
|
12
|
+
const openai = useGlobalStore.getState().settings.languageModel.openAI;
|
|
13
|
+
|
|
14
|
+
const apiKey = openai.OPENAI_API_KEY || useGlobalStore.getState().settings.OPENAI_API_KEY || '';
|
|
15
|
+
const endpoint = openai.endpoint || useGlobalStore.getState().settings.endpoint || '';
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line no-undef
|
|
18
|
+
const result: HeadersInit = {
|
|
19
|
+
...header,
|
|
20
|
+
[LOBE_CHAT_ACCESS_CODE]: useGlobalStore.getState().settings.password || '',
|
|
21
|
+
[OPENAI_API_KEY_HEADER_KEY]: apiKey,
|
|
22
|
+
[OPENAI_END_POINT]: endpoint,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
if (openai.useAzure) {
|
|
26
|
+
Object.assign(result, {
|
|
27
|
+
[AZURE_OPENAI_API_VERSION]: openai.azureApiVersion,
|
|
28
|
+
[USE_AZURE_OPENAI]: '1',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
2
|
+
|
|
3
|
+
const prefix = isDev ? '-dev' : '';
|
|
4
|
+
|
|
5
|
+
export const URLS = {
|
|
6
|
+
plugins: '/api/plugins' + prefix,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const OPENAI_URLS = {
|
|
10
|
+
chat: '/api/openai/chat' + prefix,
|
|
11
|
+
models: '/api/openai/models' + prefix,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const AZURE_OPENAI_URLS = {
|
|
15
|
+
chat: '/api/azure-openai/chat' + prefix,
|
|
16
|
+
models: '/api/azure-openai/models' + prefix,
|
|
17
|
+
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { merge } from 'lodash-es';
|
|
2
2
|
|
|
3
|
-
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY, OPENAI_END_POINT } from '@/const/fetch';
|
|
4
|
-
import { useGlobalStore } from '@/store/global';
|
|
5
3
|
import { pluginSelectors, usePluginStore } from '@/store/plugin';
|
|
6
4
|
import { initialLobeAgentConfig } from '@/store/session/initialState';
|
|
7
5
|
import type { ChatCompletionFunctions, OpenAIStreamPayload } from '@/types/openai';
|
|
8
6
|
|
|
9
|
-
import {
|
|
7
|
+
import { createHeaderWithOpenAI } from './_header';
|
|
8
|
+
import { OPENAI_URLS } from './_url';
|
|
10
9
|
|
|
11
10
|
interface FetchChatModelOptions {
|
|
12
11
|
signal?: AbortSignal | undefined;
|
|
@@ -35,14 +34,9 @@ export const fetchChatModel = (
|
|
|
35
34
|
|
|
36
35
|
const functions = filterFunctions.length === 0 ? undefined : filterFunctions;
|
|
37
36
|
|
|
38
|
-
return fetch(
|
|
37
|
+
return fetch(OPENAI_URLS.chat, {
|
|
39
38
|
body: JSON.stringify({ ...payload, functions }),
|
|
40
|
-
headers: {
|
|
41
|
-
'Content-Type': 'application/json',
|
|
42
|
-
[LOBE_CHAT_ACCESS_CODE]: useGlobalStore.getState().settings.password || '',
|
|
43
|
-
[OPENAI_API_KEY_HEADER_KEY]: useGlobalStore.getState().settings.OPENAI_API_KEY || '',
|
|
44
|
-
[OPENAI_END_POINT]: useGlobalStore.getState().settings.endpoint || '',
|
|
45
|
-
},
|
|
39
|
+
headers: createHeaderWithOpenAI({ 'Content-Type': 'application/json' }),
|
|
46
40
|
method: 'POST',
|
|
47
41
|
signal: options?.signal,
|
|
48
42
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LanguageModelWhiteList } from '@/const/llm';
|
|
2
|
+
|
|
3
|
+
import { createHeaderWithOpenAI } from './_header';
|
|
4
|
+
import { OPENAI_URLS } from './_url';
|
|
5
|
+
|
|
6
|
+
export const fetchModelList = async (): Promise<string[]> => {
|
|
7
|
+
const res = await fetch(OPENAI_URLS.models, {
|
|
8
|
+
headers: createHeaderWithOpenAI(),
|
|
9
|
+
method: 'POST',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const modelList: string[] = await res.json();
|
|
13
|
+
|
|
14
|
+
return LanguageModelWhiteList.filter((i) => modelList.includes(i));
|
|
15
|
+
};
|
package/src/services/plugin.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { PluginRequestPayload, createHeadersWithPluginSettings } from '@lobehub/
|
|
|
3
3
|
import { pluginSelectors, usePluginStore } from '@/store/plugin';
|
|
4
4
|
import { getMessageError } from '@/utils/fetch';
|
|
5
5
|
|
|
6
|
-
import { URLS } from './
|
|
6
|
+
import { URLS } from './_url';
|
|
7
7
|
|
|
8
8
|
interface FetchChatModelOptions {
|
|
9
9
|
signal?: AbortSignal | undefined;
|
|
@@ -2,7 +2,7 @@ import { getPluginIndexJSON } from '@/const/url';
|
|
|
2
2
|
import { useGlobalStore } from '@/store/global';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* fetch Plugin Market List
|
|
6
6
|
*/
|
|
7
7
|
export const getPluginList = async () => {
|
|
8
8
|
const url = getPluginIndexJSON(useGlobalStore.getState().settings.language);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useGlobalStore } from '../store';
|
|
4
|
+
|
|
5
|
+
export const useEffectAfterGlobalHydrated = (
|
|
6
|
+
fn: (store: typeof useGlobalStore) => void,
|
|
7
|
+
deps: any[] = [],
|
|
8
|
+
) => {
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const hasRehydrated = useGlobalStore.persist.hasHydrated();
|
|
11
|
+
|
|
12
|
+
if (hasRehydrated) {
|
|
13
|
+
// 等价 useEffect 多次触发
|
|
14
|
+
fn(useGlobalStore);
|
|
15
|
+
} else {
|
|
16
|
+
// 等价于 useEffect 第一次触发
|
|
17
|
+
useGlobalStore.persist.onFinishHydration(() => {
|
|
18
|
+
fn(useGlobalStore);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}, deps);
|
|
22
|
+
};
|
|
@@ -3,6 +3,8 @@ import type { GlobalSettings } from '@/types/settings';
|
|
|
3
3
|
|
|
4
4
|
export type SidebarTabKey = 'chat' | 'market' | 'settings';
|
|
5
5
|
|
|
6
|
+
export type SettingsTabs = 'agent' | 'common' | 'llm';
|
|
7
|
+
|
|
6
8
|
export interface Guide {
|
|
7
9
|
// Topic 引导
|
|
8
10
|
topic?: boolean;
|
|
@@ -19,6 +21,7 @@ export interface GlobalState {
|
|
|
19
21
|
* 用户设置
|
|
20
22
|
*/
|
|
21
23
|
settings: GlobalSettings;
|
|
24
|
+
settingsTab: SettingsTabs;
|
|
22
25
|
sidebarKey: SidebarTabKey;
|
|
23
26
|
}
|
|
24
27
|
|
|
@@ -41,5 +44,6 @@ export const initialState: GlobalState = {
|
|
|
41
44
|
showSessionPanel: true,
|
|
42
45
|
},
|
|
43
46
|
settings: DEFAULT_SETTINGS,
|
|
47
|
+
settingsTab: 'common',
|
|
44
48
|
sidebarKey: 'chat',
|
|
45
49
|
};
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { LanguageModel } from '@/types/llm';
|
|
2
|
+
|
|
3
|
+
import { globalSelectors } from './selectors';
|
|
4
|
+
import { GlobalStore } from './store';
|
|
5
|
+
|
|
6
|
+
describe('globalSelectors', () => {
|
|
7
|
+
describe('currentSettings', () => {
|
|
8
|
+
it('should merge DEFAULT_SETTINGS and s.settings correctly', () => {
|
|
9
|
+
const s = {
|
|
10
|
+
settings: {
|
|
11
|
+
avatar: 'avatar.jpg',
|
|
12
|
+
fontSize: 14,
|
|
13
|
+
language: 'en-US',
|
|
14
|
+
neutralColor: 'sand',
|
|
15
|
+
password: 'password123',
|
|
16
|
+
primaryColor: 'blue',
|
|
17
|
+
themeMode: 'light',
|
|
18
|
+
defaultAgent: {
|
|
19
|
+
config: {
|
|
20
|
+
systemRole: '',
|
|
21
|
+
model: LanguageModel.GPT3_5,
|
|
22
|
+
params: {},
|
|
23
|
+
},
|
|
24
|
+
meta: {
|
|
25
|
+
avatar: 'Default Agent',
|
|
26
|
+
description: 'Default agent for testing',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
languageModel: {
|
|
30
|
+
openAI: {
|
|
31
|
+
OPENAI_API_KEY: 'openai-api-key',
|
|
32
|
+
endpoint: 'https://openai-endpoint.com',
|
|
33
|
+
models: ['gpt-3.5-turbo'],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
} as unknown as GlobalStore;
|
|
38
|
+
|
|
39
|
+
const result = globalSelectors.currentSettings(s);
|
|
40
|
+
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
avatar: 'avatar.jpg',
|
|
43
|
+
fontSize: 14,
|
|
44
|
+
language: 'en-US',
|
|
45
|
+
neutralColor: 'sand',
|
|
46
|
+
password: 'password123',
|
|
47
|
+
primaryColor: 'blue',
|
|
48
|
+
themeMode: 'light',
|
|
49
|
+
defaultAgent: {
|
|
50
|
+
config: {
|
|
51
|
+
displayMode: 'chat',
|
|
52
|
+
historyCount: 1,
|
|
53
|
+
systemRole: '',
|
|
54
|
+
model: LanguageModel.GPT3_5,
|
|
55
|
+
params: {
|
|
56
|
+
frequency_penalty: 0,
|
|
57
|
+
presence_penalty: 0,
|
|
58
|
+
temperature: 0.6,
|
|
59
|
+
top_p: 1,
|
|
60
|
+
},
|
|
61
|
+
plugins: [],
|
|
62
|
+
},
|
|
63
|
+
meta: {
|
|
64
|
+
avatar: 'Default Agent',
|
|
65
|
+
description: 'Default agent for testing',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
languageModel: {
|
|
69
|
+
openAI: {
|
|
70
|
+
OPENAI_API_KEY: 'openai-api-key',
|
|
71
|
+
azureApiVersion: '2023-08-01-preview',
|
|
72
|
+
endpoint: 'https://openai-endpoint.com',
|
|
73
|
+
models: ['gpt-3.5-turbo'],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//
|
|
80
|
+
// describe('defaultAgent', () => {
|
|
81
|
+
// it('should merge DEFAULT_AGENT and s.settings.defaultAgent correctly', () => {
|
|
82
|
+
// const s: GlobalStore = {
|
|
83
|
+
// settings: {
|
|
84
|
+
// defaultAgent: {
|
|
85
|
+
// config: {
|
|
86
|
+
// model: 'gpt-3.5-turbo',
|
|
87
|
+
// maxTokens: 100,
|
|
88
|
+
// },
|
|
89
|
+
// meta: {
|
|
90
|
+
// name: 'Default Agent',
|
|
91
|
+
// description: 'Default agent for testing',
|
|
92
|
+
// },
|
|
93
|
+
// },
|
|
94
|
+
// },
|
|
95
|
+
// };
|
|
96
|
+
//
|
|
97
|
+
// const result = globalSelectors.defaultAgent(s);
|
|
98
|
+
//
|
|
99
|
+
//
|
|
100
|
+
//
|
|
101
|
+
// expect(result).toEqual(expected);
|
|
102
|
+
// });
|
|
103
|
+
// });
|
|
104
|
+
//
|
|
105
|
+
// describe('defaultAgentConfig', () => {
|
|
106
|
+
// it('should merge DEFAULT_AGENT_CONFIG and defaultAgent(s).config correctly', () => {
|
|
107
|
+
// const s: GlobalStore = {
|
|
108
|
+
// settings: {
|
|
109
|
+
// defaultAgent: {
|
|
110
|
+
// config: {
|
|
111
|
+
// model: 'gpt-3.5-turbo',
|
|
112
|
+
// maxTokens: 100,
|
|
113
|
+
// },
|
|
114
|
+
// },
|
|
115
|
+
// },
|
|
116
|
+
// };
|
|
117
|
+
//
|
|
118
|
+
// const result = globalSelectors.defaultAgentConfig(s);
|
|
119
|
+
//
|
|
120
|
+
// const defaultAgent = globalSelectors.defaultAgent(s);
|
|
121
|
+
// const expected = merge({}, DEFAULT_AGENT_CONFIG, defaultAgent.config);
|
|
122
|
+
//
|
|
123
|
+
// expect(result).toEqual(expected);
|
|
124
|
+
// });
|
|
125
|
+
// });
|
|
126
|
+
//
|
|
127
|
+
// describe('defaultAgentMeta', () => {
|
|
128
|
+
// it('should merge DEFAULT_AGENT_META and defaultAgent(s).meta correctly', () => {
|
|
129
|
+
// const s: GlobalStore = {
|
|
130
|
+
// settings: {
|
|
131
|
+
// defaultAgent: {
|
|
132
|
+
// meta: {
|
|
133
|
+
// name: 'Default Agent',
|
|
134
|
+
// description: 'Default agent for testing',
|
|
135
|
+
// },
|
|
136
|
+
// },
|
|
137
|
+
// },
|
|
138
|
+
// };
|
|
139
|
+
//
|
|
140
|
+
// const result = globalSelectors.defaultAgentMeta(s);
|
|
141
|
+
//
|
|
142
|
+
// const defaultAgent = globalSelectors.defaultAgent(s);
|
|
143
|
+
// const expected = merge({}, DEFAULT_AGENT_META, defaultAgent.meta);
|
|
144
|
+
//
|
|
145
|
+
// expect(result).toEqual(expected);
|
|
146
|
+
// });
|
|
147
|
+
// });
|
|
148
|
+
//
|
|
149
|
+
// describe('exportSettings', () => {
|
|
150
|
+
// it('should remove OPENAI_API_KEY and password fields from s.settings', () => {
|
|
151
|
+
// const s: GlobalStore = {
|
|
152
|
+
// settings: {
|
|
153
|
+
// OPENAI_API_KEY: 'openai-api-key',
|
|
154
|
+
// password: 'password123',
|
|
155
|
+
// avatar: 'avatar.jpg',
|
|
156
|
+
// fontSize: 14,
|
|
157
|
+
// language: 'en',
|
|
158
|
+
// neutralColor: 'white',
|
|
159
|
+
// primaryColor: 'blue',
|
|
160
|
+
// themeMode: 'light',
|
|
161
|
+
// defaultAgent: {
|
|
162
|
+
// config: {
|
|
163
|
+
// model: 'gpt-3.5-turbo',
|
|
164
|
+
// maxTokens: 100,
|
|
165
|
+
// },
|
|
166
|
+
// meta: {
|
|
167
|
+
// name: 'Default Agent',
|
|
168
|
+
// description: 'Default agent for testing',
|
|
169
|
+
// },
|
|
170
|
+
// },
|
|
171
|
+
// languageModel: {
|
|
172
|
+
// azureOpenAI: {
|
|
173
|
+
// AZURE_API_KEY: 'azure-api-key',
|
|
174
|
+
// apiVersion: 'v1',
|
|
175
|
+
// endpoint: 'https://azure-openai-endpoint.com',
|
|
176
|
+
// models: ['gpt-3.5-turbo'],
|
|
177
|
+
// },
|
|
178
|
+
// openAI: {
|
|
179
|
+
// OPENAI_API_KEY: 'openai-api-key',
|
|
180
|
+
// endpoint: 'https://openai-endpoint.com',
|
|
181
|
+
// models: ['gpt-3.5-turbo'],
|
|
182
|
+
// },
|
|
183
|
+
// },
|
|
184
|
+
// },
|
|
185
|
+
// };
|
|
186
|
+
//
|
|
187
|
+
// const result = globalSelectors.exportSettings(s);
|
|
188
|
+
//
|
|
189
|
+
// const expected = {
|
|
190
|
+
// avatar: 'avatar.jpg',
|
|
191
|
+
// fontSize: 14,
|
|
192
|
+
// language: 'en',
|
|
193
|
+
// neutralColor: 'white',
|
|
194
|
+
// primaryColor: 'blue',
|
|
195
|
+
// themeMode: 'light',
|
|
196
|
+
// defaultAgent: {
|
|
197
|
+
// config: {
|
|
198
|
+
// model: 'gpt-3.5-turbo',
|
|
199
|
+
// maxTokens: 100,
|
|
200
|
+
// },
|
|
201
|
+
// meta: {
|
|
202
|
+
// name: 'Default Agent',
|
|
203
|
+
// description: 'Default agent for testing',
|
|
204
|
+
// },
|
|
205
|
+
// },
|
|
206
|
+
// languageModel: {
|
|
207
|
+
// azureOpenAI: {
|
|
208
|
+
// AZURE_API_KEY: 'azure-api-key',
|
|
209
|
+
// apiVersion: 'v1',
|
|
210
|
+
// endpoint: 'https://azure-openai-endpoint.com',
|
|
211
|
+
// models: ['gpt-3.5-turbo'],
|
|
212
|
+
// },
|
|
213
|
+
// openAI: {
|
|
214
|
+
// endpoint: 'https://openai-endpoint.com',
|
|
215
|
+
// models: ['gpt-3.5-turbo'],
|
|
216
|
+
// },
|
|
217
|
+
// },
|
|
218
|
+
// };
|
|
219
|
+
//
|
|
220
|
+
// expect(result).toEqual(expected);
|
|
221
|
+
// });
|
|
222
|
+
//
|
|
223
|
+
// it('should return the result as GlobalSettings type', () => {
|
|
224
|
+
// const s: GlobalStore = {
|
|
225
|
+
// settings: {
|
|
226
|
+
// avatar: 'avatar.jpg',
|
|
227
|
+
// fontSize: 14,
|
|
228
|
+
// language: 'en',
|
|
229
|
+
// neutralColor: 'white',
|
|
230
|
+
// password: 'password123',
|
|
231
|
+
// primaryColor: 'blue',
|
|
232
|
+
// themeMode: 'light',
|
|
233
|
+
// defaultAgent: {
|
|
234
|
+
// config: {
|
|
235
|
+
// model: 'gpt-3.5-turbo',
|
|
236
|
+
// maxTokens: 100,
|
|
237
|
+
// },
|
|
238
|
+
// meta: {
|
|
239
|
+
// name: 'Default Agent',
|
|
240
|
+
// description: 'Default agent for testing',
|
|
241
|
+
// },
|
|
242
|
+
// },
|
|
243
|
+
// languageModel: {
|
|
244
|
+
// azureOpenAI: {
|
|
245
|
+
// AZURE_API_KEY: 'azure-api-key',
|
|
246
|
+
// apiVersion: 'v1',
|
|
247
|
+
// endpoint: 'https://azure-openai-endpoint.com',
|
|
248
|
+
// models: ['gpt-3.5-turbo'],
|
|
249
|
+
// },
|
|
250
|
+
// openAI: {
|
|
251
|
+
// OPENAI_API_KEY: 'openai-api-key',
|
|
252
|
+
// endpoint: 'https://openai-endpoint.com',
|
|
253
|
+
// models: ['gpt-3.5-turbo'],
|
|
254
|
+
// },
|
|
255
|
+
// },
|
|
256
|
+
// },
|
|
257
|
+
// };
|
|
258
|
+
//
|
|
259
|
+
// const result = globalSelectors.exportSettings(s);
|
|
260
|
+
//
|
|
261
|
+
// expect(result).toBeInstanceOf(GlobalSettings);
|
|
262
|
+
// });
|
|
263
|
+
// });
|
|
264
|
+
});
|
|
@@ -5,14 +5,13 @@ import { merge } from '@/utils/merge';
|
|
|
5
5
|
|
|
6
6
|
import { GlobalStore } from './store';
|
|
7
7
|
|
|
8
|
-
const currentSettings = (s: GlobalStore) => merge(
|
|
8
|
+
const currentSettings = (s: GlobalStore) => merge(DEFAULT_SETTINGS, s.settings);
|
|
9
9
|
|
|
10
|
-
const defaultAgent = (s: GlobalStore) => merge(
|
|
10
|
+
const defaultAgent = (s: GlobalStore) => merge(DEFAULT_AGENT, s.settings.defaultAgent);
|
|
11
11
|
|
|
12
|
-
const defaultAgentConfig = (s: GlobalStore) =>
|
|
13
|
-
merge({}, DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
12
|
+
const defaultAgentConfig = (s: GlobalStore) => merge(DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
14
13
|
|
|
15
|
-
const defaultAgentMeta = (s: GlobalStore) => merge(
|
|
14
|
+
const defaultAgentMeta = (s: GlobalStore) => merge(DEFAULT_AGENT_META, defaultAgent(s).meta);
|
|
16
15
|
|
|
17
16
|
export const exportSettings = (s: GlobalStore) => {
|
|
18
17
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|