@lobehub/chat 0.126.5 → 0.127.1
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/.env.example +8 -0
- package/CHANGELOG.md +50 -0
- package/Dockerfile +3 -0
- package/docs/Deployment/Environment-Variable.md +10 -0
- package/docs/Deployment/Environment-Variable.zh-CN.md +10 -0
- package/locales/ar/common.json +1 -0
- package/locales/ar/error.json +2 -0
- package/locales/ar/setting.json +16 -0
- package/locales/de-DE/common.json +1 -0
- package/locales/de-DE/error.json +2 -0
- package/locales/de-DE/setting.json +16 -0
- package/locales/en-US/common.json +1 -0
- package/locales/en-US/error.json +2 -0
- package/locales/en-US/setting.json +16 -0
- package/locales/es-ES/common.json +1 -0
- package/locales/es-ES/error.json +2 -0
- package/locales/es-ES/setting.json +16 -0
- package/locales/fr-FR/common.json +1 -0
- package/locales/fr-FR/error.json +2 -0
- package/locales/fr-FR/setting.json +16 -0
- package/locales/it-IT/common.json +1 -0
- package/locales/it-IT/error.json +2 -0
- package/locales/it-IT/setting.json +16 -0
- package/locales/ja-JP/common.json +1 -0
- package/locales/ja-JP/error.json +2 -0
- package/locales/ja-JP/setting.json +16 -0
- package/locales/ko-KR/common.json +1 -0
- package/locales/ko-KR/error.json +2 -0
- package/locales/ko-KR/setting.json +16 -0
- package/locales/nl-NL/common.json +1 -0
- package/locales/nl-NL/error.json +2 -0
- package/locales/nl-NL/setting.json +16 -0
- package/locales/pl-PL/common.json +1 -0
- package/locales/pl-PL/error.json +2 -0
- package/locales/pl-PL/setting.json +16 -0
- package/locales/pt-BR/common.json +1 -0
- package/locales/pt-BR/error.json +2 -0
- package/locales/pt-BR/setting.json +16 -0
- package/locales/ru-RU/common.json +1 -0
- package/locales/ru-RU/error.json +2 -0
- package/locales/ru-RU/setting.json +16 -0
- package/locales/tr-TR/common.json +1 -0
- package/locales/tr-TR/error.json +2 -0
- package/locales/tr-TR/setting.json +16 -0
- package/locales/vi-VN/common.json +1 -0
- package/locales/vi-VN/error.json +2 -0
- package/locales/vi-VN/setting.json +16 -0
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-CN/error.json +2 -0
- package/locales/zh-CN/setting.json +16 -0
- package/locales/zh-TW/common.json +1 -0
- package/locales/zh-TW/error.json +2 -0
- package/locales/zh-TW/setting.json +16 -0
- package/package.json +1 -1
- package/src/app/api/chat/[provider]/agentRuntime.ts +14 -0
- package/src/app/api/config/route.ts +2 -0
- package/src/app/api/errorResponse.ts +3 -0
- package/src/app/chat/features/ChatHeader/SettingButton.tsx +1 -2
- package/src/app/settings/(desktop)/features/Header.tsx +3 -4
- package/src/app/settings/(desktop)/features/SideBar.tsx +42 -0
- package/src/app/settings/(desktop)/index.tsx +4 -3
- package/src/app/settings/(desktop)/layout.desktop.tsx +14 -6
- package/src/app/settings/(desktop)/layout.responsive.tsx +4 -4
- package/src/app/settings/(mobile)/features/ExtraList.tsx +7 -5
- package/src/app/settings/(mobile)/features/Header/index.tsx +8 -5
- package/src/app/settings/(mobile)/index.tsx +1 -3
- package/src/app/settings/(mobile)/layout.mobile.tsx +8 -4
- package/src/app/settings/(mobile)/mobile/index.tsx +3 -5
- package/src/app/settings/agent/Agent.tsx +0 -4
- package/src/app/settings/agent/layout.tsx +9 -1
- package/src/app/settings/agent/page.tsx +17 -2
- package/src/app/settings/common/index.tsx +0 -3
- package/src/app/settings/common/layout.tsx +9 -1
- package/src/app/settings/features/SettingList/Item.tsx +50 -0
- package/src/app/settings/features/{SideBar/List.tsx → SettingList/index.tsx} +14 -15
- package/src/app/settings/layout.server.tsx +10 -3
- package/src/app/settings/llm/Azure/index.tsx +78 -106
- package/src/app/settings/llm/Bedrock/index.tsx +60 -89
- package/src/app/settings/llm/Google/index.tsx +26 -55
- package/src/app/settings/llm/Moonshot/index.tsx +29 -54
- package/src/app/settings/llm/Ollama/index.tsx +55 -0
- package/src/app/settings/llm/OpenAI/index.tsx +91 -107
- package/src/app/settings/llm/Zhipu/index.tsx +29 -54
- package/src/app/settings/llm/components/ProviderConfig/index.tsx +58 -0
- package/src/app/settings/llm/index.tsx +42 -0
- package/src/app/settings/llm/layout.tsx +9 -1
- package/src/app/settings/llm/page.tsx +6 -39
- package/src/app/settings/tts/layout.tsx +9 -1
- package/src/app/settings/tts/page.tsx +17 -2
- package/src/components/ModelProviderIcon/index.tsx +5 -1
- package/src/config/modelProviders/index.ts +3 -0
- package/src/config/modelProviders/ollama.ts +117 -0
- package/src/config/server/provider.ts +6 -0
- package/src/const/settings.ts +5 -0
- package/src/features/SideBar/BottomActions.tsx +1 -2
- package/src/layout/ResponsiveLayout.client.tsx +7 -7
- package/src/layout/ResponsiveLayout.server.tsx +6 -6
- package/src/libs/agent-runtime/error.ts +3 -0
- package/src/libs/agent-runtime/index.ts +1 -0
- package/src/libs/agent-runtime/ollama/index.ts +80 -0
- package/src/libs/agent-runtime/types/type.ts +1 -0
- package/src/locales/default/common.ts +1 -0
- package/src/locales/default/error.ts +3 -0
- package/src/locales/default/setting.ts +16 -0
- package/src/services/_auth.test.ts +132 -0
- package/src/services/_auth.ts +9 -1
- package/src/store/global/slices/common/initialState.ts +0 -2
- package/src/store/global/slices/settings/action.test.ts +0 -13
- package/src/store/global/slices/settings/action.ts +0 -5
- package/src/store/global/slices/settings/selectors/modelProvider.ts +31 -2
- package/src/types/settings/modelProvider.ts +8 -0
- package/src/app/settings/agent/index.tsx +0 -21
- package/src/app/settings/features/SideBar/Item.tsx +0 -44
- package/src/app/settings/features/SideBar/index.tsx +0 -42
- package/src/app/settings/tts/index.tsx +0 -21
- package/src/store/global/hooks/useSwitchSettingsOnInit.ts +0 -12
- /package/src/app/settings/llm/{Checker.tsx → components/Checker.tsx} +0 -0
- /package/src/app/settings/llm/{useSyncSettings.ts → components/ProviderConfig/useSyncSettings.ts} +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { act } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { ModelProvider } from '@/libs/agent-runtime';
|
|
5
|
+
import { useGlobalStore } from '@/store/global';
|
|
6
|
+
import { GlobalLLMConfig, GlobalLLMProviderKey } from '@/types/settings';
|
|
7
|
+
|
|
8
|
+
import { getProviderAuthPayload } from './_auth';
|
|
9
|
+
|
|
10
|
+
// Mock data for different providers
|
|
11
|
+
const mockZhiPuAPIKey = 'zhipu-api-key';
|
|
12
|
+
const mockMoonshotAPIKey = 'moonshot-api-key';
|
|
13
|
+
const mockGoogleAPIKey = 'google-api-key';
|
|
14
|
+
|
|
15
|
+
// mock the traditional zustand
|
|
16
|
+
vi.mock('zustand/traditional');
|
|
17
|
+
|
|
18
|
+
const setModelProviderConfig = <T extends GlobalLLMProviderKey>(
|
|
19
|
+
provider: T,
|
|
20
|
+
config: Partial<GlobalLLMConfig[T]>,
|
|
21
|
+
) => {
|
|
22
|
+
useGlobalStore.setState({
|
|
23
|
+
settings: { languageModel: { [provider]: config } },
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe('getProviderAuthPayload', () => {
|
|
28
|
+
it('should return correct payload for ZhiPu provider', () => {
|
|
29
|
+
act(() => {
|
|
30
|
+
setModelProviderConfig('zhipu', { apiKey: mockZhiPuAPIKey });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const payload = getProviderAuthPayload(ModelProvider.ZhiPu);
|
|
34
|
+
expect(payload).toEqual({ apiKey: mockZhiPuAPIKey });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should return correct payload for Moonshot provider', () => {
|
|
38
|
+
act(() => {
|
|
39
|
+
setModelProviderConfig('moonshot', { apiKey: mockMoonshotAPIKey });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const payload = getProviderAuthPayload(ModelProvider.Moonshot);
|
|
43
|
+
expect(payload).toEqual({ apiKey: mockMoonshotAPIKey });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should return correct payload for Google provider', () => {
|
|
47
|
+
act(() => {
|
|
48
|
+
setModelProviderConfig('google', { apiKey: mockGoogleAPIKey });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const payload = getProviderAuthPayload(ModelProvider.Google);
|
|
52
|
+
expect(payload).toEqual({ apiKey: mockGoogleAPIKey });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should return correct payload for Bedrock provider', () => {
|
|
56
|
+
// 假设的 Bedrock 配置
|
|
57
|
+
const mockBedrockConfig = {
|
|
58
|
+
accessKeyId: 'bedrock-access-key-id',
|
|
59
|
+
region: 'bedrock-region',
|
|
60
|
+
secretAccessKey: 'bedrock-secret-access-key',
|
|
61
|
+
};
|
|
62
|
+
act(() => {
|
|
63
|
+
setModelProviderConfig('bedrock', mockBedrockConfig);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const payload = getProviderAuthPayload(ModelProvider.Bedrock);
|
|
67
|
+
expect(payload).toEqual({
|
|
68
|
+
apiKey: mockBedrockConfig.secretAccessKey + mockBedrockConfig.accessKeyId,
|
|
69
|
+
awsAccessKeyId: mockBedrockConfig.accessKeyId,
|
|
70
|
+
awsRegion: mockBedrockConfig.region,
|
|
71
|
+
awsSecretAccessKey: mockBedrockConfig.secretAccessKey,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should return correct payload for Azure provider', () => {
|
|
76
|
+
// 假设的 Azure 配置
|
|
77
|
+
const mockAzureConfig = {
|
|
78
|
+
apiKey: 'azure-api-key',
|
|
79
|
+
apiVersion: 'azure-api-version',
|
|
80
|
+
endpoint: 'azure-endpoint',
|
|
81
|
+
};
|
|
82
|
+
act(() => {
|
|
83
|
+
setModelProviderConfig('azure', mockAzureConfig);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const payload = getProviderAuthPayload(ModelProvider.Azure);
|
|
87
|
+
expect(payload).toEqual({
|
|
88
|
+
apiKey: mockAzureConfig.apiKey,
|
|
89
|
+
azureApiVersion: mockAzureConfig.apiVersion,
|
|
90
|
+
endpoint: mockAzureConfig.endpoint,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should return correct payload for Ollama provider', () => {
|
|
95
|
+
// 假设的 Ollama 配置
|
|
96
|
+
const mockOllamaProxyUrl = 'ollama-proxy-url';
|
|
97
|
+
act(() => {
|
|
98
|
+
setModelProviderConfig('ollama', { endpoint: mockOllamaProxyUrl });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const payload = getProviderAuthPayload(ModelProvider.Ollama);
|
|
102
|
+
expect(payload).toEqual({
|
|
103
|
+
endpoint: mockOllamaProxyUrl,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should return correct payload for OpenAI provider', () => {
|
|
108
|
+
// 假设的 OpenAI 配置
|
|
109
|
+
const mockOpenAIConfig = {
|
|
110
|
+
OPENAI_API_KEY: 'openai-api-key',
|
|
111
|
+
endpoint: 'openai-endpoint',
|
|
112
|
+
useAzure: true,
|
|
113
|
+
azureApiVersion: 'openai-azure-api-version',
|
|
114
|
+
};
|
|
115
|
+
act(() => {
|
|
116
|
+
setModelProviderConfig('openAI', mockOpenAIConfig);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const payload = getProviderAuthPayload(ModelProvider.OpenAI);
|
|
120
|
+
expect(payload).toEqual({
|
|
121
|
+
apiKey: mockOpenAIConfig.OPENAI_API_KEY,
|
|
122
|
+
azureApiVersion: mockOpenAIConfig.azureApiVersion,
|
|
123
|
+
endpoint: mockOpenAIConfig.endpoint,
|
|
124
|
+
useAzure: mockOpenAIConfig.useAzure,
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should return an empty object or throw an error for an unknown provider', () => {
|
|
129
|
+
const payload = getProviderAuthPayload('UnknownProvider');
|
|
130
|
+
expect(payload).toEqual({ apiKey: '', endpoint: '' });
|
|
131
|
+
});
|
|
132
|
+
});
|
package/src/services/_auth.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { useGlobalStore } from '@/store/global';
|
|
|
4
4
|
import { modelProviderSelectors, settingsSelectors } from '@/store/global/selectors';
|
|
5
5
|
import { createJWT } from '@/utils/jwt';
|
|
6
6
|
|
|
7
|
-
const getProviderAuthPayload = (provider: string) => {
|
|
7
|
+
export const getProviderAuthPayload = (provider: string) => {
|
|
8
8
|
switch (provider) {
|
|
9
9
|
case ModelProvider.ZhiPu: {
|
|
10
10
|
return { apiKey: modelProviderSelectors.zhipuAPIKey(useGlobalStore.getState()) };
|
|
@@ -40,6 +40,14 @@ const getProviderAuthPayload = (provider: string) => {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
case ModelProvider.Ollama: {
|
|
44
|
+
const endpoint = modelProviderSelectors.ollamaProxyUrl(useGlobalStore.getState());
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
endpoint,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
default:
|
|
44
52
|
case ModelProvider.OpenAI: {
|
|
45
53
|
const openai = modelProviderSelectors.openAIConfig(useGlobalStore.getState());
|
|
@@ -23,12 +23,10 @@ export interface GlobalCommonState {
|
|
|
23
23
|
isMobile?: boolean;
|
|
24
24
|
latestVersion?: string;
|
|
25
25
|
router?: AppRouterInstance;
|
|
26
|
-
settingsTab: SettingsTabs;
|
|
27
26
|
sidebarKey: SidebarTabKey;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
export const initialCommonState: GlobalCommonState = {
|
|
31
30
|
isMobile: false,
|
|
32
|
-
settingsTab: SettingsTabs.Common,
|
|
33
31
|
sidebarKey: SidebarTabKey.Chat,
|
|
34
32
|
};
|
|
@@ -6,7 +6,6 @@ import { withSWR } from '~test-utils';
|
|
|
6
6
|
import { DEFAULT_AGENT, DEFAULT_SETTINGS } from '@/const/settings';
|
|
7
7
|
import { userService } from '@/services/user';
|
|
8
8
|
import { useGlobalStore } from '@/store/global';
|
|
9
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
|
10
9
|
import { LobeAgentSettings } from '@/types/session';
|
|
11
10
|
import { GlobalSettings, OpenAIConfig } from '@/types/settings';
|
|
12
11
|
|
|
@@ -100,18 +99,6 @@ describe('SettingsAction', () => {
|
|
|
100
99
|
});
|
|
101
100
|
});
|
|
102
101
|
|
|
103
|
-
describe('switchSettingTabs', () => {
|
|
104
|
-
it('should switch settings tabs', () => {
|
|
105
|
-
const { result } = renderHook(() => useGlobalStore());
|
|
106
|
-
|
|
107
|
-
act(() => {
|
|
108
|
-
result.current.switchSettingTabs(SettingsTabs.Agent);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
expect(result.current.settingsTab).toEqual(SettingsTabs.Agent);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
102
|
describe('switchThemeMode', () => {
|
|
116
103
|
it('should switch theme mode', async () => {
|
|
117
104
|
const { result } = renderHook(() => useGlobalStore());
|
|
@@ -5,7 +5,6 @@ import type { StateCreator } from 'zustand/vanilla';
|
|
|
5
5
|
|
|
6
6
|
import { userService } from '@/services/user';
|
|
7
7
|
import type { GlobalStore } from '@/store/global';
|
|
8
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
|
9
8
|
import { LobeAgentSettings } from '@/types/session';
|
|
10
9
|
import { GlobalLLMConfig, GlobalLLMProviderKey, GlobalSettings } from '@/types/settings';
|
|
11
10
|
import { difference } from '@/utils/difference';
|
|
@@ -22,7 +21,6 @@ export interface SettingsAction {
|
|
|
22
21
|
config: Partial<GlobalLLMConfig[T]>,
|
|
23
22
|
) => Promise<void>;
|
|
24
23
|
setSettings: (settings: DeepPartial<GlobalSettings>) => Promise<void>;
|
|
25
|
-
switchSettingTabs: (tab: SettingsTabs) => void;
|
|
26
24
|
switchThemeMode: (themeMode: ThemeMode) => Promise<void>;
|
|
27
25
|
toggleProviderEnabled: (provider: GlobalLLMProviderKey, enabled: boolean) => Promise<void>;
|
|
28
26
|
updateDefaultAgent: (agent: DeepPartial<LobeAgentSettings>) => Promise<void>;
|
|
@@ -61,9 +59,6 @@ export const createSettingsSlice: StateCreator<
|
|
|
61
59
|
await get().refreshUserConfig();
|
|
62
60
|
},
|
|
63
61
|
|
|
64
|
-
switchSettingTabs: (tab) => {
|
|
65
|
-
set({ settingsTab: tab });
|
|
66
|
-
},
|
|
67
62
|
switchThemeMode: async (themeMode) => {
|
|
68
63
|
await get().setSettings({ themeMode });
|
|
69
64
|
},
|
|
@@ -5,16 +5,21 @@ import {
|
|
|
5
5
|
GoogleProvider,
|
|
6
6
|
LOBE_DEFAULT_MODEL_LIST,
|
|
7
7
|
MoonshotProvider,
|
|
8
|
+
OllamaProvider,
|
|
8
9
|
OpenAIProvider,
|
|
9
10
|
ZhiPuProvider,
|
|
10
11
|
} from '@/config/modelProviders';
|
|
11
12
|
import { ChatModelCard, ModelProviderCard } from '@/types/llm';
|
|
13
|
+
import { GlobalLLMProviderKey } from '@/types/settings';
|
|
12
14
|
import { parseModelString } from '@/utils/parseModels';
|
|
13
15
|
|
|
14
16
|
import { GlobalStore } from '../../../store';
|
|
15
17
|
import { currentSettings } from './settings';
|
|
16
18
|
|
|
17
19
|
const modelProvider = (s: GlobalStore) => currentSettings(s).languageModel;
|
|
20
|
+
const providerEnabled = (provider: GlobalLLMProviderKey) => (s: GlobalStore) =>
|
|
21
|
+
currentSettings(s).languageModel[provider]?.enabled || false;
|
|
22
|
+
|
|
18
23
|
const openAIConfig = (s: GlobalStore) => modelProvider(s).openAI;
|
|
19
24
|
|
|
20
25
|
const openAIAPIKey = (s: GlobalStore) => openAIConfig(s).OPENAI_API_KEY;
|
|
@@ -37,6 +42,12 @@ const azureConfig = (s: GlobalStore) => modelProvider(s).azure;
|
|
|
37
42
|
const enableMoonshot = (s: GlobalStore) => modelProvider(s).moonshot.enabled;
|
|
38
43
|
const moonshotAPIKey = (s: GlobalStore) => modelProvider(s).moonshot.apiKey;
|
|
39
44
|
|
|
45
|
+
const enableOllamaConfigInSettings = (s: GlobalStore) =>
|
|
46
|
+
s.serverConfig.languageModel?.ollama?.enabled || false;
|
|
47
|
+
|
|
48
|
+
const enableOllama = (s: GlobalStore) => modelProvider(s).ollama.enabled;
|
|
49
|
+
const ollamaProxyUrl = (s: GlobalStore) => modelProvider(s).ollama.endpoint;
|
|
50
|
+
|
|
40
51
|
// const azureModelList = (s: GlobalStore): ModelProviderCard => {
|
|
41
52
|
// const azure = azureConfig(s);
|
|
42
53
|
// return {
|
|
@@ -46,8 +57,11 @@ const moonshotAPIKey = (s: GlobalStore) => modelProvider(s).moonshot.apiKey;
|
|
|
46
57
|
// };
|
|
47
58
|
|
|
48
59
|
// 提取处理 chatModels 的专门方法
|
|
49
|
-
const processChatModels = (
|
|
50
|
-
|
|
60
|
+
const processChatModels = (
|
|
61
|
+
modelConfig: ReturnType<typeof parseModelString>,
|
|
62
|
+
defaultChartModels = OpenAIProvider.chatModels,
|
|
63
|
+
): ChatModelCard[] => {
|
|
64
|
+
let chatModels = modelConfig.removeAll ? [] : defaultChartModels;
|
|
51
65
|
|
|
52
66
|
// 处理移除逻辑
|
|
53
67
|
if (!modelConfig.removeAll) {
|
|
@@ -102,6 +116,12 @@ const modelSelectList = (s: GlobalStore): ModelProviderCard[] => {
|
|
|
102
116
|
|
|
103
117
|
const chatModels = processChatModels(modelConfig);
|
|
104
118
|
|
|
119
|
+
const ollamaModelConfig = parseModelString(
|
|
120
|
+
currentSettings(s).languageModel.ollama.customModelName,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const ollamaChatModels = processChatModels(ollamaModelConfig, OllamaProvider.chatModels);
|
|
124
|
+
|
|
105
125
|
return [
|
|
106
126
|
{
|
|
107
127
|
...OpenAIProvider,
|
|
@@ -112,6 +132,7 @@ const modelSelectList = (s: GlobalStore): ModelProviderCard[] => {
|
|
|
112
132
|
{ ...MoonshotProvider, enabled: enableMoonshot(s) },
|
|
113
133
|
{ ...GoogleProvider, enabled: enableGoogle(s) },
|
|
114
134
|
{ ...BedrockProvider, enabled: enableBedrock(s) },
|
|
135
|
+
{ ...OllamaProvider, chatModels: ollamaChatModels, enabled: enableOllama(s) },
|
|
115
136
|
];
|
|
116
137
|
};
|
|
117
138
|
|
|
@@ -152,6 +173,9 @@ export const modelProviderSelectors = {
|
|
|
152
173
|
modelEnabledFiles,
|
|
153
174
|
modelEnabledUpload,
|
|
154
175
|
|
|
176
|
+
modelProviderConfig: modelProvider,
|
|
177
|
+
providerEnabled,
|
|
178
|
+
|
|
155
179
|
// OpenAI
|
|
156
180
|
openAIConfig,
|
|
157
181
|
openAIAPIKey,
|
|
@@ -174,4 +198,9 @@ export const modelProviderSelectors = {
|
|
|
174
198
|
// Moonshot
|
|
175
199
|
enableMoonshot,
|
|
176
200
|
moonshotAPIKey,
|
|
201
|
+
|
|
202
|
+
// Ollama
|
|
203
|
+
enableOllamaConfigInSettings,
|
|
204
|
+
enableOllama,
|
|
205
|
+
ollamaProxyUrl,
|
|
177
206
|
};
|
|
@@ -7,6 +7,7 @@ export interface OpenAIConfig {
|
|
|
7
7
|
* custom mode name for fine-tuning or openai like model
|
|
8
8
|
*/
|
|
9
9
|
customModelName?: string;
|
|
10
|
+
enabled: boolean;
|
|
10
11
|
endpoint?: string;
|
|
11
12
|
/**
|
|
12
13
|
* @deprecated
|
|
@@ -47,11 +48,18 @@ export interface AWSBedrockConfig {
|
|
|
47
48
|
secretAccessKey?: string;
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
export interface OllamaConfig {
|
|
52
|
+
customModelName?: string;
|
|
53
|
+
enabled?: boolean;
|
|
54
|
+
endpoint?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
50
57
|
export interface GlobalLLMConfig {
|
|
51
58
|
azure: AzureOpenAIConfig;
|
|
52
59
|
bedrock: AWSBedrockConfig;
|
|
53
60
|
google: GoogleConfig;
|
|
54
61
|
moonshot: MoonshotConfig;
|
|
62
|
+
ollama: OllamaConfig;
|
|
55
63
|
openAI: OpenAIConfig;
|
|
56
64
|
zhipu: ZhiPuConfig;
|
|
57
65
|
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
|
|
6
|
-
import PageTitle from '@/components/PageTitle';
|
|
7
|
-
import { useSwitchSideBarOnInit } from '@/store/global/hooks/useSwitchSettingsOnInit';
|
|
8
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
|
9
|
-
|
|
10
|
-
import Agent from './Agent';
|
|
11
|
-
|
|
12
|
-
export default memo(() => {
|
|
13
|
-
useSwitchSideBarOnInit(SettingsTabs.Agent);
|
|
14
|
-
const { t } = useTranslation('setting');
|
|
15
|
-
return (
|
|
16
|
-
<>
|
|
17
|
-
<PageTitle title={t('tab.agent')} />
|
|
18
|
-
<Agent />
|
|
19
|
-
</>
|
|
20
|
-
);
|
|
21
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Icon, List } from '@lobehub/ui';
|
|
2
|
-
import { createStyles, useResponsive } from 'antd-style';
|
|
3
|
-
import { ChevronRight, type LucideIcon } from 'lucide-react';
|
|
4
|
-
import { CSSProperties, ReactNode, memo } from 'react';
|
|
5
|
-
|
|
6
|
-
const { Item } = List;
|
|
7
|
-
|
|
8
|
-
const useStyles = createStyles(({ css, token, responsive }) => ({
|
|
9
|
-
container: css`
|
|
10
|
-
position: relative;
|
|
11
|
-
padding-top: 20px;
|
|
12
|
-
padding-bottom: 20px;
|
|
13
|
-
border-radius: ${token.borderRadius}px;
|
|
14
|
-
${responsive.mobile} {
|
|
15
|
-
border-radius: 0;
|
|
16
|
-
}
|
|
17
|
-
`,
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
export interface ItemProps {
|
|
21
|
-
active?: boolean;
|
|
22
|
-
className?: string;
|
|
23
|
-
icon: LucideIcon;
|
|
24
|
-
label: ReactNode;
|
|
25
|
-
style?: CSSProperties;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const SettingItem = memo<ItemProps>(({ label, icon, active = false, style, className }) => {
|
|
29
|
-
const { cx, styles } = useStyles();
|
|
30
|
-
const { mobile } = useResponsive();
|
|
31
|
-
return (
|
|
32
|
-
<Item
|
|
33
|
-
active={active}
|
|
34
|
-
avatar={<Icon icon={icon} size={{ fontSize: 16 }} />}
|
|
35
|
-
className={cx(styles.container, className)}
|
|
36
|
-
style={style}
|
|
37
|
-
title={label as string}
|
|
38
|
-
>
|
|
39
|
-
{mobile && <Icon icon={ChevronRight} size={{ fontSize: 16 }} />}
|
|
40
|
-
</Item>
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
export default SettingItem;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { DraggablePanelBody, Logo } from '@lobehub/ui';
|
|
2
|
-
import { createStyles } from 'antd-style';
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
import { Flexbox } from 'react-layout-kit';
|
|
5
|
-
|
|
6
|
-
import FolderPanel from '@/features/FolderPanel';
|
|
7
|
-
|
|
8
|
-
import UpgradeAlert from '../UpgradeAlert';
|
|
9
|
-
import List from './List';
|
|
10
|
-
|
|
11
|
-
const useStyles = createStyles(({ stylish, token, css }) => ({
|
|
12
|
-
body: stylish.noScrollbar,
|
|
13
|
-
logo: css`
|
|
14
|
-
fill: ${token.colorText};
|
|
15
|
-
`,
|
|
16
|
-
top: css`
|
|
17
|
-
position: sticky;
|
|
18
|
-
top: 0;
|
|
19
|
-
`,
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
const SideBar = memo(() => {
|
|
23
|
-
const { styles } = useStyles();
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<FolderPanel>
|
|
27
|
-
<DraggablePanelBody className={styles.body} style={{ padding: 0 }}>
|
|
28
|
-
<Flexbox className={styles.top} padding={16}>
|
|
29
|
-
<div>
|
|
30
|
-
<Logo className={styles.logo} extra={'Settings'} size={36} type={'text'} />
|
|
31
|
-
</div>
|
|
32
|
-
</Flexbox>
|
|
33
|
-
<Flexbox gap={2} style={{ paddingInline: 8 }}>
|
|
34
|
-
<UpgradeAlert />
|
|
35
|
-
<List />
|
|
36
|
-
</Flexbox>
|
|
37
|
-
</DraggablePanelBody>
|
|
38
|
-
</FolderPanel>
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
export default SideBar;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
|
|
6
|
-
import PageTitle from '@/components/PageTitle';
|
|
7
|
-
import { useSwitchSideBarOnInit } from '@/store/global/hooks/useSwitchSettingsOnInit';
|
|
8
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
|
9
|
-
|
|
10
|
-
import TTS from './TTS';
|
|
11
|
-
|
|
12
|
-
export default memo(() => {
|
|
13
|
-
useSwitchSideBarOnInit(SettingsTabs.TTS);
|
|
14
|
-
const { t } = useTranslation('setting');
|
|
15
|
-
return (
|
|
16
|
-
<>
|
|
17
|
-
<PageTitle title={t('tab.llm')} />
|
|
18
|
-
<TTS />
|
|
19
|
-
</>
|
|
20
|
-
);
|
|
21
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { useOnFinishHydrationGlobal } from '@/store/global';
|
|
2
|
-
|
|
3
|
-
import { SettingsTabs } from '../initialState';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 切换设置侧边栏选项
|
|
7
|
-
*/
|
|
8
|
-
export const useSwitchSideBarOnInit = (key: SettingsTabs) => {
|
|
9
|
-
useOnFinishHydrationGlobal((store) => {
|
|
10
|
-
store.switchSettingTabs(key);
|
|
11
|
-
});
|
|
12
|
-
};
|
|
File without changes
|
/package/src/app/settings/llm/{useSyncSettings.ts → components/ProviderConfig/useSyncSettings.ts}
RENAMED
|
File without changes
|