@lobehub/lobehub 2.0.0-next.2 → 2.0.0-next.4

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 (50) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/changelog/v1.json +18 -0
  3. package/locales/ar/models.json +9 -0
  4. package/locales/bg-BG/models.json +9 -0
  5. package/locales/de-DE/models.json +9 -0
  6. package/locales/en-US/models.json +9 -0
  7. package/locales/es-ES/models.json +9 -0
  8. package/locales/fa-IR/models.json +9 -0
  9. package/locales/fr-FR/models.json +9 -0
  10. package/locales/it-IT/models.json +9 -0
  11. package/locales/ja-JP/models.json +9 -0
  12. package/locales/ko-KR/models.json +9 -0
  13. package/locales/nl-NL/models.json +9 -0
  14. package/locales/pl-PL/models.json +9 -0
  15. package/locales/pt-BR/models.json +9 -0
  16. package/locales/ru-RU/models.json +9 -0
  17. package/locales/tr-TR/models.json +9 -0
  18. package/locales/vi-VN/models.json +9 -0
  19. package/locales/zh-CN/models.json +9 -0
  20. package/locales/zh-TW/models.json +9 -0
  21. package/package.json +1 -1
  22. package/packages/const/src/models.ts +13 -0
  23. package/packages/model-bank/src/aiModels/azure.ts +155 -0
  24. package/packages/model-bank/src/aiModels/bedrock.ts +44 -0
  25. package/packages/model-runtime/src/core/parameterResolver.ts +3 -0
  26. package/packages/model-runtime/src/providers/azureOpenai/index.ts +2 -1
  27. package/src/app/[variants]/(main)/settings/_layout/SettingsContent.tsx +0 -3
  28. package/src/libs/next-auth/sso-providers/index.ts +0 -2
  29. package/src/libs/oidc-provider/provider.ts +1 -1
  30. package/src/app/[variants]/(main)/settings/llm/ProviderList/Azure/index.tsx +0 -93
  31. package/src/app/[variants]/(main)/settings/llm/ProviderList/Bedrock/index.tsx +0 -70
  32. package/src/app/[variants]/(main)/settings/llm/ProviderList/Cloudflare/index.tsx +0 -39
  33. package/src/app/[variants]/(main)/settings/llm/ProviderList/Github/index.tsx +0 -52
  34. package/src/app/[variants]/(main)/settings/llm/ProviderList/HuggingFace/index.tsx +0 -52
  35. package/src/app/[variants]/(main)/settings/llm/ProviderList/Ollama/index.tsx +0 -20
  36. package/src/app/[variants]/(main)/settings/llm/ProviderList/OpenAI/index.tsx +0 -17
  37. package/src/app/[variants]/(main)/settings/llm/ProviderList/providers.tsx +0 -132
  38. package/src/app/[variants]/(main)/settings/llm/components/Checker.tsx +0 -118
  39. package/src/app/[variants]/(main)/settings/llm/components/ProviderConfig/index.tsx +0 -303
  40. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/CustomModelOption.tsx +0 -98
  41. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelConfigModal/Form.tsx +0 -104
  42. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelConfigModal/index.tsx +0 -77
  43. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelFetcher.tsx +0 -105
  44. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/Option.tsx +0 -68
  45. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/index.tsx +0 -146
  46. package/src/app/[variants]/(main)/settings/llm/const.ts +0 -20
  47. package/src/app/[variants]/(main)/settings/llm/features/Footer.tsx +0 -35
  48. package/src/app/[variants]/(main)/settings/llm/index.tsx +0 -30
  49. package/src/app/[variants]/(main)/settings/llm/type.ts +0 -5
  50. package/src/libs/next-auth/sso-providers/azure-ad.ts +0 -33
