@lobehub/chat 1.49.10 → 1.49.12
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 +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/components.json +24 -0
- package/locales/ar/modelProvider.json +0 -24
- package/locales/ar/models.json +15 -0
- package/locales/bg-BG/components.json +24 -0
- package/locales/bg-BG/modelProvider.json +0 -24
- package/locales/bg-BG/models.json +15 -0
- package/locales/de-DE/components.json +24 -0
- package/locales/de-DE/modelProvider.json +0 -24
- package/locales/de-DE/models.json +15 -0
- package/locales/en-US/components.json +24 -0
- package/locales/en-US/modelProvider.json +0 -24
- package/locales/en-US/models.json +15 -0
- package/locales/es-ES/components.json +24 -0
- package/locales/es-ES/modelProvider.json +0 -24
- package/locales/es-ES/models.json +15 -0
- package/locales/fa-IR/components.json +24 -0
- package/locales/fa-IR/modelProvider.json +0 -24
- package/locales/fa-IR/models.json +15 -0
- package/locales/fr-FR/components.json +24 -0
- package/locales/fr-FR/modelProvider.json +0 -24
- package/locales/fr-FR/models.json +15 -0
- package/locales/it-IT/components.json +24 -0
- package/locales/it-IT/modelProvider.json +0 -24
- package/locales/it-IT/models.json +15 -0
- package/locales/ja-JP/components.json +24 -0
- package/locales/ja-JP/modelProvider.json +0 -24
- package/locales/ja-JP/models.json +15 -0
- package/locales/ko-KR/components.json +24 -0
- package/locales/ko-KR/modelProvider.json +0 -24
- package/locales/ko-KR/models.json +4 -0
- package/locales/nl-NL/components.json +24 -0
- package/locales/nl-NL/modelProvider.json +0 -24
- package/locales/nl-NL/models.json +15 -0
- package/locales/pl-PL/components.json +24 -0
- package/locales/pl-PL/modelProvider.json +0 -24
- package/locales/pl-PL/models.json +15 -0
- package/locales/pt-BR/components.json +24 -0
- package/locales/pt-BR/modelProvider.json +0 -24
- package/locales/pt-BR/models.json +15 -0
- package/locales/ru-RU/components.json +24 -0
- package/locales/ru-RU/modelProvider.json +0 -24
- package/locales/ru-RU/models.json +15 -0
- package/locales/tr-TR/components.json +24 -0
- package/locales/tr-TR/modelProvider.json +0 -24
- package/locales/tr-TR/models.json +15 -0
- package/locales/vi-VN/components.json +24 -0
- package/locales/vi-VN/modelProvider.json +0 -24
- package/locales/vi-VN/models.json +15 -0
- package/locales/zh-CN/components.json +24 -0
- package/locales/zh-CN/modelProvider.json +0 -24
- package/locales/zh-CN/models.json +16 -1
- package/locales/zh-TW/components.json +24 -0
- package/locales/zh-TW/modelProvider.json +0 -24
- package/locales/zh-TW/models.json +15 -0
- package/package.json +1 -1
- package/src/app/(main)/chat/(workspace)/@portal/_layout/Mobile.tsx +1 -0
- package/src/app/(main)/chat/(workspace)/_layout/Desktop/Portal.tsx +26 -2
- package/src/app/(main)/settings/provider/(detail)/[id]/page.tsx +10 -3
- package/src/app/(main)/settings/provider/(detail)/ollama/CheckError.tsx +70 -0
- package/src/app/(main)/settings/provider/(detail)/ollama/Container.tsx +57 -0
- package/src/app/(main)/settings/provider/(detail)/ollama/OllamaModelDownloader/index.tsx +127 -0
- package/src/app/(main)/settings/provider/(detail)/ollama/OllamaModelDownloader/useDownloadMonitor.ts +29 -0
- package/src/app/(main)/settings/provider/(detail)/ollama/page.tsx +2 -7
- package/src/app/(main)/settings/provider/features/ProviderConfig/Checker.tsx +90 -69
- package/src/app/(main)/settings/provider/features/ProviderConfig/index.tsx +6 -6
- package/src/components/FormAction/index.tsx +66 -0
- package/src/components/OllamaSetupGuide/index.tsx +217 -0
- package/src/components/Thinking/index.tsx +14 -16
- package/src/config/aiModels/ollama.ts +12 -19
- package/src/config/modelProviders/ollama.ts +1 -0
- package/src/config/modelProviders/siliconcloud.ts +2 -2
- package/src/database/repositories/aiInfra/index.ts +33 -2
- package/src/database/server/models/aiProvider.ts +5 -1
- package/src/features/Conversation/Error/OllamaBizError/SetupGuide.tsx +2 -209
- package/src/features/Conversation/components/MarkdownElements/LobeThinking/Render.tsx +7 -58
- package/src/libs/agent-runtime/ollama/index.ts +1 -1
- package/src/libs/agent-runtime/siliconcloud/index.ts +33 -1
- package/src/locales/default/components.ts +26 -0
- package/src/locales/default/modelProvider.ts +0 -26
- package/src/server/routers/lambda/aiProvider.ts +2 -10
- package/src/services/aiProvider/client.ts +2 -8
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +10 -10
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +4 -3
- package/src/store/chat/slices/aiChat/initialState.ts +1 -1
- package/src/store/chat/slices/message/action.ts +4 -3
- package/src/store/global/initialState.ts +2 -0
- package/src/store/global/selectors.ts +2 -0
- package/src/store/serverConfig/selectors.test.ts +3 -0
- package/src/store/serverConfig/store.test.ts +3 -2
- package/src/store/serverConfig/store.ts +1 -1
- package/src/store/user/slices/common/action.test.ts +1 -0
- package/src/types/serverConfig.ts +1 -1
- package/src/app/(main)/settings/provider/(detail)/ollama/Checker.tsx +0 -73
@@ -155,32 +155,6 @@ export default {
|
|
155
155
|
desc: '必须包含http(s)://,本地未额外指定可留空',
|
156
156
|
title: 'Ollama 服务地址',
|
157
157
|
},
|
158
|
-
setup: {
|
159
|
-
cors: {
|
160
|
-
description: '因浏览器安全限制,你需要为 Ollama 进行跨域配置后方可正常使用。',
|
161
|
-
linux: {
|
162
|
-
env: '在 [Service] 部分下添加 `Environment`,添加 OLLAMA_ORIGINS 环境变量:',
|
163
|
-
reboot: '重载 systemd 并重启 Ollama',
|
164
|
-
systemd: '调用 systemd 编辑 ollama 服务:',
|
165
|
-
},
|
166
|
-
macos: '请打开「终端」应用程序,并粘贴以下指令,并按回车运行',
|
167
|
-
reboot: '请在执行完成后重启 Ollama 服务',
|
168
|
-
title: '配置 Ollama 允许跨域访问',
|
169
|
-
windows:
|
170
|
-
'在 Windows 上,点击「控制面板」,进入编辑系统环境变量。为您的用户账户新建名为 「OLLAMA_ORIGINS」 的环境变量,值为 * ,点击 「OK/应用」 保存',
|
171
|
-
},
|
172
|
-
install: {
|
173
|
-
description: '请确认你已经开启 Ollama ,如果没有下载 Ollama ,请前往官网<1>下载</1>',
|
174
|
-
docker:
|
175
|
-
'如果你更倾向于使用 Docker,Ollama 也提供了官方 Docker 镜像,你可以通过以下命令拉取:',
|
176
|
-
linux: {
|
177
|
-
command: '通过以下命令安装:',
|
178
|
-
manual: '或者,你也可以参考 <1>Linux 手动安装指南</1> 自行安装',
|
179
|
-
},
|
180
|
-
title: '在本地安装并开启 Ollama 应用',
|
181
|
-
windowsTab: 'Windows (预览版)',
|
182
|
-
},
|
183
|
-
},
|
184
158
|
title: 'Ollama',
|
185
159
|
unlock: {
|
186
160
|
cancel: '取消下载',
|
@@ -48,7 +48,7 @@ export const aiProviderRouter = router({
|
|
48
48
|
.input(z.object({ id: z.string() }))
|
49
49
|
|
50
50
|
.query(async ({ input, ctx }): Promise<AiProviderDetailItem | undefined> => {
|
51
|
-
return ctx.
|
51
|
+
return ctx.aiInfraRepos.getAiProviderDetail(input.id, KeyVaultsGateKeeper.getUserKeyVaults);
|
52
52
|
}),
|
53
53
|
|
54
54
|
getAiProviderList: aiProviderProcedure.query(async ({ ctx }) => {
|
@@ -58,15 +58,7 @@ export const aiProviderRouter = router({
|
|
58
58
|
getAiProviderRuntimeState: aiProviderProcedure
|
59
59
|
.input(z.object({ isLogin: z.boolean().optional() }))
|
60
60
|
.query(async ({ ctx }): Promise<AiProviderRuntimeState> => {
|
61
|
-
|
62
|
-
KeyVaultsGateKeeper.getUserKeyVaults,
|
63
|
-
);
|
64
|
-
|
65
|
-
const enabledAiProviders = await ctx.aiInfraRepos.getUserEnabledProviderList();
|
66
|
-
|
67
|
-
const enabledAiModels = await ctx.aiInfraRepos.getEnabledModels();
|
68
|
-
|
69
|
-
return { enabledAiModels, enabledAiProviders, runtimeConfig };
|
61
|
+
return ctx.aiInfraRepos.getAiProviderRuntimeState(KeyVaultsGateKeeper.getUserKeyVaults);
|
70
62
|
}),
|
71
63
|
|
72
64
|
removeAiProvider: aiProviderProcedure
|
@@ -25,7 +25,7 @@ export class ClientService extends BaseClientService implements IAiProviderServi
|
|
25
25
|
};
|
26
26
|
|
27
27
|
getAiProviderById: IAiProviderService['getAiProviderById'] = async (id) => {
|
28
|
-
return this.
|
28
|
+
return this.aiInfraRepos.getAiProviderDetail(id);
|
29
29
|
};
|
30
30
|
|
31
31
|
getAiProviderList: IAiProviderService['getAiProviderList'] = async () => {
|
@@ -33,13 +33,7 @@ export class ClientService extends BaseClientService implements IAiProviderServi
|
|
33
33
|
};
|
34
34
|
|
35
35
|
getAiProviderRuntimeState: IAiProviderService['getAiProviderRuntimeState'] = async () => {
|
36
|
-
|
37
|
-
|
38
|
-
const enabledAiProviders = await this.aiInfraRepos.getUserEnabledProviderList();
|
39
|
-
|
40
|
-
const enabledAiModels = await this.aiInfraRepos.getEnabledModels();
|
41
|
-
|
42
|
-
return { enabledAiModels, enabledAiProviders, runtimeConfig };
|
36
|
+
return await this.aiInfraRepos.getAiProviderRuntimeState();
|
43
37
|
};
|
44
38
|
|
45
39
|
toggleProviderEnabled: IAiProviderService['toggleProviderEnabled'] = async (id, enabled) => {
|
@@ -576,7 +576,7 @@ describe('chatMessage actions', () => {
|
|
576
576
|
const abortController = new AbortController();
|
577
577
|
|
578
578
|
act(() => {
|
579
|
-
useChatStore.setState({ abortController });
|
579
|
+
useChatStore.setState({ chatLoadingIdsAbortController: abortController });
|
580
580
|
});
|
581
581
|
|
582
582
|
await act(async () => {
|
@@ -596,18 +596,18 @@ describe('chatMessage actions', () => {
|
|
596
596
|
|
597
597
|
await act(async () => {
|
598
598
|
// 确保没有设置 abortController
|
599
|
-
useChatStore.setState({
|
599
|
+
useChatStore.setState({ chatLoadingIdsAbortController: undefined });
|
600
600
|
|
601
601
|
result.current.stopGenerateMessage();
|
602
602
|
});
|
603
603
|
|
604
604
|
// 由于没有 abortController,不应调用任何方法
|
605
|
-
expect(result.current.
|
605
|
+
expect(result.current.chatLoadingIdsAbortController).toBeUndefined();
|
606
606
|
});
|
607
607
|
|
608
608
|
it('should return early if abortController is undefined', () => {
|
609
609
|
act(() => {
|
610
|
-
useChatStore.setState({
|
610
|
+
useChatStore.setState({ chatLoadingIdsAbortController: undefined });
|
611
611
|
});
|
612
612
|
|
613
613
|
const { result } = renderHook(() => useChatStore());
|
@@ -625,7 +625,7 @@ describe('chatMessage actions', () => {
|
|
625
625
|
const abortMock = vi.fn();
|
626
626
|
const abortController = { abort: abortMock } as unknown as AbortController;
|
627
627
|
act(() => {
|
628
|
-
useChatStore.setState({ abortController });
|
628
|
+
useChatStore.setState({ chatLoadingIdsAbortController: abortController });
|
629
629
|
});
|
630
630
|
const { result } = renderHook(() => useChatStore());
|
631
631
|
|
@@ -639,7 +639,7 @@ describe('chatMessage actions', () => {
|
|
639
639
|
it('should call internal_toggleChatLoading with correct parameters', () => {
|
640
640
|
const abortController = new AbortController();
|
641
641
|
act(() => {
|
642
|
-
useChatStore.setState({ abortController });
|
642
|
+
useChatStore.setState({ chatLoadingIdsAbortController: abortController });
|
643
643
|
});
|
644
644
|
const { result } = renderHook(() => useChatStore());
|
645
645
|
const spy = vi.spyOn(result.current, 'internal_toggleChatLoading');
|
@@ -868,7 +868,7 @@ describe('chatMessage actions', () => {
|
|
868
868
|
});
|
869
869
|
|
870
870
|
const state = useChatStore.getState();
|
871
|
-
expect(state.
|
871
|
+
expect(state.chatLoadingIdsAbortController).toBeInstanceOf(AbortController);
|
872
872
|
expect(state.chatLoadingIds).toEqual(['message-id']);
|
873
873
|
});
|
874
874
|
|
@@ -887,7 +887,7 @@ describe('chatMessage actions', () => {
|
|
887
887
|
});
|
888
888
|
|
889
889
|
const state = useChatStore.getState();
|
890
|
-
expect(state.
|
890
|
+
expect(state.chatLoadingIdsAbortController).toBeUndefined();
|
891
891
|
expect(state.chatLoadingIds).toEqual([]);
|
892
892
|
});
|
893
893
|
|
@@ -920,12 +920,12 @@ describe('chatMessage actions', () => {
|
|
920
920
|
const abortController = new AbortController();
|
921
921
|
|
922
922
|
act(() => {
|
923
|
-
useChatStore.setState({ abortController });
|
923
|
+
useChatStore.setState({ chatLoadingIdsAbortController: abortController });
|
924
924
|
result.current.internal_toggleChatLoading(true, 'message-id', 'loading-action');
|
925
925
|
});
|
926
926
|
|
927
927
|
const state = useChatStore.getState();
|
928
|
-
expect(state.
|
928
|
+
expect(state.chatLoadingIdsAbortController).toEqual(abortController);
|
929
929
|
});
|
930
930
|
});
|
931
931
|
|
@@ -267,10 +267,11 @@ export const generateAIChat: StateCreator<
|
|
267
267
|
await Promise.all([summaryTitle(), addFilesToAgent()]);
|
268
268
|
},
|
269
269
|
stopGenerateMessage: () => {
|
270
|
-
const {
|
271
|
-
if (!abortController) return;
|
270
|
+
const { chatLoadingIdsAbortController, internal_toggleChatLoading } = get();
|
272
271
|
|
273
|
-
|
272
|
+
if (!chatLoadingIdsAbortController) return;
|
273
|
+
|
274
|
+
chatLoadingIdsAbortController.abort(MESSAGE_CANCEL_FLAT);
|
274
275
|
|
275
276
|
internal_toggleChatLoading(false, undefined, n('stopGenerateMessage') as string);
|
276
277
|
},
|
@@ -368,13 +368,14 @@ export const chatMessage: StateCreator<
|
|
368
368
|
);
|
369
369
|
},
|
370
370
|
internal_toggleLoadingArrays: (key, loading, id, action) => {
|
371
|
+
const abortControllerKey = `${key}AbortController`;
|
371
372
|
if (loading) {
|
372
373
|
window.addEventListener('beforeunload', preventLeavingFn);
|
373
374
|
|
374
375
|
const abortController = new AbortController();
|
375
376
|
set(
|
376
377
|
{
|
377
|
-
abortController,
|
378
|
+
[abortControllerKey]: abortController,
|
378
379
|
[key]: toggleBooleanList(get()[key] as string[], id!, loading),
|
379
380
|
},
|
380
381
|
false,
|
@@ -384,11 +385,11 @@ export const chatMessage: StateCreator<
|
|
384
385
|
return abortController;
|
385
386
|
} else {
|
386
387
|
if (!id) {
|
387
|
-
set({
|
388
|
+
set({ [abortControllerKey]: undefined, [key]: [] }, false, action);
|
388
389
|
} else
|
389
390
|
set(
|
390
391
|
{
|
391
|
-
|
392
|
+
[abortControllerKey]: undefined,
|
392
393
|
[key]: toggleBooleanList(get()[key] as string[], id, loading),
|
393
394
|
},
|
394
395
|
false,
|
@@ -52,6 +52,7 @@ export interface SystemStatus {
|
|
52
52
|
latestChangelogId?: string;
|
53
53
|
mobileShowPortal?: boolean;
|
54
54
|
mobileShowTopic?: boolean;
|
55
|
+
portalWidth: number;
|
55
56
|
sessionsWidth: number;
|
56
57
|
showChatSideBar?: boolean;
|
57
58
|
showFilePanel?: boolean;
|
@@ -86,6 +87,7 @@ export const INITIAL_STATUS = {
|
|
86
87
|
hideThreadLimitAlert: false,
|
87
88
|
inputHeight: 200,
|
88
89
|
mobileShowTopic: false,
|
90
|
+
portalWidth: 400,
|
89
91
|
sessionsWidth: 320,
|
90
92
|
showChatSideBar: true,
|
91
93
|
showFilePanel: true,
|
@@ -20,6 +20,7 @@ const hidePWAInstaller = (s: GlobalStore) => s.status.hidePWAInstaller;
|
|
20
20
|
const showChatHeader = (s: GlobalStore) => !s.status.zenMode;
|
21
21
|
const inZenMode = (s: GlobalStore) => s.status.zenMode;
|
22
22
|
const sessionWidth = (s: GlobalStore) => s.status.sessionsWidth;
|
23
|
+
const portalWidth = (s: GlobalStore) => s.status.portalWidth || 400;
|
23
24
|
const filePanelWidth = (s: GlobalStore) => s.status.filePanelWidth;
|
24
25
|
const inputHeight = (s: GlobalStore) => s.status.inputHeight;
|
25
26
|
const threadInputHeight = (s: GlobalStore) => s.status.threadInputHeight;
|
@@ -59,6 +60,7 @@ export const systemStatusSelectors = {
|
|
59
60
|
isPgliteNotInited,
|
60
61
|
mobileShowPortal,
|
61
62
|
mobileShowTopic,
|
63
|
+
portalWidth,
|
62
64
|
sessionGroupKeys,
|
63
65
|
sessionWidth,
|
64
66
|
showChatHeader,
|
@@ -49,6 +49,7 @@ describe('serverConfigSelectors', () => {
|
|
49
49
|
serverConfig: {
|
50
50
|
enabledOAuthSSO: true,
|
51
51
|
telemetry: {},
|
52
|
+
aiProvider: {},
|
52
53
|
},
|
53
54
|
});
|
54
55
|
|
@@ -63,6 +64,7 @@ describe('serverConfigSelectors', () => {
|
|
63
64
|
const store = initServerConfigStore({
|
64
65
|
serverConfig: {
|
65
66
|
telemetry: { langfuse: true },
|
67
|
+
aiProvider: {},
|
66
68
|
},
|
67
69
|
});
|
68
70
|
|
@@ -75,6 +77,7 @@ describe('serverConfigSelectors', () => {
|
|
75
77
|
const store = initServerConfigStore({
|
76
78
|
serverConfig: {
|
77
79
|
telemetry: {},
|
80
|
+
aiProvider: {},
|
78
81
|
},
|
79
82
|
});
|
80
83
|
|
@@ -23,14 +23,14 @@ describe('createServerConfigStore', () => {
|
|
23
23
|
|
24
24
|
expect(store.getState()).toEqual({
|
25
25
|
featureFlags: DEFAULT_FEATURE_FLAGS,
|
26
|
-
serverConfig: { telemetry: {} },
|
26
|
+
serverConfig: { telemetry: {}, aiProvider: {} },
|
27
27
|
});
|
28
28
|
});
|
29
29
|
|
30
30
|
it('should initialize store with custom initial state', () => {
|
31
31
|
const initialState: Partial<ServerConfigStore> = {
|
32
32
|
featureFlags: { edit_agent: false },
|
33
|
-
serverConfig: { telemetry: { langfuse: true } },
|
33
|
+
serverConfig: { telemetry: { langfuse: true }, aiProvider: {} },
|
34
34
|
};
|
35
35
|
|
36
36
|
const store = initServerConfigStore(initialState);
|
@@ -38,6 +38,7 @@ describe('createServerConfigStore', () => {
|
|
38
38
|
expect(store.getState().featureFlags.edit_agent).toBeFalsy();
|
39
39
|
expect(store.getState().serverConfig).toEqual({
|
40
40
|
telemetry: { langfuse: true },
|
41
|
+
aiProvider: {},
|
41
42
|
});
|
42
43
|
});
|
43
44
|
|
@@ -12,7 +12,7 @@ import { StoreApiWithSelector } from '@/utils/zustand';
|
|
12
12
|
|
13
13
|
const initialState: ServerConfigStore = {
|
14
14
|
featureFlags: DEFAULT_FEATURE_FLAGS,
|
15
|
-
serverConfig: { telemetry: {} },
|
15
|
+
serverConfig: { aiProvider: {}, telemetry: {} },
|
16
16
|
};
|
17
17
|
|
18
18
|
// =============== 聚合 createStoreFn ============ //
|
@@ -20,7 +20,7 @@ export interface ServerModelProviderConfig {
|
|
20
20
|
export type ServerLanguageModel = Partial<Record<GlobalLLMProviderKey, ServerModelProviderConfig>>;
|
21
21
|
|
22
22
|
export interface GlobalServerConfig {
|
23
|
-
aiProvider
|
23
|
+
aiProvider: ServerLanguageModel;
|
24
24
|
defaultAgent?: DeepPartial<UserDefaultAgent>;
|
25
25
|
enableUploadFileToServer?: boolean;
|
26
26
|
enabledAccessCode?: boolean;
|
@@ -1,73 +0,0 @@
|
|
1
|
-
import { CheckCircleFilled } from '@ant-design/icons';
|
2
|
-
import { Alert, Highlighter } from '@lobehub/ui';
|
3
|
-
import { Button } from 'antd';
|
4
|
-
import { useTheme } from 'antd-style';
|
5
|
-
import { ListResponse } from 'ollama/browser';
|
6
|
-
import { memo } from 'react';
|
7
|
-
import { useTranslation } from 'react-i18next';
|
8
|
-
import { Flexbox } from 'react-layout-kit';
|
9
|
-
import useSWR from 'swr';
|
10
|
-
|
11
|
-
import { useIsMobile } from '@/hooks/useIsMobile';
|
12
|
-
import { ollamaService } from '@/services/ollama';
|
13
|
-
|
14
|
-
const OllamaChecker = memo(() => {
|
15
|
-
const { t } = useTranslation('setting');
|
16
|
-
|
17
|
-
const theme = useTheme();
|
18
|
-
|
19
|
-
const { data, error, isLoading, mutate } = useSWR<ListResponse>(
|
20
|
-
'ollama.list',
|
21
|
-
ollamaService.getModels,
|
22
|
-
{
|
23
|
-
revalidateOnFocus: false,
|
24
|
-
revalidateOnMount: false,
|
25
|
-
revalidateOnReconnect: false,
|
26
|
-
},
|
27
|
-
);
|
28
|
-
|
29
|
-
const checkConnection = () => {
|
30
|
-
mutate().catch();
|
31
|
-
};
|
32
|
-
|
33
|
-
const isMobile = useIsMobile();
|
34
|
-
|
35
|
-
return (
|
36
|
-
<Flexbox align={isMobile ? 'flex-start' : 'flex-end'} gap={8}>
|
37
|
-
<Flexbox align={'center'} direction={isMobile ? 'horizontal-reverse' : 'horizontal'} gap={12}>
|
38
|
-
{!error && data?.models && (
|
39
|
-
<Flexbox gap={4} horizontal>
|
40
|
-
<CheckCircleFilled
|
41
|
-
style={{
|
42
|
-
color: theme.colorSuccess,
|
43
|
-
}}
|
44
|
-
/>
|
45
|
-
{t('llm.checker.pass')}
|
46
|
-
</Flexbox>
|
47
|
-
)}
|
48
|
-
<Button loading={isLoading} onClick={checkConnection}>
|
49
|
-
{t('llm.checker.button')}
|
50
|
-
</Button>
|
51
|
-
</Flexbox>
|
52
|
-
{error && (
|
53
|
-
<Flexbox gap={8} style={{ maxWidth: '600px', width: '100%' }}>
|
54
|
-
<Alert
|
55
|
-
banner
|
56
|
-
extra={
|
57
|
-
<Flexbox>
|
58
|
-
<Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
|
59
|
-
{JSON.stringify(error.body || error, null, 2)}
|
60
|
-
</Highlighter>
|
61
|
-
</Flexbox>
|
62
|
-
}
|
63
|
-
message={t(`response.${error.type}` as any, { ns: 'error' })}
|
64
|
-
showIcon
|
65
|
-
type={'error'}
|
66
|
-
/>
|
67
|
-
</Flexbox>
|
68
|
-
)}
|
69
|
-
</Flexbox>
|
70
|
-
);
|
71
|
-
});
|
72
|
-
|
73
|
-
export default OllamaChecker;
|