@lobehub/chat 0.126.5 → 0.127.1

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.
Files changed (118) hide show
  1. package/.env.example +8 -0
  2. package/CHANGELOG.md +50 -0
  3. package/Dockerfile +3 -0
  4. package/docs/Deployment/Environment-Variable.md +10 -0
  5. package/docs/Deployment/Environment-Variable.zh-CN.md +10 -0
  6. package/locales/ar/common.json +1 -0
  7. package/locales/ar/error.json +2 -0
  8. package/locales/ar/setting.json +16 -0
  9. package/locales/de-DE/common.json +1 -0
  10. package/locales/de-DE/error.json +2 -0
  11. package/locales/de-DE/setting.json +16 -0
  12. package/locales/en-US/common.json +1 -0
  13. package/locales/en-US/error.json +2 -0
  14. package/locales/en-US/setting.json +16 -0
  15. package/locales/es-ES/common.json +1 -0
  16. package/locales/es-ES/error.json +2 -0
  17. package/locales/es-ES/setting.json +16 -0
  18. package/locales/fr-FR/common.json +1 -0
  19. package/locales/fr-FR/error.json +2 -0
  20. package/locales/fr-FR/setting.json +16 -0
  21. package/locales/it-IT/common.json +1 -0
  22. package/locales/it-IT/error.json +2 -0
  23. package/locales/it-IT/setting.json +16 -0
  24. package/locales/ja-JP/common.json +1 -0
  25. package/locales/ja-JP/error.json +2 -0
  26. package/locales/ja-JP/setting.json +16 -0
  27. package/locales/ko-KR/common.json +1 -0
  28. package/locales/ko-KR/error.json +2 -0
  29. package/locales/ko-KR/setting.json +16 -0
  30. package/locales/nl-NL/common.json +1 -0
  31. package/locales/nl-NL/error.json +2 -0
  32. package/locales/nl-NL/setting.json +16 -0
  33. package/locales/pl-PL/common.json +1 -0
  34. package/locales/pl-PL/error.json +2 -0
  35. package/locales/pl-PL/setting.json +16 -0
  36. package/locales/pt-BR/common.json +1 -0
  37. package/locales/pt-BR/error.json +2 -0
  38. package/locales/pt-BR/setting.json +16 -0
  39. package/locales/ru-RU/common.json +1 -0
  40. package/locales/ru-RU/error.json +2 -0
  41. package/locales/ru-RU/setting.json +16 -0
  42. package/locales/tr-TR/common.json +1 -0
  43. package/locales/tr-TR/error.json +2 -0
  44. package/locales/tr-TR/setting.json +16 -0
  45. package/locales/vi-VN/common.json +1 -0
  46. package/locales/vi-VN/error.json +2 -0
  47. package/locales/vi-VN/setting.json +16 -0
  48. package/locales/zh-CN/common.json +1 -0
  49. package/locales/zh-CN/error.json +2 -0
  50. package/locales/zh-CN/setting.json +16 -0
  51. package/locales/zh-TW/common.json +1 -0
  52. package/locales/zh-TW/error.json +2 -0
  53. package/locales/zh-TW/setting.json +16 -0
  54. package/package.json +1 -1
  55. package/src/app/api/chat/[provider]/agentRuntime.ts +14 -0
  56. package/src/app/api/config/route.ts +2 -0
  57. package/src/app/api/errorResponse.ts +3 -0
  58. package/src/app/chat/features/ChatHeader/SettingButton.tsx +1 -2
  59. package/src/app/settings/(desktop)/features/Header.tsx +3 -4
  60. package/src/app/settings/(desktop)/features/SideBar.tsx +42 -0
  61. package/src/app/settings/(desktop)/index.tsx +4 -3
  62. package/src/app/settings/(desktop)/layout.desktop.tsx +14 -6
  63. package/src/app/settings/(desktop)/layout.responsive.tsx +4 -4
  64. package/src/app/settings/(mobile)/features/ExtraList.tsx +7 -5
  65. package/src/app/settings/(mobile)/features/Header/index.tsx +8 -5
  66. package/src/app/settings/(mobile)/index.tsx +1 -3
  67. package/src/app/settings/(mobile)/layout.mobile.tsx +8 -4
  68. package/src/app/settings/(mobile)/mobile/index.tsx +3 -5
  69. package/src/app/settings/agent/Agent.tsx +0 -4
  70. package/src/app/settings/agent/layout.tsx +9 -1
  71. package/src/app/settings/agent/page.tsx +17 -2
  72. package/src/app/settings/common/index.tsx +0 -3
  73. package/src/app/settings/common/layout.tsx +9 -1
  74. package/src/app/settings/features/SettingList/Item.tsx +50 -0
  75. package/src/app/settings/features/{SideBar/List.tsx → SettingList/index.tsx} +14 -15
  76. package/src/app/settings/layout.server.tsx +10 -3
  77. package/src/app/settings/llm/Azure/index.tsx +78 -106
  78. package/src/app/settings/llm/Bedrock/index.tsx +60 -89
  79. package/src/app/settings/llm/Google/index.tsx +26 -55
  80. package/src/app/settings/llm/Moonshot/index.tsx +29 -54
  81. package/src/app/settings/llm/Ollama/index.tsx +55 -0
  82. package/src/app/settings/llm/OpenAI/index.tsx +91 -107
  83. package/src/app/settings/llm/Zhipu/index.tsx +29 -54
  84. package/src/app/settings/llm/components/ProviderConfig/index.tsx +58 -0
  85. package/src/app/settings/llm/index.tsx +42 -0
  86. package/src/app/settings/llm/layout.tsx +9 -1
  87. package/src/app/settings/llm/page.tsx +6 -39
  88. package/src/app/settings/tts/layout.tsx +9 -1
  89. package/src/app/settings/tts/page.tsx +17 -2
  90. package/src/components/ModelProviderIcon/index.tsx +5 -1
  91. package/src/config/modelProviders/index.ts +3 -0
  92. package/src/config/modelProviders/ollama.ts +117 -0
  93. package/src/config/server/provider.ts +6 -0
  94. package/src/const/settings.ts +5 -0
  95. package/src/features/SideBar/BottomActions.tsx +1 -2
  96. package/src/layout/ResponsiveLayout.client.tsx +7 -7
  97. package/src/layout/ResponsiveLayout.server.tsx +6 -6
  98. package/src/libs/agent-runtime/error.ts +3 -0
  99. package/src/libs/agent-runtime/index.ts +1 -0
  100. package/src/libs/agent-runtime/ollama/index.ts +80 -0
  101. package/src/libs/agent-runtime/types/type.ts +1 -0
  102. package/src/locales/default/common.ts +1 -0
  103. package/src/locales/default/error.ts +3 -0
  104. package/src/locales/default/setting.ts +16 -0
  105. package/src/services/_auth.test.ts +132 -0
  106. package/src/services/_auth.ts +9 -1
  107. package/src/store/global/slices/common/initialState.ts +0 -2
  108. package/src/store/global/slices/settings/action.test.ts +0 -13
  109. package/src/store/global/slices/settings/action.ts +0 -5
  110. package/src/store/global/slices/settings/selectors/modelProvider.ts +31 -2
  111. package/src/types/settings/modelProvider.ts +8 -0
  112. package/src/app/settings/agent/index.tsx +0 -21
  113. package/src/app/settings/features/SideBar/Item.tsx +0 -44
  114. package/src/app/settings/features/SideBar/index.tsx +0 -42
  115. package/src/app/settings/tts/index.tsx +0 -21
  116. package/src/store/global/hooks/useSwitchSettingsOnInit.ts +0 -12
  117. /package/src/app/settings/llm/{Checker.tsx → components/Checker.tsx} +0 -0
  118. /package/src/app/settings/llm/{useSyncSettings.ts → components/ProviderConfig/useSyncSettings.ts} +0 -0