@@ -1,132 +0,0 @@
1
- import { useMemo } from 'react';
2
-
3
- import {
4
- Ai21ProviderCard,
5
- Ai302ProviderCard,
6
- Ai360ProviderCard,
7
- AkashChatProviderCard,
8
- AnthropicProviderCard,
9
- BaichuanProviderCard,
10
- CohereProviderCard,
11
- DeepSeekProviderCard,
12
- FireworksAIProviderCard,
13
- GiteeAIProviderCard,
14
- GoogleProviderCard,
15
- GroqProviderCard,
16
- HigressProviderCard,
17
- HunyuanProviderCard,
18
- InfiniAIProviderCard,
19
- InternLMProviderCard,
20
- JinaProviderCard,
21
- MinimaxProviderCard,
22
- MistralProviderCard,
23
- MoonshotProviderCard,
24
- NovitaProviderCard,
25
- NvidiaProviderCard,
26
- OllamaCloudProviderCard,
27
- OpenRouterProviderCard,
28
- PPIOProviderCard,
29
- PerplexityProviderCard,
30
- QiniuProviderCard,
31
- QwenProviderCard,
32
- SambaNovaProviderCard,
33
- Search1APIProviderCard,
34
- SenseNovaProviderCard,
35
- SiliconCloudProviderCard,
36
- SparkProviderCard,
37
- StepfunProviderCard,
38
- TaichuProviderCard,
39
- TogetherAIProviderCard,
40
- UpstageProviderCard,
41
- V0ProviderCard,
42
- VLLMProviderCard,
43
- WenxinProviderCard,
44
- XAIProviderCard,
45
- XinferenceProviderCard,
46
- ZeroOneProviderCard,
47
- ZhiPuProviderCard,
48
- } from '@/config/modelProviders';
49
-
50
- import { ProviderItem } from '../type';
51
- import { useAzureProvider } from './Azure';
52
- import { useBedrockProvider } from './Bedrock';
53
- import { useCloudflareProvider } from './Cloudflare';
54
- import { useGithubProvider } from './Github';
55
- import { useHuggingFaceProvider } from './HuggingFace';
56
- import { useOllamaProvider } from './Ollama';
57
- import { useOpenAIProvider } from './OpenAI';
58
-
59
- export const useProviderList = (): ProviderItem[] => {
60
- const AzureProvider = useAzureProvider();
61
- const OllamaProvider = useOllamaProvider();
62
- const OpenAIProvider = useOpenAIProvider();
63
- const BedrockProvider = useBedrockProvider();
64
- const CloudflareProvider = useCloudflareProvider();
65
- const GithubProvider = useGithubProvider();
66
- const HuggingFaceProvider = useHuggingFaceProvider();
67
-
68
- return useMemo(
69
- () => [
70
- OpenAIProvider,
71
- AzureProvider,
72
- OllamaProvider,
73
- VLLMProviderCard,
74
- XinferenceProviderCard,
75
- AnthropicProviderCard,
76
- BedrockProvider,
77
- GoogleProviderCard,
78
- DeepSeekProviderCard,
79
- HuggingFaceProvider,
80
- OpenRouterProviderCard,
81
- CloudflareProvider,
82
- GithubProvider,
83
- NovitaProviderCard,
84
- TogetherAIProviderCard,
85
- FireworksAIProviderCard,
86
- GroqProviderCard,
87
- NvidiaProviderCard,
88
- PerplexityProviderCard,
89
- MistralProviderCard,
90
- Ai21ProviderCard,
91
- UpstageProviderCard,
92
- XAIProviderCard,
93
- JinaProviderCard,
94
- SambaNovaProviderCard,
95
- Search1APIProviderCard,
96
- CohereProviderCard,
97
- V0ProviderCard,
98
- QiniuProviderCard,
99
- QwenProviderCard,
100
- WenxinProviderCard,
101
- HunyuanProviderCard,
102
- SparkProviderCard,
103
- ZhiPuProviderCard,
104
- ZeroOneProviderCard,
105
- SenseNovaProviderCard,
106
- StepfunProviderCard,
107
- MoonshotProviderCard,
108
- BaichuanProviderCard,
109
- MinimaxProviderCard,
110
- Ai360ProviderCard,
111
- TaichuProviderCard,
112
- InternLMProviderCard,
113
- SiliconCloudProviderCard,
114
- HigressProviderCard,
115
- GiteeAIProviderCard,
116
- PPIOProviderCard,
117
- InfiniAIProviderCard,
118
- AkashChatProviderCard,
119
- Ai302ProviderCard,
120
- OllamaCloudProviderCard,
121
- ],
122
- [
123
- AzureProvider,
124
- OllamaProvider,
125
- OpenAIProvider,
126
- BedrockProvider,
127
- CloudflareProvider,
128
- GithubProvider,
129
- HuggingFaceProvider,
130
- ],
131
- );
132
- };
@@ -1,118 +0,0 @@
1
- 'use client';
2
-
3
- import { CheckCircleFilled } from '@ant-design/icons';
4
- import { ChatMessageError, TraceNameMap } from '@lobechat/types';
5
- import { Alert, Button, Highlighter } from '@lobehub/ui';
6
- import { useTheme } from 'antd-style';
7
- import { memo, useState } from 'react';
8
- import { useTranslation } from 'react-i18next';
9
- import { Flexbox } from 'react-layout-kit';
10
-
11
- import { useIsMobile } from '@/hooks/useIsMobile';
12
- import { useProviderName } from '@/hooks/useProviderName';
13
- import { chatService } from '@/services/chat';
14
-
15
- interface ConnectionCheckerProps {
16
- model: string;
17
- provider: string;
18
- }
19
-
20
- const Error = memo<{ error: ChatMessageError }>(({ error }) => {
21
- const { t } = useTranslation('error');
22
- const providerName = useProviderName(error.body?.provider);
23
-
24
- return (
25
- <Flexbox gap={8} style={{ maxWidth: '600px', width: '100%' }}>
26
- <Alert
27
- banner
28
- extra={
29
- <Flexbox>
30
- <Highlighter actionIconSize={'small'} language={'json'} variant={'borderless'}>
31
- {JSON.stringify(error.body || error, null, 2)}
32
- </Highlighter>
33
- </Flexbox>
34
- }
35
- message={t(`response.${error.type}` as any, { provider: providerName })}
36
- showIcon
37
- type={'error'}
38
- />
39
- </Flexbox>
40
- );
41
- });
42
-
43
- const Checker = memo<ConnectionCheckerProps>(({ model, provider }) => {
44
- const { t } = useTranslation('setting');
45
-
46
- const [loading, setLoading] = useState(false);
47
- const [pass, setPass] = useState(false);
48
-
49
- const theme = useTheme();
50
- const [error, setError] = useState<ChatMessageError | undefined>();
51
-
52
- const checkConnection = async () => {
53
- let isError = false;
54
-
55
- await chatService.fetchPresetTaskResult({
56
- onError: (_, rawError) => {
57
- setError(rawError);
58
- setPass(false);
59
- isError = true;
60
- },
61
- onFinish: async (value) => {
62
- if (!isError && value) {
63
- setError(undefined);
64
- setPass(true);
65
- } else {
66
- setPass(false);
67
- setError({
68
- body: value,
69
- message: t('response.ConnectionCheckFailed', { ns: 'error' }),
70
- type: 'ConnectionCheckFailed',
71
- });
72
- }
73
- },
74
- onLoadingChange: (loading) => {
75
- setLoading(loading);
76
- },
77
- params: {
78
- messages: [
79
- {
80
- content: '你好',
81
- role: 'user',
82
- },
83
- ],
84
- model,
85
- provider,
86
- },
87
- trace: {
88
- sessionId: `connection:${provider}`,
89
- topicId: model,
90
- traceName: TraceNameMap.ConnectivityChecker,
91
- },
92
- });
93
- };
94
- const isMobile = useIsMobile();
95
-
96
- return (
97
- <Flexbox align={isMobile ? 'flex-start' : 'flex-end'} gap={8}>
98
- <Flexbox align={'center'} direction={isMobile ? 'horizontal-reverse' : 'horizontal'} gap={12}>
99
- {pass && (
100
- <Flexbox gap={4} horizontal>
101
- <CheckCircleFilled
102
- style={{
103
- color: theme.colorSuccess,
104
- }}
105
- />
106
- {t('llm.checker.pass')}
107
- </Flexbox>
108
- )}
109
- <Button loading={loading} onClick={checkConnection}>
110
- {t('llm.checker.button')}
111
- </Button>
112
- </Flexbox>
113
- {error && <Error error={error} />}
114
- </Flexbox>
115
- );
116
- });
117
-
118
- export default Checker;
@@ -1,303 +0,0 @@
1
- 'use client';
2
-
3
- import { ProviderCombine } from '@lobehub/icons';
4
- import {
5
- Form,
6
- type FormGroupItemType,
7
- type FormItemProps,
8
- Icon,
9
- Input,
10
- InputPassword,
11
- Tooltip,
12
- } from '@lobehub/ui';
13
- import { Switch } from 'antd';
14
- import { createStyles } from 'antd-style';
15
- import { debounce } from 'lodash-es';
16
- import { LockIcon } from 'lucide-react';
17
- import Link from 'next/link';
18
- import { ReactNode, memo } from 'react';
19
- import { Trans, useTranslation } from 'react-i18next';
20
- import { Center, Flexbox } from 'react-layout-kit';
21
- import urlJoin from 'url-join';
22
-
23
- import { useSyncSettings } from '@/app/[variants]/(main)/settings/hooks/useSyncSettings';
24
- import {
25
- KeyVaultsConfigKey,
26
- LLMProviderApiTokenKey,
27
- LLMProviderBaseUrlKey,
28
- LLMProviderConfigKey,
29
- LLMProviderModelListKey,
30
- } from '@/app/[variants]/(main)/settings/llm/const';
31
- import { FORM_STYLE } from '@/const/layoutTokens';
32
- import { AES_GCM_URL, BASE_PROVIDER_DOC_URL } from '@/const/url';
33
- import { isServerMode } from '@/const/version';
34
- import { useUserStore } from '@/store/user';
35
- import { keyVaultsConfigSelectors, modelConfigSelectors } from '@/store/user/selectors';
36
- import { ModelProviderCard } from '@/types/llm';
37
- import { GlobalLLMProviderKey } from '@/types/user/settings';
38
-
39
- import Checker from '../Checker';
40
- import ProviderModelListSelect from '../ProviderModelList';
41
-
42
- const useStyles = createStyles(({ css, prefixCls, responsive, token }) => ({
43
- aceGcm: css`
44
- padding-block: 0 !important;
45
- .${prefixCls}-form-item-label {
46
- display: none;
47
- }
48
- .${prefixCls}-form-item-control {
49
- width: 100%;
50
-
51
- font-size: 12px;
52
- color: ${token.colorTextSecondary};
53
- text-align: center;
54
-
55
- opacity: 0.66;
56
-
57
- transition: opacity 0.2s ${token.motionEaseInOut};
58
-
59
- &:hover {
60
- opacity: 1;
61
- }
62
- }
63
- `,
64
- form: css`
65
- .${prefixCls}-form-item-control:has(.${prefixCls}-input,.${prefixCls}-select) {
66
- flex: none;
67
- width: min(70%, 800px);
68
- min-width: min(70%, 800px) !important;
69
- }
70
- ${responsive.mobile} {
71
- width: 100%;
72
- min-width: unset !important;
73
- }
74
- .${prefixCls}-select-selection-overflow-item {
75
- font-size: 12px;
76
- }
77
- `,
78
- help: css`
79
- border-radius: 50%;
80
-
81
- font-size: 12px;
82
- font-weight: 500;
83
- color: ${token.colorTextDescription};
84
-
85
- background: ${token.colorFillTertiary};
86
-
87
- &:hover {
88
- color: ${token.colorText};
89
- background: ${token.colorFill};
90
- }
91
- `,
92
- }));
93
-
94
- export interface ProviderConfigProps extends Omit<ModelProviderCard, 'id' | 'chatModels'> {
95
- apiKeyItems?: FormItemProps[];
96
- canDeactivate?: boolean;
97
- checkerItem?: FormItemProps;
98
- className?: string;
99
- extra?: ReactNode;
100
- hideSwitch?: boolean;
101
- id: GlobalLLMProviderKey;
102
- modelList?: {
103
- azureDeployName?: boolean;
104
- notFoundContent?: ReactNode;
105
- placeholder?: string;
106
- showModelFetcher?: boolean;
107
- };
108
- showAceGcm?: boolean;
109
- title?: ReactNode;
110
- }
111
-
112
- const ProviderConfig = memo<ProviderConfigProps>(
113
- ({
114
- apiKeyItems,
115
- id,
116
- proxyUrl,
117
- showApiKey = true,
118
- checkModel,
119
- canDeactivate = true,
120
- checkerItem,
121
- modelList,
122
- title,
123
- defaultShowBrowserRequest,
124
- disableBrowserRequest,
125
- className,
126
- name,
127
- showAceGcm = true,
128
- showChecker = true,
129
- extra,
130
- }) => {
131
- const { t } = useTranslation('setting');
132
- const [form] = Form.useForm();
133
- const { cx, styles } = useStyles();
134
- const [
135
- toggleProviderEnabled,
136
- setSettings,
137
- enabled,
138
- isFetchOnClient,
139
- isProviderEndpointNotEmpty,
140
- isProviderApiKeyNotEmpty,
141
- ] = useUserStore((s) => [
142
- s.toggleProviderEnabled,
143
- s.setSettings,
144
- modelConfigSelectors.isProviderEnabled(id)(s),
145
- modelConfigSelectors.isProviderFetchOnClient(id)(s),
146
- keyVaultsConfigSelectors.isProviderEndpointNotEmpty(id)(s),
147
- keyVaultsConfigSelectors.isProviderApiKeyNotEmpty(id)(s),
148
- ]);
149
-
150
- useSyncSettings(form);
151
-
152
- const apiKeyItem: FormItemProps[] = !showApiKey
153
- ? []
154
- : (apiKeyItems ?? [
155
- {
156
- children: (
157
- <InputPassword
158
- autoComplete={'new-password'}
159
- placeholder={t(`llm.apiKey.placeholder`, { name })}
160
- />
161
- ),
162
- desc: t(`llm.apiKey.desc`, { name }),
163
- label: t(`llm.apiKey.title`),
164
- name: [KeyVaultsConfigKey, id, LLMProviderApiTokenKey],
165
- },
166
- ]);
167
-
168
- const aceGcmItem: FormItemProps = {
169
- children: (
170
- <>
171
- <Icon icon={LockIcon} style={{ marginRight: 4 }} />
172
- <Trans i18nKey="llm.aesGcm" ns={'setting'}>
173
- 您的秘钥与代理地址等将使用
174
- <Link href={AES_GCM_URL} style={{ marginInline: 4 }} target={'_blank'}>
175
- AES-GCM
176
- </Link>
177
- 加密算法进行加密
178
- </Trans>
179
- </>
180
- ),
181
- className: styles.aceGcm,
182
- minWidth: undefined,
183
- };
184
-
185
- const showEndpoint = !!proxyUrl;
186
-
187
- const formItems = [
188
- ...apiKeyItem,
189
- showEndpoint && {
190
- children: <Input allowClear placeholder={proxyUrl?.placeholder} />,
191
- desc: proxyUrl?.desc || t('llm.proxyUrl.desc'),
192
- label: proxyUrl?.title || t('llm.proxyUrl.title'),
193
- name: [KeyVaultsConfigKey, id, LLMProviderBaseUrlKey],
194
- },
195
- /*
196
- * Conditions to show Client Fetch Switch
197
- * 1. provider is not disabled browser request
198
- * 2. provider show browser request by default
199
- * 3. Provider allow to edit endpoint and the value of endpoint is not empty
200
- * 4. There is an apikey provided by user
201
- */
202
- !disableBrowserRequest &&
203
- (defaultShowBrowserRequest ||
204
- (showEndpoint && isProviderEndpointNotEmpty) ||
205
- (showApiKey && isProviderApiKeyNotEmpty)) && {
206
- children: (
207
- <Switch
208
- onChange={(enabled) => {
209
- setSettings({ [LLMProviderConfigKey]: { [id]: { fetchOnClient: enabled } } });
210
- }}
211
- value={isFetchOnClient}
212
- />
213
- ),
214
- desc: t('llm.fetchOnClient.desc'),
215
- label: t('llm.fetchOnClient.title'),
216
- minWidth: undefined,
217
- },
218
- {
219
- children: (
220
- <ProviderModelListSelect
221
- notFoundContent={modelList?.notFoundContent}
222
- placeholder={modelList?.placeholder ?? t('llm.modelList.placeholder')}
223
- provider={id}
224
- showAzureDeployName={modelList?.azureDeployName}
225
- showModelFetcher={modelList?.showModelFetcher}
226
- />
227
- ),
228
- desc: t('llm.modelList.desc'),
229
- label: t('llm.modelList.title'),
230
- name: [LLMProviderConfigKey, id, LLMProviderModelListKey],
231
- },
232
- showChecker
233
- ? (checkerItem ?? {
234
- children: <Checker model={checkModel!} provider={id} />,
235
- desc: t('llm.checker.desc'),
236
- label: t('llm.checker.title'),
237
- minWidth: undefined,
238
- })
239
- : undefined,
240
- showAceGcm && isServerMode && aceGcmItem,
241
- ].filter(Boolean) as FormItemProps[];
242
-
243
- /* ↓ cloud slot ↓ */
244
-
245
- /* ↑ cloud slot ↑ */
246
-
247
- const model: FormGroupItemType = {
248
- children: formItems,
249
-
250
- defaultActive: canDeactivate ? enabled : undefined,
251
-
252
- extra: (
253
- <Flexbox align={'center'} gap={8} horizontal>
254
- {extra}
255
- <Tooltip title={t('llm.helpDoc')}>
256
- <Link
257
- href={urlJoin(BASE_PROVIDER_DOC_URL, id)}
258
- onClick={(e) => e.stopPropagation()}
259
- target={'_blank'}
260
- >
261
- <Center className={styles.help} height={20} width={20}>
262
- ?
263
- </Center>
264
- </Link>
265
- </Tooltip>
266
- {canDeactivate ? (
267
- <Switch
268
- onChange={(enabled) => {
269
- toggleProviderEnabled(id, enabled);
270
- }}
271
- value={enabled}
272
- />
273
- ) : undefined}
274
- </Flexbox>
275
- ),
276
- title: (
277
- <Flexbox
278
- align={'center'}
279
- horizontal
280
- style={{
281
- height: 24,
282
- maxHeight: 24,
283
- ...(enabled ? {} : { filter: 'grayscale(100%)', maxHeight: 24, opacity: 0.66 }),
284
- }}
285
- >
286
- {title ?? <ProviderCombine provider={id} size={24} />}
287
- </Flexbox>
288
- ),
289
- };
290
-
291
- return (
292
- <Form
293
- className={cx(styles.form, className)}
294
- form={form}
295
- items={[model]}
296
- onValuesChange={debounce(setSettings, 100)}
297
- {...FORM_STYLE}
298
- />
299
- );
300
- },
301
- );
302
-
303
- export default ProviderConfig;
@@ -1,98 +0,0 @@
1
- import { ModelIcon } from '@lobehub/icons';
2
- import { ActionIcon, Icon, Text } from '@lobehub/ui';
3
- import { App } from 'antd';
4
- import isEqual from 'fast-deep-equal';
5
- import { LucideArrowRight, LucideSettings, LucideTrash2 } from 'lucide-react';
6
- import { memo } from 'react';
7
- import { useTranslation } from 'react-i18next';
8
- import { Flexbox } from 'react-layout-kit';
9
-
10
- import { ModelInfoTags } from '@/components/ModelSelect';
11
- import { useUserStore } from '@/store/user';
12
- import { modelConfigSelectors, modelProviderSelectors } from '@/store/user/selectors';
13
- import { GlobalLLMProviderKey } from '@/types/user/settings';
14
-
15
- interface CustomModelOptionProps {
16
- id: string;
17
- provider: GlobalLLMProviderKey;
18
- }
19
-
20
- const CustomModelOption = memo<CustomModelOptionProps>(({ id, provider }) => {
21
- const { t } = useTranslation('common');
22
- const { t: s } = useTranslation('setting');
23
- const { modal } = App.useApp();
24
-
25
- const [dispatchCustomModelCards, toggleEditingCustomModelCard, removeEnabledModels] =
26
- useUserStore((s) => [
27
- s.dispatchCustomModelCards,
28
- s.toggleEditingCustomModelCard,
29
- s.removeEnabledModels,
30
- ]);
31
-
32
- const modelCard = useUserStore(
33
- modelConfigSelectors.getCustomModelCard({ id, provider }),
34
- isEqual,
35
- );
36
-
37
- const isEnabled = useUserStore(
38
- (s) => modelProviderSelectors.getEnableModelsById(provider)(s)?.includes(id),
39
- isEqual,
40
- );
41
-
42
- return (
43
- <Flexbox align={'center'} distribution={'space-between'} gap={8} horizontal>
44
- <Flexbox align={'center'} gap={8} horizontal style={{ flex: 1, width: '70%' }}>
45
- <ModelIcon model={id} size={32} />
46
- <Flexbox direction={'vertical'} style={{ flex: 1, overflow: 'hidden' }}>
47
- <Flexbox align={'center'} gap={8} horizontal>
48
- <Text ellipsis>{modelCard?.displayName || id}</Text>
49
- <ModelInfoTags id={id} {...modelCard} isCustom />
50
- </Flexbox>
51
- <Text ellipsis style={{ fontSize: 12, marginTop: '4px' }} type={'secondary'}>
52
- {id}
53
- {!!modelCard?.deploymentName && (
54
- <>
55
- <Icon icon={LucideArrowRight} />
56
- {modelCard?.deploymentName}
57
- </>
58
- )}
59
- </Text>
60
- </Flexbox>
61
- </Flexbox>
62
-
63
- <Flexbox horizontal>
64
- <ActionIcon
65
- icon={LucideSettings}
66
- onClick={async (e) => {
67
- e.stopPropagation();
68
- toggleEditingCustomModelCard({ id, provider });
69
- }}
70
- title={s('llm.customModelCards.config')}
71
- />
72
- <ActionIcon
73
- icon={LucideTrash2}
74
- onClick={async (e) => {
75
- e.stopPropagation();
76
- e.preventDefault();
77
-
78
- await modal.confirm({
79
- centered: true,
80
- content: s('llm.customModelCards.confirmDelete'),
81
- okButtonProps: { danger: true },
82
- onOk: async () => {
83
- // delete model and deactivate id
84
- await dispatchCustomModelCards(provider, { id, type: 'delete' });
85
- await removeEnabledModels(provider, id);
86
- },
87
- type: 'warning',
88
- });
89
- }}
90
- style={isEnabled ? { marginRight: '10px' } : {}}
91
- title={t('delete')}
92
- />
93
- </Flexbox>
94
- </Flexbox>
95
- );
96
- });
97
-
98
- export default CustomModelOption;