@lobehub/chat 0.122.8 → 0.123.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.
Files changed (227) hide show
  1. package/.env.example +22 -2
  2. package/.eslintrc.js +1 -0
  3. package/CHANGELOG.md +50 -0
  4. package/README.md +11 -9
  5. package/README.zh-CN.md +11 -9
  6. package/docs/Deployment/Environment-Variable.md +65 -23
  7. package/docs/Deployment/Environment-Variable.zh-CN.md +64 -22
  8. package/locales/ar/chat.json +12 -1
  9. package/locales/ar/common.json +16 -0
  10. package/locales/ar/error.json +35 -6
  11. package/locales/ar/setting.json +53 -6
  12. package/locales/de-DE/chat.json +12 -1
  13. package/locales/de-DE/common.json +16 -0
  14. package/locales/de-DE/error.json +35 -6
  15. package/locales/de-DE/setting.json +53 -6
  16. package/locales/en-US/chat.json +13 -2
  17. package/locales/en-US/common.json +16 -0
  18. package/locales/en-US/error.json +35 -6
  19. package/locales/en-US/setting.json +53 -6
  20. package/locales/es-ES/chat.json +12 -1
  21. package/locales/es-ES/common.json +16 -0
  22. package/locales/es-ES/error.json +35 -6
  23. package/locales/es-ES/setting.json +53 -6
  24. package/locales/fr-FR/chat.json +13 -2
  25. package/locales/fr-FR/common.json +16 -0
  26. package/locales/fr-FR/error.json +35 -6
  27. package/locales/fr-FR/setting.json +53 -6
  28. package/locales/it-IT/chat.json +12 -1
  29. package/locales/it-IT/common.json +16 -0
  30. package/locales/it-IT/error.json +35 -6
  31. package/locales/it-IT/setting.json +53 -6
  32. package/locales/ja-JP/chat.json +12 -1
  33. package/locales/ja-JP/common.json +16 -0
  34. package/locales/ja-JP/error.json +35 -6
  35. package/locales/ja-JP/setting.json +53 -6
  36. package/locales/ko-KR/chat.json +12 -1
  37. package/locales/ko-KR/common.json +16 -0
  38. package/locales/ko-KR/error.json +35 -6
  39. package/locales/ko-KR/setting.json +53 -6
  40. package/locales/nl-NL/chat.json +12 -1
  41. package/locales/nl-NL/common.json +16 -0
  42. package/locales/nl-NL/error.json +35 -6
  43. package/locales/nl-NL/setting.json +53 -6
  44. package/locales/pl-PL/chat.json +12 -1
  45. package/locales/pl-PL/common.json +16 -0
  46. package/locales/pl-PL/error.json +35 -6
  47. package/locales/pl-PL/setting.json +53 -6
  48. package/locales/pt-BR/chat.json +12 -1
  49. package/locales/pt-BR/common.json +16 -0
  50. package/locales/pt-BR/error.json +35 -6
  51. package/locales/pt-BR/setting.json +53 -6
  52. package/locales/ru-RU/chat.json +12 -1
  53. package/locales/ru-RU/common.json +16 -0
  54. package/locales/ru-RU/error.json +35 -6
  55. package/locales/ru-RU/setting.json +53 -6
  56. package/locales/tr-TR/chat.json +12 -1
  57. package/locales/tr-TR/common.json +16 -0
  58. package/locales/tr-TR/error.json +35 -6
  59. package/locales/tr-TR/setting.json +53 -6
  60. package/locales/vi-VN/chat.json +12 -1
  61. package/locales/vi-VN/common.json +16 -0
  62. package/locales/vi-VN/error.json +35 -6
  63. package/locales/vi-VN/setting.json +53 -6
  64. package/locales/zh-CN/chat.json +12 -1
  65. package/locales/zh-CN/common.json +16 -0
  66. package/locales/zh-CN/error.json +34 -5
  67. package/locales/zh-CN/setting.json +59 -12
  68. package/locales/zh-TW/chat.json +12 -1
  69. package/locales/zh-TW/common.json +16 -0
  70. package/locales/zh-TW/error.json +35 -6
  71. package/locales/zh-TW/setting.json +53 -6
  72. package/next.config.mjs +8 -2
  73. package/package.json +8 -1
  74. package/src/app/api/chat/[provider]/agentRuntime.ts +129 -0
  75. package/src/app/api/chat/[provider]/route.ts +64 -0
  76. package/src/app/api/chat/auth.ts +42 -0
  77. package/src/app/api/chat/google/route.ts +86 -0
  78. package/src/app/api/config/route.ts +6 -1
  79. package/src/app/api/config.ts +3 -3
  80. package/src/app/api/errorResponse.test.ts +8 -8
  81. package/src/app/api/errorResponse.ts +43 -6
  82. package/src/app/api/openai/createBizOpenAI/createAzureOpenai.ts +1 -1
  83. package/src/app/api/openai/createBizOpenAI/createOpenai.ts +1 -1
  84. package/src/app/api/openai/createBizOpenAI/index.ts +2 -2
  85. package/src/app/chat/(desktop)/features/ChatHeader.tsx +6 -4
  86. package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +13 -3
  87. package/src/app/chat/(desktop)/features/ChatInput/Header/index.tsx +16 -24
  88. package/src/app/chat/(desktop)/features/SideBar/index.tsx +1 -0
  89. package/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx +3 -3
  90. package/src/app/chat/features/SessionListContent/List/Item/index.tsx +2 -3
  91. package/src/app/settings/llm/Azure/index.tsx +145 -0
  92. package/src/app/settings/llm/Bedrock/index.tsx +109 -0
  93. package/src/app/settings/llm/{LLM/Checker.tsx → Checker.tsx} +20 -22
  94. package/src/app/settings/llm/Google/index.tsx +74 -0
  95. package/src/app/settings/llm/{LLM → OpenAI}/index.tsx +27 -45
  96. package/src/app/settings/llm/Zhipu/index.tsx +78 -0
  97. package/src/app/settings/llm/const.ts +13 -0
  98. package/src/app/settings/llm/page.tsx +42 -2
  99. package/src/app/settings/llm/useSyncSettings.ts +23 -0
  100. package/src/chains/__tests__/langDetect.test.ts +2 -2
  101. package/src/chains/__tests__/pickEmoji.test.ts +2 -2
  102. package/src/chains/langDetect.ts +2 -2
  103. package/src/chains/pickEmoji.ts +2 -2
  104. package/src/chains/summaryAgentName.ts +2 -2
  105. package/src/chains/summaryDescription.ts +2 -2
  106. package/src/chains/summaryTags.ts +2 -2
  107. package/src/chains/summaryTitle.ts +2 -2
  108. package/src/chains/translate.ts +2 -2
  109. package/src/components/ModelIcon/index.tsx +37 -0
  110. package/src/components/ModelProviderIcon/index.tsx +44 -0
  111. package/src/components/ModelSelect/index.tsx +133 -0
  112. package/src/components/ModelTag/ModelIcon.tsx +35 -0
  113. package/src/components/ModelTag/index.tsx +13 -0
  114. package/src/config/modelProviders/bedrock.ts +43 -0
  115. package/src/config/modelProviders/google.ts +20 -0
  116. package/src/config/modelProviders/index.ts +18 -0
  117. package/src/config/modelProviders/openai.ts +102 -0
  118. package/src/config/modelProviders/zhipu.ts +34 -0
  119. package/src/config/{server.ts → server/app.ts} +1 -24
  120. package/src/config/server/index.ts +13 -0
  121. package/src/config/server/provider.ts +78 -0
  122. package/src/const/auth.ts +30 -0
  123. package/src/const/fetch.ts +3 -0
  124. package/src/const/settings.ts +24 -4
  125. package/src/database/core/migrations/migrateSettingsToUser/index.test.ts +2 -1
  126. package/src/database/core/migrations/migrateSettingsToUser/index.ts +1 -18
  127. package/src/database/core/migrations/migrateSettingsToUser/type.ts +100 -0
  128. package/src/database/models/message.ts +3 -1
  129. package/src/database/schemas/message.ts +1 -0
  130. package/src/database/schemas/session.ts +1 -0
  131. package/src/features/AgentSetting/AgentConfig/ModelSelect.tsx +71 -0
  132. package/src/features/AgentSetting/AgentConfig/index.tsx +171 -161
  133. package/src/features/AgentSetting/AgentConfig/useSyncConfig.ts +23 -0
  134. package/src/features/AgentSetting/AgentPrompt/TokenTag.tsx +39 -0
  135. package/src/features/AgentSetting/AgentPrompt/index.tsx +4 -26
  136. package/src/features/AgentSetting/store/index.ts +10 -2
  137. package/src/features/ChatInput/ActionBar/FileUpload.tsx +11 -4
  138. package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +56 -14
  139. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +42 -7
  140. package/src/features/ChatInput/ActionBar/Token/index.tsx +5 -2
  141. package/src/features/ChatInput/ActionBar/Tools/index.tsx +11 -1
  142. package/src/features/ChatInput/useChatInput.ts +5 -1
  143. package/src/features/Conversation/Error/APIKeyForm/Bedrock.tsx +80 -0
  144. package/src/features/Conversation/Error/APIKeyForm/Google.tsx +61 -0
  145. package/src/features/Conversation/Error/APIKeyForm/OpenAI.tsx +63 -0
  146. package/src/features/Conversation/Error/APIKeyForm/Zhipu.tsx +62 -0
  147. package/src/features/Conversation/Error/APIKeyForm/index.tsx +72 -0
  148. package/src/features/Conversation/Error/AccessCodeForm.tsx +63 -0
  149. package/src/features/Conversation/Error/ErrorJsonViewer.tsx +26 -0
  150. package/src/features/Conversation/Error/InvalidAPIKey.tsx +16 -0
  151. package/src/features/Conversation/Error/InvalidAccessCode.tsx +50 -0
  152. package/src/features/Conversation/Error/OpenAiBizError.tsx +9 -17
  153. package/src/features/Conversation/Error/{Plugin/PluginSettings.tsx → PluginSettings.tsx} +8 -3
  154. package/src/features/Conversation/Error/index.tsx +75 -70
  155. package/src/features/Conversation/Error/style.tsx +9 -3
  156. package/src/features/Conversation/Extras/Assistant.tsx +2 -3
  157. package/src/features/Conversation/Plugins/Inspector/index.tsx +8 -2
  158. package/src/features/Conversation/components/ChatItem/index.tsx +9 -24
  159. package/src/features/Conversation/types/index.tsx +2 -5
  160. package/src/hooks/_header.ts +35 -0
  161. package/src/libs/agent-runtime/BaseAI.ts +9 -0
  162. package/src/libs/agent-runtime/azureOpenai/index.ts +72 -0
  163. package/src/libs/agent-runtime/bedrock/index.ts +134 -0
  164. package/src/libs/agent-runtime/error.ts +26 -0
  165. package/src/libs/agent-runtime/google/index.ts +160 -0
  166. package/src/libs/agent-runtime/index.ts +9 -0
  167. package/src/libs/agent-runtime/openai/index.test.ts +176 -0
  168. package/src/libs/agent-runtime/openai/index.ts +107 -0
  169. package/src/libs/agent-runtime/types/chat.ts +119 -0
  170. package/src/libs/agent-runtime/types/index.ts +2 -0
  171. package/src/libs/agent-runtime/types/type.ts +34 -0
  172. package/src/libs/agent-runtime/utils/createError.ts +10 -0
  173. package/src/libs/agent-runtime/utils/debugStream.ts +18 -0
  174. package/src/libs/agent-runtime/utils/env.ts +1 -0
  175. package/src/libs/agent-runtime/utils/handleOpenAIError.ts +39 -0
  176. package/src/libs/agent-runtime/utils/uriParser.ts +16 -0
  177. package/src/libs/agent-runtime/zhipu/authToken.ts +22 -0
  178. package/src/libs/agent-runtime/zhipu/index.ts +125 -0
  179. package/src/locales/default/chat.ts +12 -2
  180. package/src/locales/default/common.ts +16 -0
  181. package/src/locales/default/error.ts +42 -5
  182. package/src/locales/default/setting.ts +61 -12
  183. package/src/services/__tests__/chat.test.ts +8 -2
  184. package/src/services/__tests__/message.test.ts +1 -1
  185. package/src/services/_auth.ts +106 -0
  186. package/src/services/_header.ts +1 -0
  187. package/src/services/_url.ts +0 -2
  188. package/src/services/chat.ts +32 -14
  189. package/src/store/chat/slices/message/action.ts +9 -6
  190. package/src/store/global/slices/common/action.ts +8 -2
  191. package/src/store/global/slices/settings/action.test.ts +2 -2
  192. package/src/store/global/slices/settings/action.ts +11 -4
  193. package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +242 -78
  194. package/src/store/global/slices/settings/selectors/__snapshots__/selectors.test.ts.snap +2 -0
  195. package/src/store/global/slices/settings/selectors/modelProvider.test.ts +171 -47
  196. package/src/store/global/slices/settings/selectors/modelProvider.ts +136 -43
  197. package/src/store/session/slices/agent/selectors.test.ts +0 -48
  198. package/src/store/session/slices/agent/selectors.ts +7 -12
  199. package/src/types/agent/index.ts +6 -2
  200. package/src/types/fetch.ts +4 -2
  201. package/src/types/files.ts +3 -3
  202. package/src/types/llm.ts +27 -0
  203. package/src/types/message/index.ts +7 -3
  204. package/src/types/openai/chat.ts +6 -11
  205. package/src/types/settings/index.ts +1 -0
  206. package/src/types/settings/modelProvider.ts +37 -1
  207. package/src/utils/__snapshots__/parseModels.test.ts.snap +63 -0
  208. package/src/utils/parseModels.test.ts +24 -0
  209. package/src/utils/parseModels.ts +37 -0
  210. package/src/app/api/openai/chat/createChatCompletion.test.ts +0 -166
  211. package/src/app/api/openai/chat/createChatCompletion.ts +0 -76
  212. package/src/app/api/openai/chat/route.ts +0 -19
  213. package/src/app/api/openai/models/route.ts +0 -17
  214. package/src/app/settings/llm/LLM/ModelList.tsx +0 -51
  215. package/src/app/settings/llm/LLM/getModelList.ts +0 -9
  216. package/src/app/settings/llm/index.tsx +0 -36
  217. package/src/const/llm.ts +0 -32
  218. package/src/features/Conversation/Error/ApiKeyForm.tsx +0 -87
  219. package/src/features/Conversation/Error/ErrorActionContainer.tsx +0 -23
  220. package/src/features/Conversation/Error/InvalidAccess.tsx +0 -90
  221. package/src/features/Conversation/Error/OpenAPIKey.tsx +0 -13
  222. package/src/features/Conversation/Error/Plugin/PluginError.tsx +0 -30
  223. package/src/services/modelList.ts +0 -15
  224. /package/src/app/chat/(desktop)/features/ChatInput/{Header → Footer}/DragUpload.tsx +0 -0
  225. /package/src/{app/api/openai/chat → libs/agent-runtime/utils}/desensitizeUrl.test.ts +0 -0
  226. /package/src/{app/api/openai/chat → libs/agent-runtime/utils}/desensitizeUrl.ts +0 -0
  227. /package/src/types/{translate.ts → message/translate.ts} +0 -0
