@lobehub/chat 1.47.16 → 1.47.18

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 (51) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/locales/ar/modelProvider.json +1 -0
  4. package/locales/ar/models.json +30 -3
  5. package/locales/bg-BG/modelProvider.json +1 -0
  6. package/locales/bg-BG/models.json +30 -3
  7. package/locales/de-DE/modelProvider.json +1 -0
  8. package/locales/de-DE/models.json +30 -3
  9. package/locales/en-US/modelProvider.json +1 -0
  10. package/locales/en-US/models.json +30 -3
  11. package/locales/es-ES/modelProvider.json +1 -0
  12. package/locales/es-ES/models.json +30 -3
  13. package/locales/fa-IR/modelProvider.json +1 -0
  14. package/locales/fa-IR/models.json +30 -3
  15. package/locales/fr-FR/modelProvider.json +1 -0
  16. package/locales/fr-FR/models.json +30 -3
  17. package/locales/it-IT/modelProvider.json +1 -0
  18. package/locales/it-IT/models.json +30 -3
  19. package/locales/ja-JP/modelProvider.json +1 -0
  20. package/locales/ja-JP/models.json +30 -3
  21. package/locales/ko-KR/modelProvider.json +1 -0
  22. package/locales/ko-KR/models.json +30 -3
  23. package/locales/nl-NL/modelProvider.json +1 -0
  24. package/locales/nl-NL/models.json +30 -3
  25. package/locales/pl-PL/modelProvider.json +1 -0
  26. package/locales/pl-PL/models.json +30 -3
  27. package/locales/pt-BR/modelProvider.json +1 -0
  28. package/locales/pt-BR/models.json +30 -3
  29. package/locales/ru-RU/modelProvider.json +1 -0
  30. package/locales/ru-RU/models.json +30 -3
  31. package/locales/tr-TR/modelProvider.json +1 -0
  32. package/locales/tr-TR/models.json +30 -3
  33. package/locales/vi-VN/modelProvider.json +1 -0
  34. package/locales/vi-VN/models.json +30 -3
  35. package/locales/zh-CN/modelProvider.json +2 -1
  36. package/locales/zh-CN/models.json +32 -5
  37. package/locales/zh-TW/modelProvider.json +1 -0
  38. package/locales/zh-TW/models.json +30 -3
  39. package/package.json +2 -2
  40. package/src/app/(main)/settings/provider/(detail)/azure/page.tsx +4 -6
  41. package/src/app/(main)/settings/provider/(detail)/bedrock/page.tsx +5 -4
  42. package/src/app/(main)/settings/provider/(detail)/cloudflare/page.tsx +3 -3
  43. package/src/app/(main)/settings/provider/(detail)/github/page.tsx +2 -2
  44. package/src/app/(main)/settings/provider/(detail)/huggingface/page.tsx +2 -2
  45. package/src/app/(main)/settings/provider/(detail)/wenxin/page.tsx +3 -3
  46. package/src/app/(main)/settings/provider/features/ProviderConfig/index.tsx +17 -4
  47. package/src/components/FormInput/FormInput.tsx +42 -0
  48. package/src/components/FormInput/FormPassword.tsx +42 -0
  49. package/src/components/FormInput/index.ts +2 -0
  50. package/src/config/modelProviders/deepseek.ts +3 -0
  51. package/src/locales/default/modelProvider.ts +1 -0
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { Input } from 'antd';
4
3
  import { useTranslation } from 'react-i18next';
5
4
 
5
+ import { FormPassword } from '@/components/FormInput';
6
6
  import { WenxinProviderCard } from '@/config/modelProviders';
7
7
  import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
8
8
  import { GlobalLLMProviderKey } from '@/types/user/settings';
