@lobehub/chat 1.44.1 → 1.44.2
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/changelog/v1.json +9 -0
- package/locales/ar/modelProvider.json +2 -0
- package/locales/bg-BG/modelProvider.json +2 -0
- package/locales/de-DE/modelProvider.json +2 -0
- package/locales/en-US/modelProvider.json +2 -0
- package/locales/es-ES/modelProvider.json +2 -0
- package/locales/fa-IR/modelProvider.json +2 -0
- package/locales/fr-FR/modelProvider.json +2 -0
- package/locales/it-IT/modelProvider.json +2 -0
- package/locales/ja-JP/modelProvider.json +2 -0
- package/locales/ko-KR/modelProvider.json +2 -0
- package/locales/nl-NL/modelProvider.json +2 -0
- package/locales/pl-PL/modelProvider.json +2 -0
- package/locales/pt-BR/modelProvider.json +2 -0
- package/locales/ru-RU/modelProvider.json +2 -0
- package/locales/tr-TR/modelProvider.json +2 -0
- package/locales/vi-VN/modelProvider.json +2 -0
- package/locales/zh-CN/modelProvider.json +3 -1
- package/locales/zh-TW/modelProvider.json +2 -0
- package/package.json +1 -1
- package/src/app/(main)/settings/provider/features/CreateNewProvider/index.tsx +8 -1
- package/src/app/(main)/settings/provider/features/ProviderConfig/Checker.tsx +9 -6
- package/src/app/(main)/settings/provider/features/ProviderConfig/index.tsx +15 -3
- package/src/config/aiModels/siliconcloud.ts +0 -13
- package/src/locales/default/modelProvider.ts +3 -1
- package/src/store/aiInfra/slices/aiProvider/action.ts +17 -2
- package/src/store/aiInfra/slices/aiProvider/initialState.ts +2 -0
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +4 -0
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.44.2](https://github.com/lobehub/lobe-chat/compare/v1.44.1...v1.44.2)
|
6
|
+
|
7
|
+
<sup>Released on **2025-01-08**</sup>
|
8
|
+
|
9
|
+
#### 🐛 Bug Fixes
|
10
|
+
|
11
|
+
- **misc**: Add provider id validate.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's fixed
|
19
|
+
|
20
|
+
- **misc**: Add provider id validate, closes [#5336](https://github.com/lobehub/lobe-chat/issues/5336) ([7f8a1b6](https://github.com/lobehub/lobe-chat/commit/7f8a1b6))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
### [Version 1.44.1](https://github.com/lobehub/lobe-chat/compare/v1.44.0...v1.44.1)
|
6
31
|
|
7
32
|
<sup>Released on **2025-01-08**</sup>
|
package/changelog/v1.json
CHANGED
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "نبذة عن مزود الخدمة"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "معرف فريد لمزود الخدمة، لا يمكن تعديله بعد الإنشاء",
|
82
|
+
"format": "يمكن أن يحتوي فقط على أحرف صغيرة، وشرطات (-) وشرطات سفلية (_)",
|
81
83
|
"placeholder": "يفضل أن يكون بالكامل بحروف صغيرة، مثل openai، لن يمكن تعديله بعد الإنشاء",
|
82
84
|
"required": "يرجى إدخال معرف المزود",
|
83
85
|
"title": "معرف المزود"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Описание на доставчика"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Уникален идентификатор за доставчика на услуги, който не може да бъде променян след създаването му",
|
82
|
+
"format": "Може да съдържа само малки букви, тирета (-) и долни черти (_)",
|
81
83
|
"placeholder": "Препоръчително изцяло с малки букви, например openai, след създаването не може да се промени",
|
82
84
|
"required": "Моля, въведете ID на доставчика",
|
83
85
|
"title": "ID на доставчика"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Beschreibung des Anbieters"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Eindeutige Kennung des Anbieters, die nach der Erstellung nicht mehr geändert werden kann",
|
82
|
+
"format": "Darf nur aus Kleinbuchstaben, Bindestrichen (-) und Unterstrichen (_) bestehen",
|
81
83
|
"placeholder": "Empfohlen in Kleinbuchstaben, z.B. openai, nach der Erstellung nicht mehr änderbar",
|
82
84
|
"required": "Bitte geben Sie die Anbieter-ID ein",
|
83
85
|
"title": "Anbieter-ID"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Provider Description"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Unique identifier for the service provider, which cannot be modified after creation",
|
82
|
+
"format": "Can only contain lowercase letters, hyphens (-), and underscores (_) ",
|
81
83
|
"placeholder": "Suggested all lowercase, e.g., openai, cannot be modified after creation",
|
82
84
|
"required": "Please enter the provider ID",
|
83
85
|
"title": "Provider ID"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Descripción del proveedor"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Identificador único del proveedor de servicios, no se puede modificar una vez creado",
|
82
|
+
"format": "Solo puede contener letras minúsculas, guiones (-) y guiones bajos (_)",
|
81
83
|
"placeholder": "Se recomienda en minúsculas, por ejemplo openai, no se puede modificar después de crear",
|
82
84
|
"required": "Por favor, introduce el ID del proveedor",
|
83
85
|
"title": "ID del proveedor"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "توضیحات ارائهدهنده"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "به عنوان شناسه منحصر به فرد ارائهدهنده خدمات، پس از ایجاد قابل ویرایش نخواهد بود",
|
82
|
+
"format": "فقط میتواند شامل حروف کوچک، خط تیره (-) و زیرخط (_) باشد",
|
81
83
|
"placeholder": "توصیه میشود تماماً با حروف کوچک باشد، مانند openai، پس از ایجاد قابل ویرایش نخواهد بود",
|
82
84
|
"required": "لطفاً شناسه ارائهدهنده را وارد کنید",
|
83
85
|
"title": "شناسه ارائهدهنده"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Description du fournisseur"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Identifiant unique du fournisseur de services, qui ne peut pas être modifié après sa création",
|
82
|
+
"format": "Ne peut contenir que des lettres minuscules, des tirets (-) et des underscores (_) ",
|
81
83
|
"placeholder": "Utilisez uniquement des lettres minuscules, par exemple openai, non modifiable après création",
|
82
84
|
"required": "Veuillez entrer l'ID du fournisseur",
|
83
85
|
"title": "ID du fournisseur"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Descrizione del fornitore"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Identificatore unico del fornitore di servizi, non modificabile dopo la creazione",
|
82
|
+
"format": "Può contenere solo lettere minuscole, trattini (-) e underscore (_)",
|
81
83
|
"placeholder": "Si consiglia di utilizzare solo lettere minuscole, ad esempio openai, non modificabile dopo la creazione",
|
82
84
|
"required": "Inserisci l'ID del fornitore",
|
83
85
|
"title": "ID del fornitore"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "サービスプロバイダーの紹介"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "サービスプロバイダーの一意の識別子であり、作成後は変更できません",
|
82
|
+
"format": "小文字のアルファベット、ハイフン(-)、およびアンダースコア(_)のみを含むことができます",
|
81
83
|
"placeholder": "小文字で入力してください(例: openai)。作成後は変更できません",
|
82
84
|
"required": "サービスプロバイダー ID を入力してください",
|
83
85
|
"title": "サービスプロバイダー ID"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "서비스 제공자 소개"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "서비스 제공자의 고유 식별자로, 생성 후에는 수정할 수 없습니다.",
|
82
|
+
"format": "소문자, 하이픈(-), 및 언더스코어(_)만 포함할 수 있습니다.",
|
81
83
|
"placeholder": "소문자로 입력하세요, 예: openai, 생성 후 수정할 수 없습니다",
|
82
84
|
"required": "서비스 제공자 ID를 입력하세요",
|
83
85
|
"title": "서비스 제공자 ID"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Beschrijving van de provider"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Een unieke identificatie voor de dienstverlener, kan na creatie niet meer worden gewijzigd",
|
82
|
+
"format": "Mag alleen kleine letters, koppeltekens (-) en underscores (_) bevatten",
|
81
83
|
"placeholder": "Gebruik alleen kleine letters, bijvoorbeeld openai, kan niet worden gewijzigd na aanmaak",
|
82
84
|
"required": "Vul de provider ID in",
|
83
85
|
"title": "Provider ID"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Opis dostawcy usług"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Unikalny identyfikator dostawcy usług, po utworzeniu nie można go zmienić",
|
82
|
+
"format": "Może zawierać tylko małe litery, myślniki (-) i podkreślenia (_)",
|
81
83
|
"placeholder": "Zaleca się użycie małych liter, np. openai, po utworzeniu nie można edytować",
|
82
84
|
"required": "Proszę wpisać identyfikator dostawcy",
|
83
85
|
"title": "Identyfikator dostawcy"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Descrição do Provedor"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Identificador único do provedor de serviços, não pode ser modificado após a criação",
|
82
|
+
"format": "Pode conter apenas letras minúsculas, hífens (-) e sublinhados (_)",
|
81
83
|
"placeholder": "Sugestão: tudo em minúsculas, por exemplo, openai, não poderá ser modificado após a criação",
|
82
84
|
"required": "Por favor, insira o ID do provedor",
|
83
85
|
"title": "ID do Provedor"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Описание провайдера"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Уникальный идентификатор для поставщика услуг, который нельзя изменить после создания",
|
82
|
+
"format": "Может содержать только строчные буквы, дефисы (-) и подчеркивания (_)",
|
81
83
|
"placeholder": "Рекомендуется использовать строчные буквы, например, openai, после создания изменить нельзя",
|
82
84
|
"required": "Пожалуйста, введите ID провайдера",
|
83
85
|
"title": "ID провайдера"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Hizmet Sağlayıcı Tanımı"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Hizmet sağlayıcının benzersiz kimliği, oluşturulduktan sonra değiştirilemez",
|
82
|
+
"format": "Sadece küçük harfler, tire (-) ve alt çizgi (_) içerebilir",
|
81
83
|
"placeholder": "Küçük harflerle yazılması önerilir, örneğin openai, oluşturduktan sonra değiştirilemez",
|
82
84
|
"required": "Lütfen hizmet sağlayıcı ID'sini girin",
|
83
85
|
"title": "Hizmet Sağlayıcı ID"
|
@@ -78,6 +78,8 @@
|
|
78
78
|
"title": "Giới thiệu về nhà cung cấp"
|
79
79
|
},
|
80
80
|
"id": {
|
81
|
+
"desc": "Là định danh duy nhất của nhà cung cấp dịch vụ, không thể sửa đổi sau khi tạo",
|
82
|
+
"format": "Chỉ có thể chứa chữ cái thường, dấu gạch ngang (-) và dấu gạch dưới (_)",
|
81
83
|
"placeholder": "Nên viết toàn bộ bằng chữ thường, ví dụ openai, không thể sửa sau khi tạo",
|
82
84
|
"required": "Vui lòng nhập ID nhà cung cấp",
|
83
85
|
"title": "ID nhà cung cấp"
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.44.
|
3
|
+
"version": "1.44.2",
|
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",
|
@@ -43,10 +43,17 @@ const CreateNewProvider = memo<CreateNewProviderProps>(({ onClose, open }) => {
|
|
43
43
|
children: (
|
44
44
|
<Input autoFocus placeholder={t('createNewAiProvider.id.placeholder')} variant={'filled'} />
|
45
45
|
),
|
46
|
+
desc: t('createNewAiProvider.id.desc'),
|
46
47
|
label: t('createNewAiProvider.id.title'),
|
47
48
|
minWidth: 400,
|
48
49
|
name: 'id',
|
49
|
-
rules: [
|
50
|
+
rules: [
|
51
|
+
{ message: t('createNewAiProvider.id.required'), required: true },
|
52
|
+
{
|
53
|
+
message: t('createNewAiProvider.id.format'),
|
54
|
+
pattern: /^[_a-z-]+$/,
|
55
|
+
},
|
56
|
+
],
|
50
57
|
},
|
51
58
|
{
|
52
59
|
children: (
|
@@ -12,13 +12,9 @@ import { TraceNameMap } from '@/const/trace';
|
|
12
12
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
13
13
|
import { useProviderName } from '@/hooks/useProviderName';
|
14
14
|
import { chatService } from '@/services/chat';
|
15
|
+
import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
|
15
16
|
import { ChatMessageError } from '@/types/message';
|
16
17
|
|
17
|
-
interface ConnectionCheckerProps {
|
18
|
-
model: string;
|
19
|
-
provider: string;
|
20
|
-
}
|
21
|
-
|
22
18
|
const Error = memo<{ error: ChatMessageError }>(({ error }) => {
|
23
19
|
const { t } = useTranslation('error');
|
24
20
|
const providerName = useProviderName(error.body?.provider);
|
@@ -42,9 +38,16 @@ const Error = memo<{ error: ChatMessageError }>(({ error }) => {
|
|
42
38
|
);
|
43
39
|
});
|
44
40
|
|
41
|
+
interface ConnectionCheckerProps {
|
42
|
+
model: string;
|
43
|
+
provider: string;
|
44
|
+
}
|
45
|
+
|
45
46
|
const Checker = memo<ConnectionCheckerProps>(({ model, provider }) => {
|
46
47
|
const { t } = useTranslation('setting');
|
47
48
|
|
49
|
+
const disabled = useAiInfraStore(aiProviderSelectors.isProviderConfigUpdating(provider));
|
50
|
+
|
48
51
|
const [loading, setLoading] = useState(false);
|
49
52
|
const [pass, setPass] = useState(false);
|
50
53
|
|
@@ -108,7 +111,7 @@ const Checker = memo<ConnectionCheckerProps>(({ model, provider }) => {
|
|
108
111
|
{t('llm.checker.pass')}
|
109
112
|
</Flexbox>
|
110
113
|
)}
|
111
|
-
<Button loading={loading} onClick={checkConnection}>
|
114
|
+
<Button disabled={disabled} loading={loading} onClick={checkConnection}>
|
112
115
|
{t('llm.checker.button')}
|
113
116
|
</Button>
|
114
117
|
</Flexbox>
|
@@ -5,7 +5,7 @@ import { Avatar, Form, type FormItemProps, Icon, type ItemGroup, Tooltip } from
|
|
5
5
|
import { useDebounceFn } from 'ahooks';
|
6
6
|
import { Input, Skeleton, Switch } from 'antd';
|
7
7
|
import { createStyles } from 'antd-style';
|
8
|
-
import { LockIcon } from 'lucide-react';
|
8
|
+
import { Loader2Icon, LockIcon } from 'lucide-react';
|
9
9
|
import Link from 'next/link';
|
10
10
|
import { ReactNode, memo, useLayoutEffect } from 'react';
|
11
11
|
import { Trans, useTranslation } from 'react-i18next';
|
@@ -128,7 +128,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
128
128
|
} = settings;
|
129
129
|
const { t } = useTranslation('modelProvider');
|
130
130
|
const [form] = Form.useForm();
|
131
|
-
const { cx, styles } = useStyles();
|
131
|
+
const { cx, styles, theme } = useStyles();
|
132
132
|
|
133
133
|
const [
|
134
134
|
toggleProviderEnabled,
|
@@ -136,6 +136,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
136
136
|
updateAiProviderConfig,
|
137
137
|
enabled,
|
138
138
|
isLoading,
|
139
|
+
configUpdating,
|
139
140
|
isFetchOnClient,
|
140
141
|
isProviderEndpointNotEmpty,
|
141
142
|
isProviderApiKeyNotEmpty,
|
@@ -145,6 +146,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
145
146
|
s.updateAiProviderConfig,
|
146
147
|
aiProviderSelectors.isProviderEnabled(id)(s),
|
147
148
|
aiProviderSelectors.isAiProviderConfigLoading(id)(s),
|
149
|
+
aiProviderSelectors.isProviderConfigUpdating(id)(s),
|
148
150
|
aiProviderSelectors.isProviderFetchOnClient(id)(s),
|
149
151
|
aiProviderSelectors.isActiveProviderEndpointNotEmpty(s),
|
150
152
|
aiProviderSelectors.isActiveProviderApiKeyNotEmpty(s),
|
@@ -173,6 +175,11 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
173
175
|
<Input.Password
|
174
176
|
autoComplete={'new-password'}
|
175
177
|
placeholder={t(`providerModels.config.apiKey.placeholder`, { name })}
|
178
|
+
suffix={
|
179
|
+
configUpdating && (
|
180
|
+
<Icon icon={Loader2Icon} spin style={{ color: theme.colorTextTertiary }} />
|
181
|
+
)
|
182
|
+
}
|
176
183
|
/>
|
177
184
|
),
|
178
185
|
desc: t(`providerModels.config.apiKey.desc`, { name }),
|
@@ -211,6 +218,11 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
211
218
|
(!!proxyUrl && proxyUrl?.placeholder) ||
|
212
219
|
t('providerModels.config.baseURL.placeholder')
|
213
220
|
}
|
221
|
+
suffix={
|
222
|
+
configUpdating && (
|
223
|
+
<Icon icon={Loader2Icon} spin style={{ color: theme.colorTextTertiary }} />
|
224
|
+
)
|
225
|
+
}
|
214
226
|
/>
|
215
227
|
),
|
216
228
|
desc: (!!proxyUrl && proxyUrl?.desc) || t('providerModels.config.baseURL.desc'),
|
@@ -235,7 +247,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
235
247
|
children: isLoading ? (
|
236
248
|
<Skeleton.Button active className={styles.switchLoading} />
|
237
249
|
) : (
|
238
|
-
<Switch disabled={
|
250
|
+
<Switch disabled={configUpdating} value={isFetchOnClient} />
|
239
251
|
),
|
240
252
|
desc: t('providerModels.config.fetchOnClient.desc'),
|
241
253
|
label: t('providerModels.config.fetchOnClient.title'),
|
@@ -303,19 +303,6 @@ const siliconcloudChatModels: AIChatModelCard[] = [
|
|
303
303
|
},
|
304
304
|
type: 'chat',
|
305
305
|
},
|
306
|
-
{
|
307
|
-
contextWindowTokens: 32_768,
|
308
|
-
description:
|
309
|
-
'Qwen2-72B-Instruct 是 Qwen2 系列中的指令微调大语言模型,参数规模为 72B。该模型基于 Transformer 架构,采用了 SwiGLU 激活函数、注意力 QKV 偏置和组查询注意力等技术。它能够处理大规模输入。该模型在语言理解、生成、多语言能力、编码、数学和推理等多个基准测试中表现出色,超越了大多数开源模型,并在某些任务上展现出与专有模型相当的竞争力',
|
310
|
-
displayName: 'Qwen2 72B Instruct',
|
311
|
-
id: 'Qwen/Qwen2-7B-Instruct',
|
312
|
-
pricing: {
|
313
|
-
currency: 'CNY',
|
314
|
-
input: 4.13,
|
315
|
-
output: 4.13,
|
316
|
-
},
|
317
|
-
type: 'chat',
|
318
|
-
},
|
319
306
|
{
|
320
307
|
contextWindowTokens: 32_768,
|
321
308
|
description:
|
@@ -28,6 +28,7 @@ enum AiProviderSwrKey {
|
|
28
28
|
export interface AiProviderAction {
|
29
29
|
createNewAiProvider: (params: CreateAiProviderParams) => Promise<void>;
|
30
30
|
deleteAiProvider: (id: string) => Promise<void>;
|
31
|
+
internal_toggleAiProviderConfigUpdating: (id: string, loading: boolean) => void;
|
31
32
|
internal_toggleAiProviderLoading: (id: string, loading: boolean) => void;
|
32
33
|
refreshAiProviderDetail: () => Promise<void>;
|
33
34
|
refreshAiProviderList: () => Promise<void>;
|
@@ -64,6 +65,20 @@ export const createAiProviderSlice: StateCreator<
|
|
64
65
|
|
65
66
|
await get().refreshAiProviderList();
|
66
67
|
},
|
68
|
+
internal_toggleAiProviderConfigUpdating: (id, loading) => {
|
69
|
+
set(
|
70
|
+
(state) => {
|
71
|
+
if (loading)
|
72
|
+
return { aiProviderConfigUpdatingIds: [...state.aiProviderConfigUpdatingIds, id] };
|
73
|
+
|
74
|
+
return {
|
75
|
+
aiProviderConfigUpdatingIds: state.aiProviderConfigUpdatingIds.filter((i) => i !== id),
|
76
|
+
};
|
77
|
+
},
|
78
|
+
false,
|
79
|
+
'toggleAiProviderLoading',
|
80
|
+
);
|
81
|
+
},
|
67
82
|
internal_toggleAiProviderLoading: (id, loading) => {
|
68
83
|
set(
|
69
84
|
(state) => {
|
@@ -109,11 +124,11 @@ export const createAiProviderSlice: StateCreator<
|
|
109
124
|
},
|
110
125
|
|
111
126
|
updateAiProviderConfig: async (id, value) => {
|
112
|
-
get().
|
127
|
+
get().internal_toggleAiProviderConfigUpdating(id, true);
|
113
128
|
await aiProviderService.updateAiProviderConfig(id, value);
|
114
129
|
await get().refreshAiProviderDetail();
|
115
130
|
|
116
|
-
get().
|
131
|
+
get().internal_toggleAiProviderConfigUpdating(id, false);
|
117
132
|
},
|
118
133
|
|
119
134
|
updateAiProviderSort: async (items) => {
|
@@ -10,6 +10,7 @@ import {
|
|
10
10
|
export interface AIProviderState {
|
11
11
|
activeAiProvider?: string;
|
12
12
|
activeProviderModelList: any[];
|
13
|
+
aiProviderConfigUpdatingIds: string[];
|
13
14
|
aiProviderDetail?: AiProviderDetailItem | null;
|
14
15
|
aiProviderList: AiProviderListItem[];
|
15
16
|
aiProviderLoadingIds: string[];
|
@@ -24,6 +25,7 @@ export interface AIProviderState {
|
|
24
25
|
|
25
26
|
export const initialAIProviderState: AIProviderState = {
|
26
27
|
activeProviderModelList: [],
|
28
|
+
aiProviderConfigUpdatingIds: [],
|
27
29
|
aiProviderList: [],
|
28
30
|
aiProviderLoadingIds: [],
|
29
31
|
aiProviderRuntimeConfig: {},
|
@@ -84,6 +84,9 @@ const providerConfigById =
|
|
84
84
|
return s.aiProviderRuntimeConfig?.[id];
|
85
85
|
};
|
86
86
|
|
87
|
+
const isProviderConfigUpdating = (id: string) => (s: AIProviderStoreState) =>
|
88
|
+
s.aiProviderConfigUpdatingIds.includes(id);
|
89
|
+
|
87
90
|
export const aiProviderSelectors = {
|
88
91
|
activeProviderConfig,
|
89
92
|
disabledAiProviderList,
|
@@ -91,6 +94,7 @@ export const aiProviderSelectors = {
|
|
91
94
|
isActiveProviderApiKeyNotEmpty,
|
92
95
|
isActiveProviderEndpointNotEmpty,
|
93
96
|
isAiProviderConfigLoading,
|
97
|
+
isProviderConfigUpdating,
|
94
98
|
isProviderEnabled,
|
95
99
|
isProviderFetchOnClient,
|
96
100
|
isProviderLoading,
|