@@ -1,73 +1,44 @@
1
1
  import { Google } from '@lobehub/icons';
2
- import { Form, type ItemGroup } from '@lobehub/ui';
3
- import { Form as AntForm, Input, Switch } from 'antd';
4
- import { debounce } from 'lodash-es';
2
+ import { Input } from 'antd';
5
3
  import { memo } from 'react';
6
4
  import { useTranslation } from 'react-i18next';
7
- import { Flexbox } from 'react-layout-kit';
8
5
 
9
- import { FORM_STYLE } from '@/const/layoutTokens';
10
6
  import { ModelProvider } from '@/libs/agent-runtime';
11
- import { useGlobalStore } from '@/store/global';
12
- import { modelProviderSelectors } from '@/store/global/selectors';
13
7
  import { GlobalLLMProviderKey } from '@/types/settings';
14
8
 
15
- import Checker from '../Checker';
9
+ import Checker from '../components/Checker';
10
+ import ProviderConfig from '../components/ProviderConfig';
16
11
  import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
17
- import { useSyncSettings } from '../useSyncSettings';
18
12
 
19
13
  const providerKey: GlobalLLMProviderKey = 'google';
20
14
 
21
15
  const GoogleProvider = memo(() => {
22
16
  const { t } = useTranslation('setting');
23
- const [form] = AntForm.useForm();
24
- useSyncSettings(form);
25
-
26
- const [toggleProviderEnabled, setSettings] = useGlobalStore((s) => [
27
- s.toggleProviderEnabled,
28
- s.setSettings,
29
- ]);
30
-
31
- const enabled = useGlobalStore(modelProviderSelectors.enableGoogle);
32
-
33
- const model: ItemGroup = {
34
- children: [
35
- {
36
- children: (
37
- <Input.Password
38
- autoComplete={'new-password'}
39
- placeholder={t('llm.Google.token.placeholder')}
40
- />
41
- ),
42
- desc: t('llm.Google.token.desc'),
43
- label: t('llm.Google.token.title'),
44
- name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
45
- },
46
- {
47
- children: <Checker model={'gemini-pro'} provider={ModelProvider.Google} />,
48
- desc: t('llm.checker.desc'),
49
- label: t('llm.checker.title'),
50
- minWidth: '100%',
51
- },
52
- ],
53
- defaultActive: enabled,
54
- extra: (
55
- <Switch
56
- onChange={(enabled) => {
57
- toggleProviderEnabled(providerKey, enabled);
58
- }}
59
- value={enabled}
60
- />
61
- ),
62
- title: (
63
- <Flexbox align={'center'} gap={8} horizontal>
64
- <Google.BrandColor size={28} />
65
- </Flexbox>
66
- ),
67
- };
68
17
 
69
18
  return (
70
- <Form form={form} items={[model]} onValuesChange={debounce(setSettings, 100)} {...FORM_STYLE} />
19
+ <ProviderConfig
20
+ configItems={[
21
+ {
22
+ children: (
23
+ <Input.Password
24
+ autoComplete={'new-password'}
25
+ placeholder={t('llm.Google.token.placeholder')}
26
+ />
27
+ ),
28
+ desc: t('llm.Google.token.desc'),
29
+ label: t('llm.Google.token.title'),
30
+ name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
31
+ },
32
+ {
33
+ children: <Checker model={'gemini-pro'} provider={ModelProvider.Google} />,
34
+ desc: t('llm.checker.desc'),
35
+ label: t('llm.checker.title'),
36
+ minWidth: '100%',
37
+ },
38
+ ]}
39
+ provider={providerKey}
40
+ title={<Google.BrandColor size={28} />}
41
+ />
71
42
  );
72
43
  });
