Skip to content

Commit

Permalink
🐛 fix: add provider id validate (#5336)
Browse files Browse the repository at this point in the history
* fix loading issue

* fix provider id issue
  • Loading branch information
arvinxx authored Jan 8, 2025
1 parent 0578d6d commit 7f8a1b6
Show file tree
Hide file tree
Showing 26 changed files with 95 additions and 27 deletions.
2 changes: 2 additions & 0 deletions locales/ar/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "نبذة عن مزود الخدمة"
},
"id": {
"desc": "معرف فريد لمزود الخدمة، لا يمكن تعديله بعد الإنشاء",
"format": "يمكن أن يحتوي فقط على أحرف صغيرة، وشرطات (-) وشرطات سفلية (_)",
"placeholder": "يفضل أن يكون بالكامل بحروف صغيرة، مثل openai، لن يمكن تعديله بعد الإنشاء",
"required": "يرجى إدخال معرف المزود",
"title": "معرف المزود"
Expand Down
2 changes: 2 additions & 0 deletions locales/bg-BG/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Описание на доставчика"
},
"id": {
"desc": "Уникален идентификатор за доставчика на услуги, който не може да бъде променян след създаването му",
"format": "Може да съдържа само малки букви, тирета (-) и долни черти (_)",
"placeholder": "Препоръчително изцяло с малки букви, например openai, след създаването не може да се промени",
"required": "Моля, въведете ID на доставчика",
"title": "ID на доставчика"
Expand Down
2 changes: 2 additions & 0 deletions locales/de-DE/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Beschreibung des Anbieters"
},
"id": {
"desc": "Eindeutige Kennung des Anbieters, die nach der Erstellung nicht mehr geändert werden kann",
"format": "Darf nur aus Kleinbuchstaben, Bindestrichen (-) und Unterstrichen (_) bestehen",
"placeholder": "Empfohlen in Kleinbuchstaben, z.B. openai, nach der Erstellung nicht mehr änderbar",
"required": "Bitte geben Sie die Anbieter-ID ein",
"title": "Anbieter-ID"
Expand Down
2 changes: 2 additions & 0 deletions locales/en-US/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Provider Description"
},
"id": {
"desc": "Unique identifier for the service provider, which cannot be modified after creation",
"format": "Can only contain lowercase letters, hyphens (-), and underscores (_) ",
"placeholder": "Suggested all lowercase, e.g., openai, cannot be modified after creation",
"required": "Please enter the provider ID",
"title": "Provider ID"
Expand Down
2 changes: 2 additions & 0 deletions locales/es-ES/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Descripción del proveedor"
},
"id": {
"desc": "Identificador único del proveedor de servicios, no se puede modificar una vez creado",
"format": "Solo puede contener letras minúsculas, guiones (-) y guiones bajos (_)",
"placeholder": "Se recomienda en minúsculas, por ejemplo openai, no se puede modificar después de crear",
"required": "Por favor, introduce el ID del proveedor",
"title": "ID del proveedor"
Expand Down
2 changes: 2 additions & 0 deletions locales/fa-IR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "توضیحات ارائه‌دهنده"
},
"id": {
"desc": "به عنوان شناسه منحصر به فرد ارائه‌دهنده خدمات، پس از ایجاد قابل ویرایش نخواهد بود",
"format": "فقط می‌تواند شامل حروف کوچک، خط تیره (-) و زیرخط (_) باشد",
"placeholder": "توصیه می‌شود تماماً با حروف کوچک باشد، مانند openai، پس از ایجاد قابل ویرایش نخواهد بود",
"required": "لطفاً شناسه ارائه‌دهنده را وارد کنید",
"title": "شناسه ارائه‌دهنده"
Expand Down
2 changes: 2 additions & 0 deletions locales/fr-FR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Description du fournisseur"
},
"id": {
"desc": "Identifiant unique du fournisseur de services, qui ne peut pas être modifié après sa création",
"format": "Ne peut contenir que des lettres minuscules, des tirets (-) et des underscores (_) ",
"placeholder": "Utilisez uniquement des lettres minuscules, par exemple openai, non modifiable après création",
"required": "Veuillez entrer l'ID du fournisseur",
"title": "ID du fournisseur"
Expand Down
2 changes: 2 additions & 0 deletions locales/it-IT/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Descrizione del fornitore"
},
"id": {
"desc": "Identificatore unico del fornitore di servizi, non modificabile dopo la creazione",
"format": "Può contenere solo lettere minuscole, trattini (-) e underscore (_)",
"placeholder": "Si consiglia di utilizzare solo lettere minuscole, ad esempio openai, non modificabile dopo la creazione",
"required": "Inserisci l'ID del fornitore",
"title": "ID del fornitore"
Expand Down
2 changes: 2 additions & 0 deletions locales/ja-JP/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "サービスプロバイダーの紹介"
},
"id": {
"desc": "サービスプロバイダーの一意の識別子であり、作成後は変更できません",
"format": "小文字のアルファベット、ハイフン(-)、およびアンダースコア(_)のみを含むことができます",
"placeholder": "小文字で入力してください(例: openai)。作成後は変更できません",
"required": "サービスプロバイダー ID を入力してください",
"title": "サービスプロバイダー ID"
Expand Down
2 changes: 2 additions & 0 deletions locales/ko-KR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "서비스 제공자 소개"
},
"id": {
"desc": "서비스 제공자의 고유 식별자로, 생성 후에는 수정할 수 없습니다.",
"format": "소문자, 하이픈(-), 및 언더스코어(_)만 포함할 수 있습니다.",
"placeholder": "소문자로 입력하세요, 예: openai, 생성 후 수정할 수 없습니다",
"required": "서비스 제공자 ID를 입력하세요",
"title": "서비스 제공자 ID"
Expand Down
2 changes: 2 additions & 0 deletions locales/nl-NL/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Beschrijving van de provider"
},
"id": {
"desc": "Een unieke identificatie voor de dienstverlener, kan na creatie niet meer worden gewijzigd",
"format": "Mag alleen kleine letters, koppeltekens (-) en underscores (_) bevatten",
"placeholder": "Gebruik alleen kleine letters, bijvoorbeeld openai, kan niet worden gewijzigd na aanmaak",
"required": "Vul de provider ID in",
"title": "Provider ID"
Expand Down
2 changes: 2 additions & 0 deletions locales/pl-PL/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Opis dostawcy usług"
},
"id": {
"desc": "Unikalny identyfikator dostawcy usług, po utworzeniu nie można go zmienić",
"format": "Może zawierać tylko małe litery, myślniki (-) i podkreślenia (_)",
"placeholder": "Zaleca się użycie małych liter, np. openai, po utworzeniu nie można edytować",
"required": "Proszę wpisać identyfikator dostawcy",
"title": "Identyfikator dostawcy"
Expand Down
2 changes: 2 additions & 0 deletions locales/pt-BR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Descrição do Provedor"
},
"id": {
"desc": "Identificador único do provedor de serviços, não pode ser modificado após a criação",
"format": "Pode conter apenas letras minúsculas, hífens (-) e sublinhados (_)",
"placeholder": "Sugestão: tudo em minúsculas, por exemplo, openai, não poderá ser modificado após a criação",
"required": "Por favor, insira o ID do provedor",
"title": "ID do Provedor"
Expand Down
2 changes: 2 additions & 0 deletions locales/ru-RU/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Описание провайдера"
},
"id": {
"desc": "Уникальный идентификатор для поставщика услуг, который нельзя изменить после создания",
"format": "Может содержать только строчные буквы, дефисы (-) и подчеркивания (_)",
"placeholder": "Рекомендуется использовать строчные буквы, например, openai, после создания изменить нельзя",
"required": "Пожалуйста, введите ID провайдера",
"title": "ID провайдера"
Expand Down
2 changes: 2 additions & 0 deletions locales/tr-TR/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Hizmet Sağlayıcı Tanımı"
},
"id": {
"desc": "Hizmet sağlayıcının benzersiz kimliği, oluşturulduktan sonra değiştirilemez",
"format": "Sadece küçük harfler, tire (-) ve alt çizgi (_) içerebilir",
"placeholder": "Küçük harflerle yazılması önerilir, örneğin openai, oluşturduktan sonra değiştirilemez",
"required": "Lütfen hizmet sağlayıcı ID'sini girin",
"title": "Hizmet Sağlayıcı ID"
Expand Down
2 changes: 2 additions & 0 deletions locales/vi-VN/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "Giới thiệu về nhà cung cấp"
},
"id": {
"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",
"format": "Chỉ có thể chứa chữ cái thường, dấu gạch ngang (-) và dấu gạch dưới (_)",
"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",
"required": "Vui lòng nhập ID nhà cung cấp",
"title": "ID nhà cung cấp"
Expand Down
4 changes: 3 additions & 1 deletion locales/zh-CN/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@
"title": "服务商简介"
},
"id": {
"placeholder": "建议全小写,例如 openai,创建后将不可修改",
"desc": "作为服务商唯一标识,创建后将不可修改",
"format": "只能包含小写字母、连字符(-)和下划线(_)",
"placeholder": "例如 openai、gemini 等",
"required": "请填写服务商 ID",
"title": "服务商 ID"
},
Expand Down
2 changes: 2 additions & 0 deletions locales/zh-TW/modelProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"title": "服務商簡介"
},
"id": {
"desc": "作為服務商唯一標識,創建後將不可修改",
"format": "只能包含小寫字母、連字符(-)和下劃線(_)",
"placeholder": "建議全小寫,例如 openai,創建後將不可修改",
"required": "請填寫服務商 ID",
"title": "服務商 ID"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,17 @@ const CreateNewProvider = memo<CreateNewProviderProps>(({ onClose, open }) => {
children: (
<Input autoFocus placeholder={t('createNewAiProvider.id.placeholder')} variant={'filled'} />
),
desc: t('createNewAiProvider.id.desc'),
label: t('createNewAiProvider.id.title'),
minWidth: 400,
name: 'id',
rules: [{ message: t('createNewAiProvider.id.required'), required: true }],
rules: [
{ message: t('createNewAiProvider.id.required'), required: true },
{
message: t('createNewAiProvider.id.format'),
pattern: /^[_a-z-]+$/,
},
],
},
{
children: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,9 @@ import { TraceNameMap } from '@/const/trace';
import { useIsMobile } from '@/hooks/useIsMobile';
import { useProviderName } from '@/hooks/useProviderName';
import { chatService } from '@/services/chat';
import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
import { ChatMessageError } from '@/types/message';

interface ConnectionCheckerProps {
model: string;
provider: string;
}

const Error = memo<{ error: ChatMessageError }>(({ error }) => {
const { t } = useTranslation('error');
const providerName = useProviderName(error.body?.provider);
Expand All @@ -42,9 +38,16 @@ const Error = memo<{ error: ChatMessageError }>(({ error }) => {
);
});

interface ConnectionCheckerProps {
model: string;
provider: string;
}

const Checker = memo<ConnectionCheckerProps>(({ model, provider }) => {
const { t } = useTranslation('setting');

const disabled = useAiInfraStore(aiProviderSelectors.isProviderConfigUpdating(provider));

const [loading, setLoading] = useState(false);
const [pass, setPass] = useState(false);

Expand Down Expand Up @@ -108,7 +111,7 @@ const Checker = memo<ConnectionCheckerProps>(({ model, provider }) => {
{t('llm.checker.pass')}
</Flexbox>
)}
<Button loading={loading} onClick={checkConnection}>
<Button disabled={disabled} loading={loading} onClick={checkConnection}>
{t('llm.checker.button')}
</Button>
</Flexbox>
Expand Down
18 changes: 15 additions & 3 deletions src/app/(main)/settings/provider/features/ProviderConfig/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Avatar, Form, type FormItemProps, Icon, type ItemGroup, Tooltip } from
import { useDebounceFn } from 'ahooks';
import { Input, Skeleton, Switch } from 'antd';
import { createStyles } from 'antd-style';
import { LockIcon } from 'lucide-react';
import { Loader2Icon, LockIcon } from 'lucide-react';
import Link from 'next/link';
import { ReactNode, memo, useLayoutEffect } from 'react';
import { Trans, useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -128,14 +128,15 @@ const ProviderConfig = memo<ProviderConfigProps>(
} = settings;
const { t } = useTranslation('modelProvider');
const [form] = Form.useForm();
const { cx, styles } = useStyles();
const { cx, styles, theme } = useStyles();

const [
toggleProviderEnabled,
useFetchAiProviderItem,
updateAiProviderConfig,
enabled,
isLoading,
configUpdating,
isFetchOnClient,
isProviderEndpointNotEmpty,
isProviderApiKeyNotEmpty,
Expand All @@ -145,6 +146,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
s.updateAiProviderConfig,
aiProviderSelectors.isProviderEnabled(id)(s),
aiProviderSelectors.isAiProviderConfigLoading(id)(s),
aiProviderSelectors.isProviderConfigUpdating(id)(s),
aiProviderSelectors.isProviderFetchOnClient(id)(s),
aiProviderSelectors.isActiveProviderEndpointNotEmpty(s),
aiProviderSelectors.isActiveProviderApiKeyNotEmpty(s),
Expand Down Expand Up @@ -173,6 +175,11 @@ const ProviderConfig = memo<ProviderConfigProps>(
<Input.Password
autoComplete={'new-password'}
placeholder={t(`providerModels.config.apiKey.placeholder`, { name })}
suffix={
configUpdating && (
<Icon icon={Loader2Icon} spin style={{ color: theme.colorTextTertiary }} />
)
}
/>
),
desc: t(`providerModels.config.apiKey.desc`, { name }),
Expand Down Expand Up @@ -211,6 +218,11 @@ const ProviderConfig = memo<ProviderConfigProps>(
(!!proxyUrl && proxyUrl?.placeholder) ||
t('providerModels.config.baseURL.placeholder')
}
suffix={
configUpdating && (
<Icon icon={Loader2Icon} spin style={{ color: theme.colorTextTertiary }} />
)
}
/>
),
desc: (!!proxyUrl && proxyUrl?.desc) || t('providerModels.config.baseURL.desc'),
Expand All @@ -235,7 +247,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
children: isLoading ? (
<Skeleton.Button active className={styles.switchLoading} />
) : (
<Switch disabled={isLoading} value={isFetchOnClient} />
<Switch disabled={configUpdating} value={isFetchOnClient} />
),
desc: t('providerModels.config.fetchOnClient.desc'),
label: t('providerModels.config.fetchOnClient.title'),
Expand Down
13 changes: 0 additions & 13 deletions src/config/aiModels/siliconcloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,19 +303,6 @@ const siliconcloudChatModels: AIChatModelCard[] = [
},
type: 'chat',
},
{
contextWindowTokens: 32_768,
description:
'Qwen2-72B-Instruct 是 Qwen2 系列中的指令微调大语言模型,参数规模为 72B。该模型基于 Transformer 架构,采用了 SwiGLU 激活函数、注意力 QKV 偏置和组查询注意力等技术。它能够处理大规模输入。该模型在语言理解、生成、多语言能力、编码、数学和推理等多个基准测试中表现出色,超越了大多数开源模型,并在某些任务上展现出与专有模型相当的竞争力',
displayName: 'Qwen2 72B Instruct',
id: 'Qwen/Qwen2-7B-Instruct',
pricing: {
currency: 'CNY',
input: 4.13,
output: 4.13,
},
type: 'chat',
},
{
contextWindowTokens: 32_768,
description:
Expand Down
4 changes: 3 additions & 1 deletion src/locales/default/modelProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ export default {
title: '服务商简介',
},
id: {
placeholder: '建议全小写,例如 openai,创建后将不可修改',
desc: '作为服务商唯一标识,创建后将不可修改',
format: '只能包含小写字母、连字符(-)和下划线(_)',
placeholder: '例如 openai、gemini 等',
required: '请填写服务商 ID',
title: '服务商 ID',
},
Expand Down
19 changes: 17 additions & 2 deletions src/store/aiInfra/slices/aiProvider/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum AiProviderSwrKey {
export interface AiProviderAction {
createNewAiProvider: (params: CreateAiProviderParams) => Promise<void>;
deleteAiProvider: (id: string) => Promise<void>;
internal_toggleAiProviderConfigUpdating: (id: string, loading: boolean) => void;
internal_toggleAiProviderLoading: (id: string, loading: boolean) => void;
refreshAiProviderDetail: () => Promise<void>;
refreshAiProviderList: () => Promise<void>;
Expand Down Expand Up @@ -64,6 +65,20 @@ export const createAiProviderSlice: StateCreator<

await get().refreshAiProviderList();
},
internal_toggleAiProviderConfigUpdating: (id, loading) => {
set(
(state) => {
if (loading)
return { aiProviderConfigUpdatingIds: [...state.aiProviderConfigUpdatingIds, id] };

return {
aiProviderConfigUpdatingIds: state.aiProviderConfigUpdatingIds.filter((i) => i !== id),
};
},
false,
'toggleAiProviderLoading',
);
},
internal_toggleAiProviderLoading: (id, loading) => {
set(
(state) => {
Expand Down Expand Up @@ -109,11 +124,11 @@ export const createAiProviderSlice: StateCreator<
},

updateAiProviderConfig: async (id, value) => {
get().internal_toggleAiProviderLoading(id, true);
get().internal_toggleAiProviderConfigUpdating(id, true);
await aiProviderService.updateAiProviderConfig(id, value);
await get().refreshAiProviderDetail();

get().internal_toggleAiProviderLoading(id, false);
get().internal_toggleAiProviderConfigUpdating(id, false);
},

updateAiProviderSort: async (items) => {
Expand Down
2 changes: 2 additions & 0 deletions src/store/aiInfra/slices/aiProvider/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
export interface AIProviderState {
activeAiProvider?: string;
activeProviderModelList: any[];
aiProviderConfigUpdatingIds: string[];
aiProviderDetail?: AiProviderDetailItem | null;
aiProviderList: AiProviderListItem[];
aiProviderLoadingIds: string[];
Expand All @@ -24,6 +25,7 @@ export interface AIProviderState {

export const initialAIProviderState: AIProviderState = {
activeProviderModelList: [],
aiProviderConfigUpdatingIds: [],
aiProviderList: [],
aiProviderLoadingIds: [],
aiProviderRuntimeConfig: {},
Expand Down
4 changes: 4 additions & 0 deletions src/store/aiInfra/slices/aiProvider/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,17 @@ const providerConfigById =
return s.aiProviderRuntimeConfig?.[id];
};

const isProviderConfigUpdating = (id: string) => (s: AIProviderStoreState) =>
s.aiProviderConfigUpdatingIds.includes(id);

export const aiProviderSelectors = {
activeProviderConfig,
disabledAiProviderList,
enabledAiProviderList,
isActiveProviderApiKeyNotEmpty,
isActiveProviderEndpointNotEmpty,
isAiProviderConfigLoading,
isProviderConfigUpdating,
isProviderEnabled,
isProviderFetchOnClient,
isProviderLoading,
Expand Down

0 comments on commit 7f8a1b6

Please sign in to comment.