@@ -0,0 +1,145 @@
1
+ import { Azure, OpenAI } from '@lobehub/icons';
2
+ import { Form, type ItemGroup, Markdown } from '@lobehub/ui';
3
+ import { Form as AntForm, AutoComplete, Divider, Input, Switch } from 'antd';
4
+ import { createStyles } from 'antd-style';
5
+ import { debounce } from 'lodash-es';
6
+ import { memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
9
+
10
+ import { FORM_STYLE } from '@/const/layoutTokens';
11
+ import { ModelProvider } from '@/libs/agent-runtime';
12
+ import { useGlobalStore } from '@/store/global';
13
+ import { modelProviderSelectors } from '@/store/global/selectors';
14
+
15
+ import Checker from '../Checker';
16
+ import { LLMProviderApiTokenKey, LLMProviderBaseUrlKey, LLMProviderConfigKey } from '../const';
17
+ import { useSyncSettings } from '../useSyncSettings';
18
+
19
+ const useStyles = createStyles(({ css, token }) => ({
20
+ markdown: css`
21
+ a {
22
+ font-size: 12px !important;
23
+ }
24
+
25
+ p {
26
+ font-size: 12px !important;
27
+ color: ${token.colorTextDescription} !important;
28
+ }
29
+ `,
30
+ tip: css`
31
+ font-size: 12px;
32
+ color: ${token.colorTextDescription};
33
+ `,
34
+ }));
35
+
36
+ const providerKey = 'azure';
37
+
38
+ const AzureOpenAIProvider = memo(() => {
39
+ const { t } = useTranslation('setting');
40
+ const [form] = AntForm.useForm();
41
+ const { styles } = useStyles();
42
+
43
+ const [toggleProviderEnabled, setSettings] = useGlobalStore((s) => [
44
+ s.toggleProviderEnabled,
45
+ s.setSettings,
46
+ ]);
47
+
48
+ const enabled = useGlobalStore(modelProviderSelectors.enableAzure);
49
+
50
+ useSyncSettings(form);
51
+
52
+ const openAI: ItemGroup = {
53
+ children: [
54
+ {
55
+ children: (
56
+ <Input.Password
57
+ autoComplete={'new-password'}
58
+ placeholder={t('llm.AzureOpenAI.token.placeholder')}
59
+ />
60
+ ),
61
+ desc: t('llm.AzureOpenAI.token.desc'),
62
+ label: t('llm.AzureOpenAI.token.title'),
63
+ name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
64
+ },
65
+ {
66
+ children: <Input allowClear placeholder={t('llm.AzureOpenAI.endpoint.placeholder')} />,
67
+ desc: t('llm.AzureOpenAI.endpoint.desc'),
68
+ label: t('llm.AzureOpenAI.endpoint.title'),
69
+ name: [LLMProviderConfigKey, providerKey, LLMProviderBaseUrlKey],
70
+ },
71
+ {
72
+ children: (
73
+ <AutoComplete
74
+ options={[
75
+ '2023-12-01-preview',
76
+ '2023-08-01-preview',
77
+ '2023-07-01-preview',
78
+ '2023-06-01-preview',
79
+ '2023-03-15-preview',
80
+ ].map((i) => ({
81
+ label: i,
82
+ value: i,
83
+ }))}
84
+ placeholder={'20XX-XX-XX'}
85
+ />
86
+ ),
87
+ desc: (
88
+ <Markdown className={styles.markdown}>
89
+ {t('llm.AzureOpenAI.azureApiVersion.desc')}
90
+ </Markdown>
91
+ ),
92
+ label: t('llm.AzureOpenAI.azureApiVersion.title'),
93
+ name: [LLMProviderConfigKey, providerKey, 'apiVersion'],
94
+ },
95
+ {
96
+ children: (
97
+ <Input.TextArea
98
+ allowClear
99
+ placeholder={'gpt-35-16k,my-gpt=gpt-35-turbo'}
100
+ style={{ height: 100 }}
101
+ />
102
+ ),
103
+ desc: (
104
+ <Markdown className={styles.markdown}>{t('llm.AzureOpenAI.deployments.desc')}</Markdown>
105
+ ),
106
+
107
+ label: t('llm.AzureOpenAI.deployments.title'),
108
+ name: [LLMProviderConfigKey, providerKey, 'deployments'],
109
+ },
110
+ {
111
+ children: <Checker model={'gpt-3.5-turbo'} provider={ModelProvider.Azure} />,
112
+ desc: t('llm.checker.desc'),
113
+ label: t('llm.checker.title'),
114
+ minWidth: undefined,
115
+ },
116
+ ],
117
+ defaultActive: enabled,
118
+ extra: (
119
+ <Switch
120
+ onChange={(enabled) => {
121
+ toggleProviderEnabled(providerKey, enabled);
122
+ }}
123
+ value={enabled}
124
+ />
125
+ ),
126
+ title: (
127
+ <Flexbox align={'center'} gap={8} horizontal>
128
+ <Azure.Combine size={24} type={'color'}></Azure.Combine>
129
+ <Divider style={{ margin: '0 4px' }} type={'vertical'} />
130
+ <OpenAI.Combine size={24}></OpenAI.Combine>
131
+ </Flexbox>
132
+ ),
133
+ };
134
+
135
+ return (
136
+ <Form
137
+ form={form}
138
+ items={[openAI]}
139
+ onValuesChange={debounce(setSettings, 100)}
140
+ {...FORM_STYLE}
141
+ />
142
+ );
143
+ });
144
+
145
+ export default AzureOpenAIProvider;
@@ -0,0 +1,109 @@
1
+ import { Aws, Bedrock } from '@lobehub/icons';
2
+ import { Form, type ItemGroup } from '@lobehub/ui';
3
+ import { Form as AntForm, Divider, Input, Select, Switch } from 'antd';
4
+ import { debounce } from 'lodash-es';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Flexbox } from 'react-layout-kit';
8
+
9
+ import { FORM_STYLE } from '@/const/layoutTokens';
10
+ import { ModelProvider } from '@/libs/agent-runtime';
11
+ import { useGlobalStore } from '@/store/global';
12
+ import { modelProviderSelectors } from '@/store/global/selectors';
13
+ import { GlobalLLMProviderKey } from '@/types/settings';
14
+
15
+ import Checker from '../Checker';
16
+ import { LLMProviderConfigKey } from '../const';
17
+ import { useSyncSettings } from '../useSyncSettings';
18
+
19
+ const providerKey: GlobalLLMProviderKey = 'bedrock';
20
+
21
+ const BedrockProvider = memo(() => {
22
+ const { t } = useTranslation('setting');
23
+ const [form] = AntForm.useForm();
24
+ const [toggleProviderEnabled, setSettings] = useGlobalStore((s) => [
25
+ s.toggleProviderEnabled,
26
+ s.setSettings,
27
+ ]);
28
+ const enabled = useGlobalStore(modelProviderSelectors.enableBedrock);
29
+
30
+ useSyncSettings(form);
31
+
32
+ const model: ItemGroup = {
33
+ children: [
34
+ {
35
+ children: (
36
+ <Input.Password
37
+ autoComplete={'new-password'}
38
+ placeholder={t('llm.Bedrock.accessKeyId.placeholder')}
39
+ />
40
+ ),
41
+ desc: t('llm.Bedrock.accessKeyId.desc'),
42
+ label: t('llm.Bedrock.accessKeyId.title'),
43
+ name: [LLMProviderConfigKey, providerKey, 'accessKeyId'],
44
+ },
45
+ {
46
+ children: (
47
+ <Input.Password
48
+ autoComplete={'new-password'}
49
+ placeholder={t('llm.Bedrock.secretAccessKey.placeholder')}
50
+ />
51
+ ),
52
+ desc: t('llm.Bedrock.secretAccessKey.desc'),
53
+ label: t('llm.Bedrock.secretAccessKey.title'),
54
+ name: [LLMProviderConfigKey, providerKey, 'secretAccessKey'],
55
+ },
56
+ {
57
+ children: (
58
+ <Select
59
+ allowClear
60
+ options={['us-east-1', 'us-west-2', 'ap-southeast-1'].map((i) => ({
61
+ label: i,
62
+ value: i,
63
+ }))}
64
+ placeholder={'us-east-1'}
65
+ />
66
+ ),
67
+ desc: t('llm.Bedrock.region.desc'),
68
+ label: t('llm.Bedrock.region.title'),
69
+ name: [LLMProviderConfigKey, providerKey, 'region'],
70
+ },
71
+ {
72
+ children: (
73
+ <Checker model={'anthropic.claude-instant-v1'} provider={ModelProvider.Bedrock} />
74
+ ),
75
+ desc: t('llm.Bedrock.checker.desc'),
76
+ label: t('llm.checker.title'),
77
+ minWidth: undefined,
78
+ },
79
+ ],
80
+ defaultActive: enabled,
81
+ extra: (
82
+ <div
83
+ onClick={(e) => {
84
+ e.stopPropagation();
85
+ }}
86
+ >
87
+ <Switch
88
+ onChange={(enabled) => {
89
+ toggleProviderEnabled(providerKey, enabled);
90
+ }}
91
+ value={enabled}
92
+ />
93
+ </div>
94
+ ),
95
+ title: (
96
+ <Flexbox align={'center'} gap={8} horizontal>
97
+ <Aws.Color size={32} />
98
+ <Divider style={{ margin: '0 4px' }} type={'vertical'} />
99
+ <Bedrock.Combine size={24} type={'color'} />
100
+ </Flexbox>
101
+ ),
102
+ };
103
+
104
+ return (
105
+ <Form form={form} items={[model]} onValuesChange={debounce(setSettings, 100)} {...FORM_STYLE} />
106
+ );
107
+ });
108
+
109
+ export default BedrockProvider;
@@ -6,15 +6,16 @@ import { memo, useState } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Flexbox } from 'react-layout-kit';
8
8
 
