@lobehub/chat 0.161.9 → 0.161.10
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/package.json +1 -1
- package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +5 -2
- package/src/app/(main)/settings/llm/components/ProviderModelList/CustomModelOption.tsx +6 -7
- package/src/app/(main)/settings/llm/components/ProviderModelList/{ModelConfigModal.tsx → ModelConfigModal/Form.tsx} +19 -63
- package/src/app/(main)/settings/llm/components/ProviderModelList/ModelConfigModal/index.tsx +78 -0
- package/src/app/(main)/settings/llm/components/ProviderModelList/Option.tsx +35 -11
- package/src/app/(main)/settings/llm/components/ProviderModelList/index.tsx +15 -18
- package/src/components/ModelProviderIcon/index.tsx +2 -2
- package/src/components/ModelSelect/index.tsx +5 -14
- package/src/features/User/UserPanel/PanelContent.tsx +1 -1
- package/src/hooks/useSyncData.ts +3 -1
- package/src/layout/GlobalProvider/StoreInitialization.tsx +17 -9
- package/src/layout/GlobalProvider/index.tsx +1 -1
- package/src/locales/default/components.ts +1 -0
- package/src/services/message/client.test.ts +0 -24
- package/src/services/message/client.ts +0 -5
- package/src/services/message/type.ts +0 -1
- package/src/services/user/client.test.ts +100 -0
- package/src/services/user/client.ts +16 -14
- package/src/services/user/index.ts +0 -2
- package/src/services/user/type.ts +2 -4
- package/src/store/user/initialState.ts +10 -1
- package/src/store/user/selectors.ts +3 -7
- package/src/store/user/slices/auth/action.test.ts +5 -87
- package/src/store/user/slices/auth/action.ts +3 -58
- package/src/store/user/slices/auth/initialState.ts +2 -1
- package/src/store/user/slices/common/action.test.ts +196 -20
- package/src/store/user/slices/common/action.ts +55 -26
- package/src/store/user/slices/common/initialState.ts +9 -0
- package/src/store/user/slices/modelList/action.test.ts +363 -0
- package/src/store/user/slices/{settings/actions/llm.ts → modelList/action.ts} +66 -60
- package/src/store/user/slices/modelList/initialState.ts +15 -0
- package/src/store/user/slices/modelList/selectors/index.ts +2 -0
- package/src/store/user/slices/{settings → modelList}/selectors/modelConfig.test.ts +3 -2
- package/src/store/user/slices/{settings → modelList}/selectors/modelConfig.ts +1 -1
- package/src/store/user/slices/{settings → modelList}/selectors/modelProvider.test.ts +7 -7
- package/src/store/user/slices/{settings → modelList}/selectors/modelProvider.ts +2 -4
- package/src/store/user/slices/preference/action.test.ts +0 -52
- package/src/store/user/slices/preference/action.ts +1 -17
- package/src/store/user/slices/preference/initialState.ts +0 -5
- package/src/store/user/slices/preference/selectors.test.ts +2 -2
- package/src/store/user/slices/preference/selectors.ts +1 -1
- package/src/store/user/slices/settings/{actions/general.ts → action.ts} +5 -5
- package/src/store/user/slices/settings/initialState.ts +0 -12
- package/src/store/user/slices/settings/selectors/index.ts +0 -3
- package/src/store/user/slices/sync/action.test.ts +19 -5
- package/src/store/user/slices/sync/action.ts +9 -6
- package/src/store/user/slices/{settings/selectors/sync.ts → sync/selectors.ts} +2 -2
- package/src/store/user/store.ts +5 -2
- package/src/types/serverConfig.ts +3 -1
- package/src/types/user/index.ts +13 -0
- package/src/utils/parseModels.test.ts +121 -1
- package/src/utils/parseModels.ts +9 -4
- package/src/store/user/slices/settings/actions/index.ts +0 -18
- package/src/store/user/slices/settings/actions/llm.test.ts +0 -136
- /package/src/app/(main)/settings/llm/components/ProviderModelList/{MaxTokenSlider.tsx → ModelConfigModal/MaxTokenSlider.tsx} +0 -0
- /package/src/store/user/slices/{settings → modelList}/reducers/customModelCard.test.ts +0 -0
- /package/src/store/user/slices/{settings → modelList}/reducers/customModelCard.ts +0 -0
- /package/src/store/user/slices/settings/{actions/general.test.ts → action.test.ts} +0 -0
- /package/src/store/user/slices/settings/selectors/__snapshots__/{selectors.test.ts.snap → settings.test.ts.snap} +0 -0
- /package/src/store/user/slices/settings/selectors/{selectors.test.ts → settings.test.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.161.10](https://github.com/lobehub/lobe-chat/compare/v0.161.9...v0.161.10)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-05-23**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor user store and fix custom model list form.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor user store and fix custom model list form, closes [#2620](https://github.com/lobehub/lobe-chat/issues/2620) ([81ea886](https://github.com/lobehub/lobe-chat/commit/81ea886))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
### [Version 0.161.9](https://github.com/lobehub/lobe-chat/compare/v0.161.8...v0.161.9)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2024-05-23**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.161.
|
|
3
|
+
"version": "0.161.10",
|
|
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",
|
|
@@ -50,6 +50,8 @@ interface ProviderConfigProps {
|
|
|
50
50
|
canDeactivate?: boolean;
|
|
51
51
|
checkModel?: string;
|
|
52
52
|
checkerItem?: FormItemProps;
|
|
53
|
+
className?: string;
|
|
54
|
+
hideSwitch?: boolean;
|
|
53
55
|
modelList?: {
|
|
54
56
|
azureDeployName?: boolean;
|
|
55
57
|
notFoundContent?: ReactNode;
|
|
@@ -81,11 +83,12 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
|
81
83
|
checkerItem,
|
|
82
84
|
modelList,
|
|
83
85
|
showBrowserRequest,
|
|
86
|
+
className,
|
|
84
87
|
}) => {
|
|
85
88
|
const { t } = useTranslation('setting');
|
|
86
89
|
const { t: modelT } = useTranslation('modelProvider');
|
|
87
90
|
const [form] = Form.useForm();
|
|
88
|
-
const { styles } = useStyles();
|
|
91
|
+
const { cx, styles } = useStyles();
|
|
89
92
|
const [
|
|
90
93
|
toggleProviderEnabled,
|
|
91
94
|
setSettings,
|
|
@@ -192,7 +195,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
|
192
195
|
|
|
193
196
|
return (
|
|
194
197
|
<Form
|
|
195
|
-
className={styles.form}
|
|
198
|
+
className={cx(styles.form, className)}
|
|
196
199
|
form={form}
|
|
197
200
|
items={[model]}
|
|
198
201
|
onValuesChange={debounce(setSettings, 100)}
|
|
@@ -71,18 +71,17 @@ const CustomModelOption = memo<CustomModelOptionProps>(({ id, provider }) => {
|
|
|
71
71
|
e.stopPropagation();
|
|
72
72
|
e.preventDefault();
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
await modal.confirm({
|
|
75
75
|
centered: true,
|
|
76
76
|
content: s('llm.customModelCards.confirmDelete'),
|
|
77
77
|
okButtonProps: { danger: true },
|
|
78
|
+
onOk: async () => {
|
|
79
|
+
// delete model and deactivate id
|
|
80
|
+
await dispatchCustomModelCards(provider, { id, type: 'delete' });
|
|
81
|
+
await removeEnabledModels(provider, id);
|
|
82
|
+
},
|
|
78
83
|
type: 'warning',
|
|
79
84
|
});
|
|
80
|
-
|
|
81
|
-
// delete model and deactive id
|
|
82
|
-
if (isConfirm) {
|
|
83
|
-
await dispatchCustomModelCards(provider, { id, type: 'delete' });
|
|
84
|
-
await removeEnabledModels(provider, id);
|
|
85
|
-
}
|
|
86
85
|
}}
|
|
87
86
|
title={t('delete')}
|
|
88
87
|
/>
|
|
@@ -1,71 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import isEqual from 'fast-deep-equal';
|
|
4
|
-
import { memo } from 'react';
|
|
1
|
+
import { Checkbox, Form, FormInstance, Input } from 'antd';
|
|
2
|
+
import { memo, useEffect } from 'react';
|
|
5
3
|
import { useTranslation } from 'react-i18next';
|
|
6
4
|
|
|
7
|
-
import {
|
|
8
|
-
import { modelConfigSelectors } from '@/store/user/selectors';
|
|
5
|
+
import { ChatModelCard } from '@/types/llm';
|
|
9
6
|
|
|
10
7
|
import MaxTokenSlider from './MaxTokenSlider';
|
|
11
8
|
|
|
12
|
-
interface
|
|
13
|
-
|
|
9
|
+
interface ModelConfigFormProps {
|
|
10
|
+
initialValues?: ChatModelCard;
|
|
11
|
+
onFormInstanceReady: (instance: FormInstance) => void;
|
|
14
12
|
showAzureDeployName?: boolean;
|
|
15
13
|
}
|
|
16
|
-
const ModelConfigModal = memo<ModelConfigModalProps>(({ showAzureDeployName, provider }) => {
|
|
17
|
-
const [formInstance] = Form.useForm();
|
|
18
|
-
const { t } = useTranslation('setting');
|
|
19
|
-
const { t: tc } = useTranslation('common');
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
s.editingCustomCardModel?.id,
|
|
25
|
-
s.editingCustomCardModel?.provider,
|
|
26
|
-
s.dispatchCustomModelCards,
|
|
27
|
-
s.toggleEditingCustomModelCard,
|
|
28
|
-
]);
|
|
15
|
+
const ModelConfigForm = memo<ModelConfigFormProps>(
|
|
16
|
+
({ showAzureDeployName, onFormInstanceReady, initialValues }) => {
|
|
17
|
+
const { t } = useTranslation('setting');
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
modelConfigSelectors.getCustomModelCard({ id, provider: editingProvider }),
|
|
32
|
-
isEqual,
|
|
33
|
-
);
|
|
19
|
+
const [formInstance] = Form.useForm();
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
onFormInstanceReady(formInstance);
|
|
23
|
+
}, []);
|
|
38
24
|
|
|
39
|
-
|
|
40
|
-
<Modal
|
|
41
|
-
destroyOnClose
|
|
42
|
-
footer={[
|
|
43
|
-
<Button key="cancel" onClick={closeModal}>
|
|
44
|
-
{tc('cancel')}
|
|
45
|
-
</Button>,
|
|
46
|
-
|
|
47
|
-
<Button
|
|
48
|
-
key="ok"
|
|
49
|
-
onClick={() => {
|
|
50
|
-
if (!editingProvider || !id) return;
|
|
51
|
-
const data = formInstance.getFieldsValue();
|
|
52
|
-
|
|
53
|
-
dispatchCustomModelCards(editingProvider as any, { id, type: 'update', value: data });
|
|
54
|
-
|
|
55
|
-
closeModal();
|
|
56
|
-
}}
|
|
57
|
-
style={{ marginInlineStart: '16px' }}
|
|
58
|
-
type="primary"
|
|
59
|
-
>
|
|
60
|
-
{tc('ok')}
|
|
61
|
-
</Button>,
|
|
62
|
-
]}
|
|
63
|
-
maskClosable
|
|
64
|
-
onCancel={closeModal}
|
|
65
|
-
open={open}
|
|
66
|
-
title={t('llm.customModelCards.modelConfig.modalTitle')}
|
|
67
|
-
zIndex={1051} // Select is 1050
|
|
68
|
-
>
|
|
25
|
+
return (
|
|
69
26
|
<div
|
|
70
27
|
onClick={(e) => {
|
|
71
28
|
e.stopPropagation();
|
|
@@ -77,9 +34,8 @@ const ModelConfigModal = memo<ModelConfigModalProps>(({ showAzureDeployName, pro
|
|
|
77
34
|
<Form
|
|
78
35
|
colon={false}
|
|
79
36
|
form={formInstance}
|
|
80
|
-
initialValues={
|
|
37
|
+
initialValues={initialValues}
|
|
81
38
|
labelCol={{ span: 4 }}
|
|
82
|
-
preserve={false}
|
|
83
39
|
style={{ marginTop: 16 }}
|
|
84
40
|
wrapperCol={{ offset: 1, span: 18 }}
|
|
85
41
|
>
|
|
@@ -136,7 +92,7 @@ const ModelConfigModal = memo<ModelConfigModalProps>(({ showAzureDeployName, pro
|
|
|
136
92
|
</Form.Item>
|
|
137
93
|
</Form>
|
|
138
94
|
</div>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export default
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
export default ModelConfigForm;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Modal } from '@lobehub/ui';
|
|
2
|
+
import { Button, FormInstance } from 'antd';
|
|
3
|
+
import isEqual from 'fast-deep-equal';
|
|
4
|
+
import { memo, useState } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
import { useUserStore } from '@/store/user';
|
|
8
|
+
import { modelConfigSelectors } from '@/store/user/slices/modelList/selectors';
|
|
9
|
+
|
|
10
|
+
import ModelConfigForm from './Form';
|
|
11
|
+
|
|
12
|
+
interface ModelConfigModalProps {
|
|
13
|
+
provider?: string;
|
|
14
|
+
showAzureDeployName?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ModelConfigModal = memo<ModelConfigModalProps>(({ showAzureDeployName, provider }) => {
|
|
18
|
+
const { t } = useTranslation('setting');
|
|
19
|
+
const { t: tc } = useTranslation('common');
|
|
20
|
+
const [formInstance, setFormInstance] = useState<FormInstance>();
|
|
21
|
+
|
|
22
|
+
const [open, id, editingProvider, dispatchCustomModelCards, toggleEditingCustomModelCard] =
|
|
23
|
+
useUserStore((s) => [
|
|
24
|
+
!!s.editingCustomCardModel && provider === s.editingCustomCardModel?.provider,
|
|
25
|
+
s.editingCustomCardModel?.id,
|
|
26
|
+
s.editingCustomCardModel?.provider,
|
|
27
|
+
s.dispatchCustomModelCards,
|
|
28
|
+
s.toggleEditingCustomModelCard,
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
const modelCard = useUserStore(
|
|
32
|
+
modelConfigSelectors.getCustomModelCard({ id, provider: editingProvider }),
|
|
33
|
+
isEqual,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const closeModal = () => {
|
|
37
|
+
toggleEditingCustomModelCard(undefined);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Modal
|
|
42
|
+
destroyOnClose
|
|
43
|
+
footer={[
|
|
44
|
+
<Button key="cancel" onClick={closeModal}>
|
|
45
|
+
{tc('cancel')}
|
|
46
|
+
</Button>,
|
|
47
|
+
|
|
48
|
+
<Button
|
|
49
|
+
key="ok"
|
|
50
|
+
onClick={() => {
|
|
51
|
+
if (!editingProvider || !id || !formInstance) return;
|
|
52
|
+
const data = formInstance.getFieldsValue();
|
|
53
|
+
|
|
54
|
+
dispatchCustomModelCards(editingProvider as any, { id, type: 'update', value: data });
|
|
55
|
+
|
|
56
|
+
closeModal();
|
|
57
|
+
}}
|
|
58
|
+
style={{ marginInlineStart: '16px' }}
|
|
59
|
+
type="primary"
|
|
60
|
+
>
|
|
61
|
+
{tc('ok')}
|
|
62
|
+
</Button>,
|
|
63
|
+
]}
|
|
64
|
+
maskClosable
|
|
65
|
+
onCancel={closeModal}
|
|
66
|
+
open={open}
|
|
67
|
+
title={t('llm.customModelCards.modelConfig.modalTitle')}
|
|
68
|
+
zIndex={1251} // Select is 1150
|
|
69
|
+
>
|
|
70
|
+
<ModelConfigForm
|
|
71
|
+
initialValues={modelCard}
|
|
72
|
+
onFormInstanceReady={setFormInstance}
|
|
73
|
+
showAzureDeployName={showAzureDeployName}
|
|
74
|
+
/>
|
|
75
|
+
</Modal>
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
export default ModelConfigModal;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { ActionIcon, Tooltip } from '@lobehub/ui';
|
|
1
2
|
import { Typography } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
2
4
|
import isEqual from 'fast-deep-equal';
|
|
5
|
+
import { Recycle } from 'lucide-react';
|
|
3
6
|
import { memo } from 'react';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
4
8
|
import { Flexbox } from 'react-layout-kit';
|
|
5
9
|
|
|
6
10
|
import ModelIcon from '@/components/ModelIcon';
|
|
@@ -16,25 +20,45 @@ interface OptionRenderProps {
|
|
|
16
20
|
id: string;
|
|
17
21
|
isAzure?: boolean;
|
|
18
22
|
provider: GlobalLLMProviderKey;
|
|
23
|
+
removed?: boolean;
|
|
19
24
|
}
|
|
20
|
-
const OptionRender = memo<OptionRenderProps>(({ displayName, id, provider, isAzure }) => {
|
|
25
|
+
const OptionRender = memo<OptionRenderProps>(({ displayName, id, provider, isAzure, removed }) => {
|
|
21
26
|
const model = useUserStore((s) => modelProviderSelectors.getModelCardById(id)(s), isEqual);
|
|
22
|
-
|
|
27
|
+
const { t } = useTranslation('components');
|
|
28
|
+
const theme = useTheme();
|
|
23
29
|
// if there is isCustom, it means it is a user defined custom model
|
|
24
30
|
if (model?.isCustom || isAzure) return <CustomModelOption id={id} provider={provider} />;
|
|
25
31
|
|
|
26
32
|
return (
|
|
27
|
-
<Flexbox
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
<Flexbox
|
|
34
|
+
align={'center'}
|
|
35
|
+
gap={8}
|
|
36
|
+
horizontal
|
|
37
|
+
justify={'space-between'}
|
|
38
|
+
style={{ paddingInlineEnd: 8 }}
|
|
39
|
+
>
|
|
40
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
41
|
+
<ModelIcon model={id} size={32} />
|
|
42
|
+
<Flexbox>
|
|
43
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
44
|
+
{displayName}
|
|
45
|
+
<ModelInfoTags directionReverse placement={'top'} {...model!} />
|
|
46
|
+
</Flexbox>
|
|
47
|
+
<Typography.Text style={{ fontSize: 12 }} type={'secondary'}>
|
|
48
|
+
{id}
|
|
49
|
+
</Typography.Text>
|
|
33
50
|
</Flexbox>
|
|
34
|
-
<Typography.Text style={{ fontSize: 12 }} type={'secondary'}>
|
|
35
|
-
{id}
|
|
36
|
-
</Typography.Text>
|
|
37
51
|
</Flexbox>
|
|
52
|
+
{removed && (
|
|
53
|
+
<Tooltip
|
|
54
|
+
overlayStyle={{ maxWidth: 300 }}
|
|
55
|
+
placement={'top'}
|
|
56
|
+
style={{ pointerEvents: 'none' }}
|
|
57
|
+
title={t('ModelSelect.removed')}
|
|
58
|
+
>
|
|
59
|
+
<ActionIcon icon={Recycle} style={{ color: theme.colorWarning }} />
|
|
60
|
+
</Tooltip>
|
|
61
|
+
)}
|
|
38
62
|
</Flexbox>
|
|
39
63
|
);
|
|
40
64
|
});
|
|
@@ -51,10 +51,9 @@ const ProviderModelListSelect = memo<CustomModelSelectProps>(
|
|
|
51
51
|
({ showModelFetcher = false, provider, showAzureDeployName, notFoundContent, placeholder }) => {
|
|
52
52
|
const { t } = useTranslation('common');
|
|
53
53
|
const { t: transSetting } = useTranslation('setting');
|
|
54
|
-
const [setModelProviderConfig,
|
|
54
|
+
const [setModelProviderConfig, updateEnabledModels] = useUserStore((s) => [
|
|
55
55
|
s.setModelProviderConfig,
|
|
56
|
-
s.
|
|
57
|
-
s.useFetchProviderModelList,
|
|
56
|
+
s.updateEnabledModels,
|
|
58
57
|
]);
|
|
59
58
|
|
|
60
59
|
const chatModelCards = useUserStore(
|
|
@@ -94,21 +93,7 @@ const ProviderModelListSelect = memo<CustomModelSelectProps>(
|
|
|
94
93
|
mode="tags"
|
|
95
94
|
notFoundContent={notFoundContent}
|
|
96
95
|
onChange={(value, options) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// if there is a new model, add it to `customModelCards`
|
|
100
|
-
options.forEach((option: { label?: string; value?: string }, index: number) => {
|
|
101
|
-
// if is a known model, it should have value
|
|
102
|
-
// if is an unknown model, the option will be {}
|
|
103
|
-
if (option.value) return;
|
|
104
|
-
|
|
105
|
-
const modelId = value[index];
|
|
106
|
-
|
|
107
|
-
dispatchCustomModelCards(provider, {
|
|
108
|
-
modelCard: { id: modelId },
|
|
109
|
-
type: 'add',
|
|
110
|
-
});
|
|
111
|
-
});
|
|
96
|
+
updateEnabledModels(provider, value, options as any[]);
|
|
112
97
|
}}
|
|
113
98
|
optionFilterProp="label"
|
|
114
99
|
optionRender={({ label, value }) => {
|
|
@@ -123,6 +108,18 @@ const ProviderModelListSelect = memo<CustomModelSelectProps>(
|
|
|
123
108
|
/>
|
|
124
109
|
);
|
|
125
110
|
|
|
111
|
+
if (enabledModels?.some((m) => value === m)) {
|
|
112
|
+
return (
|
|
113
|
+
<OptionRender
|
|
114
|
+
displayName={label as string}
|
|
115
|
+
id={value as string}
|
|
116
|
+
isAzure={showAzureDeployName}
|
|
117
|
+
provider={provider}
|
|
118
|
+
removed
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
126
123
|
// model is defined by user in client
|
|
127
124
|
return (
|
|
128
125
|
<Flexbox align={'center'} gap={8} horizontal>
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
DeepSeek,
|
|
6
6
|
Google,
|
|
7
7
|
Groq,
|
|
8
|
+
LobeHub,
|
|
8
9
|
Minimax,
|
|
9
10
|
Mistral,
|
|
10
11
|
Moonshot,
|
|
@@ -16,7 +17,6 @@ import {
|
|
|
16
17
|
ZeroOne,
|
|
17
18
|
Zhipu,
|
|
18
19
|
} from '@lobehub/icons';
|
|
19
|
-
import { Logo } from '@lobehub/ui';
|
|
20
20
|
import { memo } from 'react';
|
|
21
21
|
import { Center } from 'react-layout-kit';
|
|
22
22
|
|
|
@@ -29,7 +29,7 @@ interface ModelProviderIconProps {
|
|
|
29
29
|
const ModelProviderIcon = memo<ModelProviderIconProps>(({ provider }) => {
|
|
30
30
|
switch (provider) {
|
|
31
31
|
case 'lobehub': {
|
|
32
|
-
return <
|
|
32
|
+
return <LobeHub size={20} />;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
case ModelProvider.ZhiPu: {
|
|
@@ -79,10 +79,10 @@ export const ModelInfoTags = memo<ModelInfoTagsProps>(
|
|
|
79
79
|
return (
|
|
80
80
|
<Flexbox direction={directionReverse ? 'horizontal-reverse' : 'horizontal'} gap={4}>
|
|
81
81
|
{model.files && (
|
|
82
|
-
<Tooltip
|
|
82
|
+
<Tooltip
|
|
83
83
|
overlayStyle={{ pointerEvents: 'none' }}
|
|
84
|
-
placement={placement}
|
|
85
|
-
title={t('ModelSelect.featureTag.file')}
|
|
84
|
+
placement={placement}
|
|
85
|
+
title={t('ModelSelect.featureTag.file')}
|
|
86
86
|
>
|
|
87
87
|
<div className={cx(styles.tag, styles.tagGreen)} style={{ cursor: 'pointer' }} title="">
|
|
88
88
|
<Icon icon={LucidePaperclip} />
|
|
@@ -90,9 +90,9 @@ export const ModelInfoTags = memo<ModelInfoTagsProps>(
|
|
|
90
90
|
</Tooltip>
|
|
91
91
|
)}
|
|
92
92
|
{model.vision && (
|
|
93
|
-
<Tooltip
|
|
93
|
+
<Tooltip
|
|
94
94
|
overlayStyle={{ pointerEvents: 'none' }}
|
|
95
|
-
placement={placement}
|
|
95
|
+
placement={placement}
|
|
96
96
|
title={t('ModelSelect.featureTag.vision')}
|
|
97
97
|
>
|
|
98
98
|
<div className={cx(styles.tag, styles.tagGreen)} style={{ cursor: 'pointer' }} title="">
|
|
@@ -128,15 +128,6 @@ export const ModelInfoTags = memo<ModelInfoTagsProps>(
|
|
|
128
128
|
</Center>
|
|
129
129
|
</Tooltip>
|
|
130
130
|
)}
|
|
131
|
-
{/*{model.isCustom && (*/}
|
|
132
|
-
{/* <Tooltip*/}
|
|
133
|
-
{/* overlayStyle={{ maxWidth: 300 }}*/}
|
|
134
|
-
{/* placement={placement}*/}
|
|
135
|
-
{/* title={t('ModelSelect.featureTag.custom')}*/}
|
|
136
|
-
{/* >*/}
|
|
137
|
-
{/* <Center className={styles.custom}>DIY</Center>*/}
|
|
138
|
-
{/* </Tooltip>*/}
|
|
139
|
-
{/*)}*/}
|
|
140
131
|
</Flexbox>
|
|
141
132
|
);
|
|
142
133
|
},
|
package/src/hooks/useSyncData.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
|
|
3
3
|
import { useChatStore } from '@/store/chat';
|
|
4
|
+
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
4
5
|
import { useSessionStore } from '@/store/session';
|
|
5
6
|
import { useUserStore } from '@/store/user';
|
|
6
7
|
import { syncSettingsSelectors } from '@/store/user/selectors';
|
|
@@ -42,7 +43,8 @@ export const useEnabledDataSync = () => {
|
|
|
42
43
|
s.useEnabledSync,
|
|
43
44
|
]);
|
|
44
45
|
|
|
46
|
+
const { enableWebrtc } = useServerConfigStore(featureFlagsSelectors);
|
|
45
47
|
const syncEvent = useSyncEvent();
|
|
46
48
|
|
|
47
|
-
useEnabledSync(userEnableSync, userId
|
|
49
|
+
useEnabledSync(enableWebrtc, { onEvent: syncEvent, userEnableSync, userId });
|
|
48
50
|
};
|
|
@@ -10,32 +10,40 @@ import { useIsMobile } from '@/hooks/useIsMobile';
|
|
|
10
10
|
import { useEnabledDataSync } from '@/hooks/useSyncData';
|
|
11
11
|
import { useAgentStore } from '@/store/agent';
|
|
12
12
|
import { useGlobalStore } from '@/store/global';
|
|
13
|
+
import { useServerConfigStore } from '@/store/serverConfig';
|
|
13
14
|
import { useUserStore } from '@/store/user';
|
|
15
|
+
import { authSelectors } from '@/store/user/selectors';
|
|
14
16
|
|
|
15
17
|
const StoreInitialization = memo(() => {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
s.
|
|
18
|
+
const router = useRouter();
|
|
19
|
+
|
|
20
|
+
const [useInitUserState, isLogin] = useUserStore((s) => [
|
|
21
|
+
s.useInitUserState,
|
|
22
|
+
authSelectors.isLogin(s),
|
|
20
23
|
]);
|
|
24
|
+
|
|
25
|
+
const { serverConfig } = useServerConfigStore();
|
|
26
|
+
|
|
21
27
|
const useInitGlobalPreference = useGlobalStore((s) => s.useInitGlobalPreference);
|
|
22
28
|
|
|
23
29
|
const useFetchDefaultAgentConfig = useAgentStore((s) => s.useFetchDefaultAgentConfig);
|
|
24
30
|
// init the system preference
|
|
25
|
-
useInitPreference();
|
|
26
31
|
useInitGlobalPreference();
|
|
27
|
-
|
|
28
32
|
useFetchDefaultAgentConfig();
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
useInitUserState(isLogin, serverConfig, {
|
|
35
|
+
onSuccess: (state) => {
|
|
36
|
+
if (state.isOnboard === false) {
|
|
37
|
+
router.push('/onboard');
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
});
|
|
32
41
|
|
|
33
42
|
useEnabledDataSync();
|
|
34
43
|
|
|
35
44
|
const useStoreUpdater = createStoreUpdater(useGlobalStore);
|
|
36
45
|
|
|
37
46
|
const mobile = useIsMobile();
|
|
38
|
-
const router = useRouter();
|
|
39
47
|
|
|
40
48
|
useStoreUpdater('isMobile', mobile);
|
|
41
49
|
useStoreUpdater('router', router);
|
|
@@ -58,13 +58,13 @@ const GlobalLayout = async ({ children }: GlobalLayoutProps) => {
|
|
|
58
58
|
defaultNeutralColor={neutralColor?.value as any}
|
|
59
59
|
defaultPrimaryColor={primaryColor?.value as any}
|
|
60
60
|
>
|
|
61
|
-
<StoreInitialization />
|
|
62
61
|
<ServerConfigStoreProvider
|
|
63
62
|
featureFlags={serverFeatureFlags}
|
|
64
63
|
isMobile={isMobile}
|
|
65
64
|
serverConfig={serverConfig}
|
|
66
65
|
>
|
|
67
66
|
{children}
|
|
67
|
+
<StoreInitialization />
|
|
68
68
|
</ServerConfigStoreProvider>
|
|
69
69
|
<DebugUI />
|
|
70
70
|
</AppTheme>
|
|
@@ -343,28 +343,4 @@ describe('MessageClientService', () => {
|
|
|
343
343
|
expect(result).toBe(false);
|
|
344
344
|
});
|
|
345
345
|
});
|
|
346
|
-
|
|
347
|
-
describe('messageCountToCheckTrace', () => {
|
|
348
|
-
it('should return true if message count is greater than or equal to 4', async () => {
|
|
349
|
-
// Setup
|
|
350
|
-
(MessageModel.count as Mock).mockResolvedValue(5);
|
|
351
|
-
|
|
352
|
-
// Execute
|
|
353
|
-
const result = await messageService.messageCountToCheckTrace();
|
|
354
|
-
|
|
355
|
-
// Assert
|
|
356
|
-
expect(result).toBe(true);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it('should return false if message count is less than 4', async () => {
|
|
360
|
-
// Setup
|
|
361
|
-
(MessageModel.count as Mock).mockResolvedValue(3);
|
|
362
|
-
|
|
363
|
-
// Execute
|
|
364
|
-
const result = await messageService.messageCountToCheckTrace();
|
|
365
|
-
|
|
366
|
-
// Assert
|
|
367
|
-
expect(result).toBe(false);
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
346
|
});
|