73
44
 
@@ -1,76 +1,51 @@
1
1
  import { Moonshot } from '@lobehub/icons';
2
- import { Form, type ItemGroup } from '@lobehub/ui';
3
- import { Form as AntForm, Input, Switch } from 'antd';
2
+ import { Input } from 'antd';
4
3
  import { useTheme } from 'antd-style';
5
- import { debounce } from 'lodash-es';
6
4
  import { memo } from 'react';
7
5
  import { useTranslation } from 'react-i18next';
8
- import { Flexbox } from 'react-layout-kit';
9
6
 
10
- import { FORM_STYLE } from '@/const/layoutTokens';
11
7
  import { ModelProvider } from '@/libs/agent-runtime';
12
- import { useGlobalStore } from '@/store/global';
13
- import { modelProviderSelectors } from '@/store/global/selectors';
14
8
 
15
- import Checker from '../Checker';
9
+ import Checker from '../components/Checker';
10
+ import ProviderConfig from '../components/ProviderConfig';
16
11
  import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
17
- import { useSyncSettings } from '../useSyncSettings';
18
12
 
19
13
  const providerKey = 'moonshot';
20
14
 
21
15
  const MoonshotProvider = memo(() => {
22
16
  const { t } = useTranslation('setting');
23
- const [form] = AntForm.useForm();
24
- const theme = useTheme();
25
- const [toggleProviderEnabled, setSettings] = useGlobalStore((s) => [
26
- s.toggleProviderEnabled,
27
- s.setSettings,
28
- ]);
29
- const enabled = useGlobalStore(modelProviderSelectors.enableMoonshot);
30
17
 
31
- useSyncSettings(form);
18
+ const theme = useTheme();
32
19
 
33
- const model: ItemGroup = {
34
- children: [
35
- {
36
- children: (
37
- <Input.Password
38
- autoComplete={'new-password'}
39
- placeholder={t('llm.Moonshot.token.placeholder')}
40
- />
41
- ),
42
- desc: t('llm.Moonshot.token.desc'),
43
- label: t('llm.Moonshot.token.title'),
44
- name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
45
- },
46
- {
47
- children: <Checker model={'moonshot-v1-8k'} provider={ModelProvider.Moonshot} />,
48
- desc: t('llm.checker.desc'),
49
- label: t('llm.checker.title'),
50
- minWidth: '100%',
51
- },
52
- ],
53
- defaultActive: enabled,
54
- extra: (
55
- <Switch
56
- onChange={(enabled) => {
57
- toggleProviderEnabled(providerKey, enabled);
58
- }}
59
- value={enabled}
60
- />
61
- ),
62
- title: (
63
- <Flexbox align={'center'} gap={8} horizontal>
20
+ return (
21
+ <ProviderConfig
22
+ configItems={[
23
+ {
24
+ children: (
25
+ <Input.Password
26
+ autoComplete={'new-password'}
27
+ placeholder={t('llm.Moonshot.token.placeholder')}
28
+ />
29
+ ),
30
+ desc: t('llm.Moonshot.token.desc'),
31
+ label: t('llm.Moonshot.token.title'),
32
+ name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
33
+ },
34
+ {
35
+ children: <Checker model={'moonshot-v1-8k'} provider={ModelProvider.Moonshot} />,
36
+ desc: t('llm.checker.desc'),
37
+ label: t('llm.checker.title'),
38
+ minWidth: '100%',
39
+ },
40
+ ]}
41
+ provider={providerKey}
42
+ title={
64
43
  <Moonshot.Combine
65
44
  color={theme.isDarkMode ? theme.colorText : Moonshot.colorPrimary}
66
45
  size={24}
67
46
  />
68
- </Flexbox>
69
- ),
70
- };
71
-
72
- return (
73
- <Form form={form} items={[model]} onValuesChange={debounce(setSettings, 100)} {...FORM_STYLE} />
47
+ }
48
+ />
74
49
  );
75
50
  });
76
51
 
@@ -0,0 +1,55 @@
1
+ import { Ollama } from '@lobehub/icons';
2
+ import { Input } from 'antd';
3
+ import { useTheme } from 'antd-style';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { ModelProvider } from '@/libs/agent-runtime';
8
+
9
+ import Checker from '../components/Checker';
10
+ import ProviderConfig from '../components/ProviderConfig';
11
+ import { LLMProviderBaseUrlKey, LLMProviderConfigKey } from '../const';
12
+
13
+ const providerKey = 'ollama';
14
+
15
+ const OllamaProvider = memo(() => {
16
+ const { t } = useTranslation('setting');
17
+ const theme = useTheme();
18
+
19
+ return (
20
+ <ProviderConfig
21
+ configItems={[
22
+ {
23
+ children: <Input allowClear placeholder={t('llm.Ollama.endpoint.placeholder')} />,
24
+ desc: t('llm.Ollama.endpoint.desc'),
25
+ label: t('llm.Ollama.endpoint.title'),
26
+ name: [LLMProviderConfigKey, providerKey, LLMProviderBaseUrlKey],
27
+ },
28
+ {
29
+ children: (
30
+ <Input.TextArea
31
+ allowClear
32
+ placeholder={t('llm.Ollama.customModelName.placeholder')}
33
+ style={{ height: 100 }}
34
+ />
35
+ ),
36
+ desc: t('llm.Ollama.customModelName.desc'),
37
+ label: t('llm.Ollama.customModelName.title'),
38
+ name: [LLMProviderConfigKey, providerKey, 'customModelName'],
39
+ },
40
+ {
41
+ children: <Checker model={'llama2'} provider={ModelProvider.Ollama} />,
42
+ desc: t('llm.Ollama.checker.desc'),
43
+ label: t('llm.checker.title'),
44
+ minWidth: undefined,
45
+ },
46
+ ]}
47
+ provider={providerKey}
48
+ title={
49
+ <Ollama.Combine color={theme.isDarkMode ? theme.colorText : theme.colorPrimary} size={24} />
50
+ }
51
+ />
52
+ );
53
+ });
54
+
55
+ export default OllamaProvider;
@@ -1,20 +1,17 @@
1
1
  import { OpenAI } from '@lobehub/icons';
2
- import { Form, type ItemGroup, Markdown } from '@lobehub/ui';
3
- import { Form as AntForm, AutoComplete, Input, Switch } from 'antd';
2
+ import { Markdown } from '@lobehub/ui';
3
+ import { AutoComplete, Input, Switch } from 'antd';
4
4
  import { createStyles } from 'antd-style';
5
- import { debounce } from 'lodash-es';
6
5
  import { memo } from 'react';
7
6
  import { useTranslation } from 'react-i18next';
8
- import { Flexbox } from 'react-layout-kit';
9
7
 
10
- import { FORM_STYLE } from '@/const/layoutTokens';
11
8
  import { ModelProvider } from '@/libs/agent-runtime';
12
9
  import { useGlobalStore } from '@/store/global';
13
10
  import { modelProviderSelectors } from '@/store/global/selectors';
14
11
 
15
- import Checker from '../Checker';
12
+ import Checker from '../components/Checker';
13
+ import ProviderConfig from '../components/ProviderConfig';
16
14
  import { LLMProviderConfigKey } from '../const';
17
- import { useSyncSettings } from '../useSyncSettings';
18
15
 
19
16
  const useStyles = createStyles(({ css, token }) => ({
20
17
  markdown: css`
@@ -37,109 +34,96 @@ const providerKey = 'openAI';
37
34
  const LLM = memo(() => {
38
35
  const { t } = useTranslation('setting');
39
36
  const { styles } = useStyles();
40
- const [form] = AntForm.useForm();
41
37
 
42
- const [useAzure, setSettings] = useGlobalStore((s) => [
43
- modelProviderSelectors.enableAzure(s),
44
- s.setSettings,
45
- ]);
46
-
47
- useSyncSettings(form);
48
-
49
- const openAI: ItemGroup = {
50
- children: [
51
- {
52
- children: (
53
- <Input.Password
54
- autoComplete={'new-password'}
55
- placeholder={
56
- useAzure ? t('llm.AzureOpenAI.token.placeholder') : t('llm.OpenAI.token.placeholder')
57
- }
58
- />
59
- ),
60
- desc: useAzure ? t('llm.AzureOpenAI.token.desc') : t('llm.OpenAI.token.desc'),
61
- label: useAzure ? t('llm.AzureOpenAI.token.title') : t('llm.OpenAI.token.title'),
62
- name: [LLMProviderConfigKey, providerKey, 'OPENAI_API_KEY'],
63
- },
64
- {
65
- children: (
66
- <Input
67
- allowClear
68
- placeholder={
69
- useAzure
70
- ? t('llm.AzureOpenAI.endpoint.placeholder')
71
- : t('llm.OpenAI.endpoint.placeholder')
72
- }
73
- />
74
- ),
75
- desc: useAzure ? t('llm.AzureOpenAI.endpoint.desc') : t('llm.OpenAI.endpoint.desc'),
76
- label: useAzure ? t('llm.AzureOpenAI.endpoint.title') : t('llm.OpenAI.endpoint.title'),
77
- name: [LLMProviderConfigKey, providerKey, 'endpoint'],
78
- },
79
- {
80
- children: (
81
- <Input.TextArea
82
- allowClear
83
- placeholder={t('llm.OpenAI.customModelName.placeholder')}
84
- style={{ height: 100 }}
85
- />
86
- ),
87
- desc: t('llm.OpenAI.customModelName.desc'),
88
- label: t('llm.OpenAI.customModelName.title'),
89
- name: [LLMProviderConfigKey, providerKey, 'customModelName'],
90
- },
91
- {
92
- children: <Switch />,
93
- desc: t('llm.OpenAI.useAzure.desc'),
94
- label: t('llm.OpenAI.useAzure.title'),
95
- minWidth: undefined,
96
- name: [LLMProviderConfigKey, 'openAI', 'useAzure'],
97
- valuePropName: 'checked',
98
- },
99
- {
100
- children: (
101
- <AutoComplete
102
- options={[
103
- '2023-12-01-preview',
104
- '2023-08-01-preview',
105
- '2023-07-01-preview',
106
- '2023-06-01-preview',
107
- '2023-05-15',
108
- '2023-03-15-preview',
109
- ].map((i) => ({
110
- label: i,
111
- value: i,
112
- }))}
113
- placeholder={'20XX-XX-XX'}
114
- />
115
- ),
116
- desc: (
117
- <Markdown className={styles.markdown}>{t('llm.OpenAI.azureApiVersion.desc')}</Markdown>
118
- ),
119
- hidden: !useAzure,
120
- label: t('llm.OpenAI.azureApiVersion.title'),
121
- name: [LLMProviderConfigKey, providerKey, 'azureApiVersion'],
122
- },
123
- {
124
- children: <Checker model={'gpt-3.5-turbo'} provider={ModelProvider.OpenAI} />,
125
- desc: t('llm.checker.desc'),
126
- label: t('llm.checker.title'),
127
- minWidth: '100%',
128
- },
129
- ],
130
- title: (
131
- <Flexbox align={'center'} gap={8} horizontal>
132
- <OpenAI.Combine size={24}></OpenAI.Combine>
133
- </Flexbox>
134
- ),
135
- };
38
+ const [useAzure] = useGlobalStore((s) => [modelProviderSelectors.enableAzure(s)]);
136
39
 
137
40
  return (
138
- <Form
139
- form={form}
140
- items={[openAI]}
141
- onValuesChange={debounce(setSettings, 100)}
142
- {...FORM_STYLE}
41
+ <ProviderConfig
42
+ canDeactivate={false}
43
+ configItems={[
44
+ {
45
+ children: (
46
+ <Input.Password
47
+ autoComplete={'new-password'}
48
+ placeholder={
49
+ useAzure
50
+ ? t('llm.AzureOpenAI.token.placeholder')
51
+ : t('llm.OpenAI.token.placeholder')
52
+ }
53
+ />
54
+ ),
55
+ desc: useAzure ? t('llm.AzureOpenAI.token.desc') : t('llm.OpenAI.token.desc'),
56
+ label: useAzure ? t('llm.AzureOpenAI.token.title') : t('llm.OpenAI.token.title'),
57
+ name: [LLMProviderConfigKey, providerKey, 'OPENAI_API_KEY'],
58
+ },
59
+ {
60
+ children: (
61
+ <Input
62
+ allowClear
63
+ placeholder={
64
+ useAzure
65
+ ? t('llm.AzureOpenAI.endpoint.placeholder')
66
+ : t('llm.OpenAI.endpoint.placeholder')
67
+ }
68
+ />
69
+ ),
70
+ desc: useAzure ? t('llm.AzureOpenAI.endpoint.desc') : t('llm.OpenAI.endpoint.desc'),
71
+ label: useAzure ? t('llm.AzureOpenAI.endpoint.title') : t('llm.OpenAI.endpoint.title'),
72
+ name: [LLMProviderConfigKey, providerKey, 'endpoint'],
73
+ },
74
+ {
75
+ children: (
76
+ <Input.TextArea
77
+ allowClear
78
+ placeholder={t('llm.OpenAI.customModelName.placeholder')}
79
+ style={{ height: 100 }}
80
+ />
81
+ ),
82
+ desc: t('llm.OpenAI.customModelName.desc'),
83
+ label: t('llm.OpenAI.customModelName.title'),
84
+ name: [LLMProviderConfigKey, providerKey, 'customModelName'],
85
+ },
86
+ {
87
+ children: <Switch />,
88
+ desc: t('llm.OpenAI.useAzure.desc'),
89
+ label: t('llm.OpenAI.useAzure.title'),
90
+ minWidth: undefined,
91
+ name: [LLMProviderConfigKey, 'openAI', 'useAzure'],
92
+ valuePropName: 'checked',
93
+ },
94
+ {
95
+ children: (
96
+ <AutoComplete
97
+ options={[
98
+ '2023-12-01-preview',
99
+ '2023-08-01-preview',
100
+ '2023-07-01-preview',
101
+ '2023-06-01-preview',
102
+ '2023-05-15',
103
+ '2023-03-15-preview',
104
+ ].map((i) => ({
105
+ label: i,
106
+ value: i,
107
+ }))}
108
+ placeholder={'20XX-XX-XX'}
109
+ />
110
+ ),
111
+ desc: (
112
+ <Markdown className={styles.markdown}>{t('llm.OpenAI.azureApiVersion.desc')}</Markdown>
113
+ ),
114
+ hidden: !useAzure,
115
+ label: t('llm.OpenAI.azureApiVersion.title'),
116
+ name: [LLMProviderConfigKey, providerKey, 'azureApiVersion'],
117
+ },
118
+ {
119
+ children: <Checker model={'gpt-3.5-turbo'} provider={ModelProvider.OpenAI} />,
120
+ desc: t('llm.checker.desc'),
121
+ label: t('llm.checker.title'),
122
+ minWidth: '100%',
123
+ },
124
+ ]}
125
+ provider={providerKey}
126
+ title={<OpenAI.Combine size={24}></OpenAI.Combine>}
143
127
  />
144
128
  );
145
129
  });
@@ -1,77 +1,52 @@
1
1
  import { Zhipu } from '@lobehub/icons';
2
- import { Form, type ItemGroup } from '@lobehub/ui';
3
- import { Form as AntForm, Input, Switch } from 'antd';
2
+ import { Input } from 'antd';
4
3
  import { useTheme } from 'antd-style';
5
- import { debounce } from 'lodash-es';
6
4
  import { lighten } from 'polished';
7
5
  import { memo } from 'react';
8
6
  import { useTranslation } from 'react-i18next';
9
- import { Flexbox } from 'react-layout-kit';
10
7
 
11
- import { FORM_STYLE } from '@/const/layoutTokens';
12
8
  import { ModelProvider } from '@/libs/agent-runtime';
13
- import { useGlobalStore } from '@/store/global';
14
- import { modelProviderSelectors } from '@/store/global/selectors';
15
9
 
16
- import Checker from '../Checker';
10
+ import Checker from '../components/Checker';
11
+ import ProviderConfig from '../components/ProviderConfig';
17
12
  import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
18
- import { useSyncSettings } from '../useSyncSettings';
19
13
 
20
14
  const providerKey = 'zhipu';
21
15
 
22
16
  const ZhipuProvider = memo(() => {
23
17
  const { t } = useTranslation('setting');
24
- const [form] = AntForm.useForm();
25
- const theme = useTheme();
26
- const [toggleProviderEnabled, setSettings] = useGlobalStore((s) => [
27
- s.toggleProviderEnabled,
28
- s.setSettings,
29
- ]);
30
- const enabled = useGlobalStore(modelProviderSelectors.enableZhipu);
31
18
 
32
- useSyncSettings(form);
19
+ const theme = useTheme();
33
20
 
34
- const model: ItemGroup = {
35
- children: [
36
- {
37
- children: (
38
- <Input.Password
39
- autoComplete={'new-password'}
40
- placeholder={t('llm.Zhipu.token.placeholder')}
41
- />
42
- ),
43
- desc: t('llm.Zhipu.token.desc'),
44
- label: t('llm.Zhipu.token.title'),
45
- name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
46
- },
47
- {
48
- children: <Checker model={'glm-3-turbo'} provider={ModelProvider.ZhiPu} />,
49
- desc: t('llm.checker.desc'),
50
- label: t('llm.checker.title'),
51
- minWidth: '100%',
52
- },
53
- ],
54
- defaultActive: enabled,
55
- extra: (
56
- <Switch
57
- onChange={(enabled) => {
58
- toggleProviderEnabled(providerKey, enabled);
59
- }}
60
- value={enabled}
61
- />
62
- ),
63
- title: (
64
- <Flexbox align={'center'} gap={8} horizontal>
21
+ return (
22
+ <ProviderConfig
23
+ configItems={[
24
+ {
25
+ children: (
26
+ <Input.Password
27
+ autoComplete={'new-password'}
28
+ placeholder={t('llm.Zhipu.token.placeholder')}
29
+ />
30
+ ),
31
+ desc: t('llm.Zhipu.token.desc'),
32
+ label: t('llm.Zhipu.token.title'),
33
+ name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
34
+ },
35
+ {
36
+ children: <Checker model={'glm-3-turbo'} provider={ModelProvider.ZhiPu} />,
37
+ desc: t('llm.checker.desc'),
38
+ label: t('llm.checker.title'),
39
+ minWidth: '100%',
40
+ },
41
+ ]}
42
+ provider={providerKey}
43
+ title={
65
44
  <Zhipu.Combine
66
45
  color={theme.isDarkMode ? lighten(0.1, Zhipu.colorPrimary) : Zhipu.colorPrimary}
67
46
  size={32}
68
47
  />
69
- </Flexbox>
70
- ),
71
- };
72
-
73
- return (
74
- <Form form={form} items={[model]} onValuesChange={debounce(setSettings, 100)} {...FORM_STYLE} />
48
+ }
49
+ />
75
50
  );
76
51
  });
77
52
 
@@ -0,0 +1,58 @@
1
+ import { Form, type ItemGroup } from '@lobehub/ui';
2
+ import type { FormItemProps } from '@lobehub/ui/es/Form/components/FormItem';
3
+ import { Form as AntForm, Switch } from 'antd';
4
+ import { debounce } from 'lodash-es';
5
+ import { ReactNode, memo } from 'react';
6
+
7
+ import { FORM_STYLE } from '@/const/layoutTokens';
8
+ import { useGlobalStore } from '@/store/global';
9
+ import { modelProviderSelectors } from '@/store/global/selectors';
10
+ import { GlobalLLMProviderKey } from '@/types/settings';
11
+
12
+ import { useSyncSettings } from './useSyncSettings';
13
+
14
+ interface ProviderConfigProps {
15
+ canDeactivate?: boolean;
16
+ configItems: FormItemProps[];
17
+ provider: GlobalLLMProviderKey;
18
+ title: ReactNode;
19
+ }
20
+
21
+ const ProviderConfig = memo<ProviderConfigProps>(
22
+ ({ provider, canDeactivate = true, title, configItems }) => {
23
+ const [form] = AntForm.useForm();
24
+ const [toggleProviderEnabled, setSettings] = useGlobalStore((s) => [
25
+ s.toggleProviderEnabled,
26
+ s.setSettings,
27
+ ]);
28
+
29
+ const enabled = useGlobalStore(modelProviderSelectors.providerEnabled(provider));
30
+
31
+ useSyncSettings(form);
32
+
33
+ const model: ItemGroup = {
34
+ children: configItems,
35
+ defaultActive: canDeactivate ? enabled : undefined,
36
+ extra: canDeactivate ? (
37
+ <Switch
38
+ onChange={(enabled) => {
39
+ toggleProviderEnabled(provider, enabled);
40
+ }}
41
+ value={enabled}
42
+ />
43
+ ) : undefined,
44
+ title,
45
+ };
46
+
47
+ return (
48
+ <Form
49
+ form={form}
50
+ items={[model]}
51
+ onValuesChange={debounce(setSettings, 100)}
52
+ {...FORM_STYLE}
53
+ />
54
+ );
55
+ },
56
+ );
57
+
58
+ export default ProviderConfig;