9
+ import { useIsMobile } from '@/hooks/useIsMobile';
9
10
  import { chatService } from '@/services/chat';
10
11
  import { ChatMessageError } from '@/types/message';
11
12
 
12
- import { getModelList } from './getModelList';
13
-
14
- interface CheckerProps {
15
- checkModel?: boolean;
13
+ interface ConnectionCheckerProps {
14
+ model: string;
15
+ provider: string;
16
16
  }
17
- const Checker = memo<CheckerProps>(({ checkModel }) => {
17
+
18
+ const Checker = memo<ConnectionCheckerProps>(({ model, provider }) => {
18
19
  const { t } = useTranslation('setting');
19
20
 
20
21
  const [loading, setLoading] = useState(false);
@@ -24,10 +25,6 @@ const Checker = memo<CheckerProps>(({ checkModel }) => {
24
25
  const [error, setError] = useState<ChatMessageError | undefined>();
25
26
 
26
27
  const checkConnection = async () => {
27
- if (checkModel) {
28
- getModelList();
29
- }
30
-
31
28
  const data = await chatService.fetchPresetTaskResult({
32
29
  onError: (_, rawError) => {
33
30
  setError(rawError);
@@ -43,7 +40,8 @@ const Checker = memo<CheckerProps>(({ checkModel }) => {
43
40
  role: 'user',
44
41
  },
45
42
  ],
46
- model: 'gpt-3.5-turbo',
43
+ model,
44
+ provider,
47
45
  },
48
46
  });
49
47
 
@@ -52,13 +50,11 @@ const Checker = memo<CheckerProps>(({ checkModel }) => {
52
50
  setPass(true);
53
51
  }
54
52
  };
55
- return (
56
- <Flexbox gap={8}>
57
- <Flexbox align={'center'} gap={12} horizontal>
58
- <Button loading={loading} onClick={checkConnection}>
59
- {t('llm.OpenAI.check.button')}
60
- </Button>
53
+ const isMobile = useIsMobile();
61
54
 
55
+ return (
56
+ <Flexbox align={isMobile ? 'flex-start' : 'flex-end'} gap={8}>
57
+ <Flexbox align={'center'} direction={isMobile ? 'horizontal-reverse' : 'horizontal'} gap={12}>
62
58
  {pass && (
63
59
  <Flexbox gap={4} horizontal>
64
60
  <CheckCircleFilled
@@ -66,23 +62,25 @@ const Checker = memo<CheckerProps>(({ checkModel }) => {
66
62
  color: theme.colorSuccess,
67
63
  }}
68
64
  />
69
- {t('llm.OpenAI.check.pass')}
65
+ {t('llm.checker.pass')}
70
66
  </Flexbox>
71
67
  )}
68
+ <Button loading={loading} onClick={checkConnection}>
69
+ {t('llm.checker.button')}
70
+ </Button>
72
71
  </Flexbox>
73
-
74
72
  {error && (
75
- <Flexbox gap={8}>
73
+ <Flexbox gap={8} style={{ maxWidth: '600px', width: '100%' }}>
76
74
  <Alert
77
75
  banner
78
76
  extra={
79
- <Flexbox style={{ maxWidth: 600 }}>
77
+ <Flexbox>
80
78
  <Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
81
- {JSON.stringify(error.body, null, 2)}
79
+ {JSON.stringify(error.body || error, null, 2)}
82
80
  </Highlighter>
83
81
  </Flexbox>
84
82
  }
85
- message={error.message}
83
+ message={t(`response.${error.type}` as any, { ns: 'error' })}
86
84
  showIcon
87
85
  type={'error'}
88
86
  />
@@ -0,0 +1,74 @@
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';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Flexbox } from 'react-layout-kit';
8
+
9
+ import { FORM_STYLE } from '@/const/layoutTokens';
10
+ import { ModelProvider } from '@/libs/agent-runtime';
11
+ import { useGlobalStore } from '@/store/global';
12
+ import { modelProviderSelectors } from '@/store/global/selectors';
13
+ import { GlobalLLMProviderKey } from '@/types/settings';
14
+
15
+ import Checker from '../Checker';
16
+ import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
17
+ import { useSyncSettings } from '../useSyncSettings';
18
+
19
+ const providerKey: GlobalLLMProviderKey = 'google';
20
+
21
+ const GoogleProvider = memo(() => {
22
+ 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: undefined,
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
+
69
+ return (
70
+ <Form form={form} items={[model]} onValuesChange={debounce(setSettings, 100)} {...FORM_STYLE} />
71
+ );
72
+ });
73
+
74
+ export default GoogleProvider;
@@ -1,16 +1,20 @@
1
+ import { OpenAI } from '@lobehub/icons';
1
2
  import { Form, type ItemGroup, Markdown } from '@lobehub/ui';
2
3
  import { Form as AntForm, AutoComplete, Input, Switch } from 'antd';
3
4
  import { createStyles } from 'antd-style';
4
5
  import { debounce } from 'lodash-es';
5
- import { Webhook } from 'lucide-react';
6
- import { memo, useEffect } from 'react';
6
+ import { memo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
8
9
 
9
10
  import { FORM_STYLE } from '@/const/layoutTokens';
11
+ import { ModelProvider } from '@/libs/agent-runtime';
10
12
  import { useGlobalStore } from '@/store/global';
11
13
  import { modelProviderSelectors } from '@/store/global/selectors';
12
14
 
13
- import Checker from './Checker';
15
+ import Checker from '../Checker';
16
+ import { LLMProviderConfigKey } from '../const';
17
+ import { useSyncSettings } from '../useSyncSettings';
14
18
 
15
19
  const useStyles = createStyles(({ css, token }) => ({
16
20
  markdown: css`
@@ -28,29 +32,19 @@ const useStyles = createStyles(({ css, token }) => ({
28
32
  color: ${token.colorTextDescription};
29
33
  `,
30
34
  }));
31
-
32
- const configKey = 'languageModel';
35
+ const providerKey = 'openAI';
33
36
 
34
37
  const LLM = memo(() => {
35
38
  const { t } = useTranslation('setting');
36
- const [form] = AntForm.useForm();
37
39
  const { styles } = useStyles();
40
+ const [form] = AntForm.useForm();
41
+
38
42
  const [useAzure, setSettings] = useGlobalStore((s) => [
39
43
  modelProviderSelectors.enableAzure(s),
40
44
  s.setSettings,
41
45
  ]);
42
46
 
43
- useEffect(() => {
44
- const unsubscribe = useGlobalStore.subscribe(
45
- (s) => s.settings,
46
- (settings) => {
47
- form.setFieldsValue(settings);
48
- },
49
- );
50
- return () => {
51
- unsubscribe();
52
- };
53
- }, []);
47
+ useSyncSettings(form);
54
48
 
55
49
  const openAI: ItemGroup = {
56
50
  children: [
@@ -65,7 +59,7 @@ const LLM = memo(() => {
65
59
  ),
66
60
  desc: useAzure ? t('llm.AzureOpenAI.token.desc') : t('llm.OpenAI.token.desc'),
67
61
  label: useAzure ? t('llm.AzureOpenAI.token.title') : t('llm.OpenAI.token.title'),
68
- name: [configKey, 'openAI', 'OPENAI_API_KEY'],
62
+ name: [LLMProviderConfigKey, providerKey, 'OPENAI_API_KEY'],
69
63
  },
70
64
  {
71
65
  children: (
@@ -80,7 +74,7 @@ const LLM = memo(() => {
80
74
  ),
81
75
  desc: useAzure ? t('llm.AzureOpenAI.endpoint.desc') : t('llm.OpenAI.endpoint.desc'),
82
76
  label: useAzure ? t('llm.AzureOpenAI.endpoint.title') : t('llm.OpenAI.endpoint.title'),
83
- name: [configKey, 'openAI', 'endpoint'],
77
+ name: [LLMProviderConfigKey, providerKey, 'endpoint'],
84
78
  },
85
79
  {
86
80
  children: (
@@ -92,30 +86,21 @@ const LLM = memo(() => {
92
86
  ),
93
87
  desc: t('llm.OpenAI.customModelName.desc'),
94
88
  label: t('llm.OpenAI.customModelName.title'),
95
- name: [configKey, 'openAI', 'customModelName'],
89
+ name: [LLMProviderConfigKey, providerKey, 'customModelName'],
96
90
  },
97
91
  {
98
- children: (
99
- <Switch />
100
- // <Flexbox gap={4}>
101
- // <div>
102
- //
103
- // </div>
104
- // {getClientConfig().USE_AZURE_OPENAI && (
105
- // <div className={styles.tip}>{t('llm.OpenAI.useAzure.serverConfig')}</div>
106
- // )}
107
- // </Flexbox>
108
- ),
92
+ children: <Switch />,
109
93
  desc: t('llm.OpenAI.useAzure.desc'),
110
94
  label: t('llm.OpenAI.useAzure.title'),
111
95
  minWidth: undefined,
112
- name: [configKey, 'openAI', 'useAzure'],
96
+ name: [LLMProviderConfigKey, 'openAI', 'useAzure'],
113
97
  valuePropName: 'checked',
114
98
  },
115
99
  {
116
100
  children: (
117
101
  <AutoComplete
118
102
  options={[
103
+ '2023-12-01-preview',
119
104
  '2023-08-01-preview',
120
105
  '2023-07-01-preview',
121
106
  '2023-06-01-preview',
@@ -133,23 +118,20 @@ const LLM = memo(() => {
133
118
  ),
134
119
  hidden: !useAzure,
135
120
  label: t('llm.OpenAI.azureApiVersion.title'),
136
- name: [configKey, 'openAI', 'azureApiVersion'],
121
+ name: [LLMProviderConfigKey, providerKey, 'azureApiVersion'],
137
122
  },
138
123
  {
139
- children: <Checker checkModel={!useAzure} />,
140
- desc: t('llm.OpenAI.check.desc'),
141
- label: t('llm.OpenAI.check.title'),
142
- minWidth: undefined,
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%',
143
128
  },
144
- // {
145
- // children: useAzure ? <Flexbox>{t('llm.OpenAI.models.notSupport')}</Flexbox> : <ModelList />,
146
- // desc: useAzure ? t('llm.OpenAI.models.notSupportTip') : t('llm.OpenAI.models.desc'),
147
- // label: t('llm.OpenAI.models.title'),
148
- // name: [configKey, 'openAI', 'models'],
149
- // },
150
129
  ],
151
- icon: Webhook,
152
- title: t('llm.OpenAI.title'),
130
+ title: (
131
+ <Flexbox align={'center'} gap={8} horizontal>
132
+ <OpenAI.Combine size={24}></OpenAI.Combine>
133
+ </Flexbox>
134
+ ),
153
135
  };
154
136
 
155
137
  return (
@@ -0,0 +1,78 @@
1
+ import { Zhipu } from '@lobehub/icons';
2
+ import { Form, type ItemGroup } from '@lobehub/ui';
3
+ import { Form as AntForm, Input, Switch } from 'antd';
4
+ import { useTheme } from 'antd-style';
5
+ import { debounce } from 'lodash-es';
6
+ import { lighten } from 'polished';
7
+ import { memo } from 'react';
8
+ import { useTranslation } from 'react-i18next';
9
+ import { Flexbox } from 'react-layout-kit';
10
+
11
+ import { FORM_STYLE } from '@/const/layoutTokens';
12
+ import { ModelProvider } from '@/libs/agent-runtime';
13
+ import { useGlobalStore } from '@/store/global';
14
+ import { modelProviderSelectors } from '@/store/global/selectors';
15
+
16
+ import Checker from '../Checker';
17
+ import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
18
+ import { useSyncSettings } from '../useSyncSettings';
19
+
20
+ const providerKey = 'zhipu';
21
+
22
+ const ZhipuProvider = memo(() => {
23
+ 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
+
32
+ useSyncSettings(form);
33
+
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: undefined,
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>
65
+ <Zhipu.Combine
66
+ color={theme.isDarkMode ? lighten(0.1, Zhipu.colorPrimary) : Zhipu.colorPrimary}
67
+ size={32}
68
+ />
69
+ </Flexbox>
70
+ ),
71
+ };
72
+
73
+ return (
74
+ <Form form={form} items={[model]} onValuesChange={debounce(setSettings, 100)} {...FORM_STYLE} />
75
+ );
76
+ });
77
+
78
+ export default ZhipuProvider;
@@ -0,0 +1,13 @@
1
+ export const LLMProviderConfigKey = 'languageModel';
2
+
3
+ /**
4
+ * we use this key to define default api key
5
+ * equal GOOGLE_API_KEY or ZHIPU_API_KEY
6
+ */
7
+ export const LLMProviderApiTokenKey = 'apiKey';
8
+
9
+ /**
10
+ * we use this key to define the baseURL
11
+ * equal OPENAI_PROXY_URL
12
+ */
13
+ export const LLMProviderBaseUrlKey = 'endpoint';