@@ -26,7 +26,7 @@ const useProviderCard = (): ProviderItem => {
26
26
  children: isLoading ? (
27
27
  <SkeletonInput />
28
28
  ) : (
29
- <Input.Password
29
+ <FormPassword
30
30
  autoComplete={'new-password'}
31
31
  placeholder={t(`${providerKey}.accessKey.placeholder`)}
32
32
  />
@@ -39,7 +39,7 @@ const useProviderCard = (): ProviderItem => {
39
39
  children: isLoading ? (
40
40
  <SkeletonInput />
41
41
  ) : (
42
- <Input.Password
42
+ <FormPassword
43
43
  autoComplete={'new-password'}
44
44
  placeholder={t(`${providerKey}.secretKey.placeholder`)}
45
45
  />
@@ -3,7 +3,7 @@
3
3
  import { ProviderCombine } from '@lobehub/icons';
4
4
  import { Avatar, Form, type FormItemProps, Icon, type ItemGroup, Tooltip } from '@lobehub/ui';
5
5
  import { useDebounceFn } from 'ahooks';
6
- import { Input, Skeleton, Switch } from 'antd';
6
+ import { Skeleton, Switch } from 'antd';
7
7
  import { createStyles } from 'antd-style';
8
8
  import { Loader2Icon, LockIcon } from 'lucide-react';
9
9
  import Link from 'next/link';
@@ -11,7 +11,9 @@ import { ReactNode, memo, useLayoutEffect } from 'react';
11
11
  import { Trans, useTranslation } from 'react-i18next';
12
12
  import { Center, Flexbox } from 'react-layout-kit';
13
13
  import urlJoin from 'url-join';
14
+ import { z } from 'zod';
14
15
 
16
+ import { FormInput, FormPassword } from '@/components/FormInput';
15
17
  import { FORM_STYLE } from '@/const/layoutTokens';
16
18
  import { AES_GCM_URL, BASE_PROVIDER_DOC_URL } from '@/const/url';
17
19
  import { isServerMode } from '@/const/version';
@@ -24,8 +26,8 @@ import {
24
26
 
25
27
  import { KeyVaultsConfigKey, LLMProviderApiTokenKey, LLMProviderBaseUrlKey } from '../../const';
26
28
  import Checker from './Checker';
27
- import { SkeletonInput } from './SkeletonInput';
28
29
  import EnableSwitch from './EnableSwitch';
30
+ import { SkeletonInput } from './SkeletonInput';
29
31
  import UpdateProviderInfo from './UpdateProviderInfo';
30
32
 
31
33
  const useStyles = createStyles(({ css, prefixCls, responsive, token }) => ({
@@ -170,7 +172,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
170
172
  children: isLoading ? (
171
173
  <SkeletonInput />
172
174
  ) : (
173
- <Input.Password
175
+ <FormPassword
174
176
  autoComplete={'new-password'}
175
177
  placeholder={t(`providerModels.config.apiKey.placeholder`, { name })}
176
178
  suffix={
@@ -210,7 +212,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
210
212
  children: isLoading ? (
211
213
  <SkeletonInput />
212
214
  ) : (
213
- <Input
215
+ <FormInput
214
216
  allowClear
215
217
  placeholder={
216
218
  (!!proxyUrl && proxyUrl?.placeholder) ||
@@ -226,6 +228,17 @@ const ProviderConfig = memo<ProviderConfigProps>(
226
228
  desc: (!!proxyUrl && proxyUrl?.desc) || t('providerModels.config.baseURL.desc'),
227
229
  label: (!!proxyUrl && proxyUrl?.title) || t('providerModels.config.baseURL.title'),
228
230
  name: [KeyVaultsConfigKey, LLMProviderBaseUrlKey],
231
+ rules: [
232
+ {
233
+ validator: (_: any, value: string) => {
234
+ if (!value) return;
235
+
236
+ return z.string().url().safeParse(value).error
237
+ ? Promise.reject(t('providerModels.config.baseURL.invalid'))
238
+ : Promise.resolve();
239
+ },
240
+ },
241
+ ],
229
242
  }
230
243
  : undefined;
231
244
 
@@ -0,0 +1,42 @@
1
+ import { Input } from 'antd';
2
+ import { InputRef, InputProps as Props } from 'antd/es/input/Input';
3
+ import { memo, useRef, useState } from 'react';
4
+
5
+ interface FormInputProps extends Omit<Props, 'onChange'> {
6
+ onChange?: (value: string) => void;
7
+ }
8
+
9
+ const FormInput = memo<FormInputProps>(({ onChange, value: defaultValue, ...props }) => {
10
+ const ref = useRef<InputRef>(null);
11
+ const isChineseInput = useRef(false);
12
+
13
+ const [value, setValue] = useState(defaultValue as string);
14
+
15
+ return (
16
+ <Input
17
+ onBlur={() => {
18
+ onChange?.(value);
19
+ }}
20
+ onChange={(e) => {
21
+ setValue(e.target.value);
22
+ }}
23
+ onCompositionEnd={() => {
24
+ isChineseInput.current = false;
25
+ }}
26
+ onCompositionStart={() => {
27
+ isChineseInput.current = true;
28
+ }}
29
+ onPressEnter={() => {
30
+ if (isChineseInput.current) return;
31
+ onChange?.(value);
32
+ }}
33
+ ref={ref}
34
+ {...props}
35
+ value={value}
36
+ />
37
+ );
38
+ });
39
+
40
+ FormInput.displayName = 'FormInput';
41
+
42
+ export default FormInput;
@@ -0,0 +1,42 @@
1
+ import { Input } from 'antd';
2
+ import { InputRef, InputProps as Props } from 'antd/es/input/Input';
3
+ import { memo, useRef, useState } from 'react';
4
+
5
+ interface FormPasswordProps extends Omit<Props, 'onChange'> {
6
+ onChange?: (value: string) => void;
7
+ }
8
+
9
+ const FormPassword = memo<FormPasswordProps>(({ onChange, value: defaultValue, ...props }) => {
10
+ const ref = useRef<InputRef>(null);
11
+ const isChineseInput = useRef(false);
12
+
13
+ const [value, setValue] = useState(defaultValue as string);
14
+
15
+ return (
16
+ <Input.Password
17
+ onBlur={() => {
18
+ onChange?.(value);
19
+ }}
20
+ onChange={(e) => {
21
+ setValue(e.target.value);
22
+ }}
23
+ onCompositionEnd={() => {
24
+ isChineseInput.current = false;
25
+ }}
26
+ onCompositionStart={() => {
27
+ isChineseInput.current = true;
28
+ }}
29
+ onPressEnter={() => {
30
+ if (isChineseInput.current) return;
31
+ onChange?.(value);
32
+ }}
33
+ ref={ref}
34
+ {...props}
35
+ value={value}
36
+ />
37
+ );
38
+ });
39
+
40
+ FormPassword.displayName = 'FormPassword';
41
+
42
+ export default FormPassword;
@@ -0,0 +1,2 @@
1
+ export { default as FormInput } from './FormInput';
2
+ export { default as FormPassword } from './FormPassword';
@@ -43,6 +43,9 @@ const DeepSeek: ModelProviderCard = {
43
43
  modelsUrl: 'https://platform.deepseek.com/api-docs/zh-cn/quick_start/pricing',
44
44
  name: 'DeepSeek',
45
45
  settings: {
46
+ proxyUrl: {
47
+ placeholder: 'https://api.deepseek.com',
48
+ },
46
49
  sdkType: 'openai',
47
50
  showModelFetcher: true,
48
51
  },
@@ -201,6 +201,7 @@ export default {
201
201
  },
202
202
  baseURL: {
203
203
  desc: '必须包含 http(s)://',
204
+ invalid: '请输入合法的 URL',
204
205
  placeholder: 'https://your-proxy-url.com/v1',
205
206
  title: 'API 代理地址',
206
207
  },