@lobehub/chat 0.72.3 → 0.73.0
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/next.config.mjs +6 -2
- package/package.json +5 -10
- package/src/config/server.ts +2 -0
- package/src/const/fetch.ts +15 -2
- package/src/const/llm.ts +17 -0
- package/src/const/settings.ts +16 -8
- package/src/const/url.ts +2 -1
- package/src/locales/default/setting.ts +59 -13
- package/src/locales/options.ts +1 -1
- package/src/pages/api/{openai.ts → createChatCompletion.ts} +7 -36
- package/src/pages/api/openai/chat.api.ts +43 -0
- package/src/pages/api/openai/createAzureOpenai.ts +26 -0
- package/src/pages/api/openai/createOpenai.ts +17 -0
- package/src/pages/api/openai/models.api.ts +17 -0
- package/src/pages/settings/features/Settings/Common.tsx +4 -28
- package/src/pages/settings/features/Settings/LLM/Checker.tsx +85 -0
- package/src/pages/settings/features/Settings/LLM/ModelList.tsx +51 -0
- package/src/pages/settings/features/Settings/LLM/getModelList.ts +9 -0
- package/src/pages/settings/features/Settings/LLM/index.tsx +152 -0
- package/src/pages/settings/features/Settings/index.tsx +13 -12
- package/src/services/_header.ts +33 -0
- package/src/services/_url.ts +17 -0
- package/src/services/chatModel.ts +4 -10
- package/src/services/modelList.ts +15 -0
- package/src/services/plugin.ts +1 -1
- package/src/services/pluginMarket.ts +1 -1
- package/src/store/global/hooks/index.ts +1 -0
- package/src/store/global/hooks/useEffectAfterHydrated.ts +22 -0
- package/src/store/global/initialState.ts +4 -0
- package/src/store/global/selectors.test.ts +264 -0
- package/src/store/global/selectors.ts +4 -5
- package/src/store/global/slices/settings.ts +16 -4
- package/src/store/global/store.ts +34 -5
- package/src/types/settings.ts +45 -8
- package/src/utils/fetch.ts +4 -12
- package/src/pages/api/openai.api.ts +0 -24
- package/src/services/url.ts +0 -8
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { LanguageModel } from '@/types/llm';
|
|
2
|
+
|
|
3
|
+
import { globalSelectors } from './selectors';
|
|
4
|
+
import { GlobalStore } from './store';
|
|
5
|
+
|
|
6
|
+
describe('globalSelectors', () => {
|
|
7
|
+
describe('currentSettings', () => {
|
|
8
|
+
it('should merge DEFAULT_SETTINGS and s.settings correctly', () => {
|
|
9
|
+
const s = {
|
|
10
|
+
settings: {
|
|
11
|
+
avatar: 'avatar.jpg',
|
|
12
|
+
fontSize: 14,
|
|
13
|
+
language: 'en-US',
|
|
14
|
+
neutralColor: 'sand',
|
|
15
|
+
password: 'password123',
|
|
16
|
+
primaryColor: 'blue',
|
|
17
|
+
themeMode: 'light',
|
|
18
|
+
defaultAgent: {
|
|
19
|
+
config: {
|
|
20
|
+
systemRole: '',
|
|
21
|
+
model: LanguageModel.GPT3_5,
|
|
22
|
+
params: {},
|
|
23
|
+
},
|
|
24
|
+
meta: {
|
|
25
|
+
avatar: 'Default Agent',
|
|
26
|
+
description: 'Default agent for testing',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
languageModel: {
|
|
30
|
+
openAI: {
|
|
31
|
+
OPENAI_API_KEY: 'openai-api-key',
|
|
32
|
+
endpoint: 'https://openai-endpoint.com',
|
|
33
|
+
models: ['gpt-3.5-turbo'],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
} as unknown as GlobalStore;
|
|
38
|
+
|
|
39
|
+
const result = globalSelectors.currentSettings(s);
|
|
40
|
+
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
avatar: 'avatar.jpg',
|
|
43
|
+
fontSize: 14,
|
|
44
|
+
language: 'en-US',
|
|
45
|
+
neutralColor: 'sand',
|
|
46
|
+
password: 'password123',
|
|
47
|
+
primaryColor: 'blue',
|
|
48
|
+
themeMode: 'light',
|
|
49
|
+
defaultAgent: {
|
|
50
|
+
config: {
|
|
51
|
+
displayMode: 'chat',
|
|
52
|
+
historyCount: 1,
|
|
53
|
+
systemRole: '',
|
|
54
|
+
model: LanguageModel.GPT3_5,
|
|
55
|
+
params: {
|
|
56
|
+
frequency_penalty: 0,
|
|
57
|
+
presence_penalty: 0,
|
|
58
|
+
temperature: 0.6,
|
|
59
|
+
top_p: 1,
|
|
60
|
+
},
|
|
61
|
+
plugins: [],
|
|
62
|
+
},
|
|
63
|
+
meta: {
|
|
64
|
+
avatar: 'Default Agent',
|
|
65
|
+
description: 'Default agent for testing',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
languageModel: {
|
|
69
|
+
openAI: {
|
|
70
|
+
OPENAI_API_KEY: 'openai-api-key',
|
|
71
|
+
azureApiVersion: '2023-08-01-preview',
|
|
72
|
+
endpoint: 'https://openai-endpoint.com',
|
|
73
|
+
models: ['gpt-3.5-turbo'],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//
|
|
80
|
+
// describe('defaultAgent', () => {
|
|
81
|
+
// it('should merge DEFAULT_AGENT and s.settings.defaultAgent correctly', () => {
|
|
82
|
+
// const s: GlobalStore = {
|
|
83
|
+
// settings: {
|
|
84
|
+
// defaultAgent: {
|
|
85
|
+
// config: {
|
|
86
|
+
// model: 'gpt-3.5-turbo',
|
|
87
|
+
// maxTokens: 100,
|
|
88
|
+
// },
|
|
89
|
+
// meta: {
|
|
90
|
+
// name: 'Default Agent',
|
|
91
|
+
// description: 'Default agent for testing',
|
|
92
|
+
// },
|
|
93
|
+
// },
|
|
94
|
+
// },
|
|
95
|
+
// };
|
|
96
|
+
//
|
|
97
|
+
// const result = globalSelectors.defaultAgent(s);
|
|
98
|
+
//
|
|
99
|
+
//
|
|
100
|
+
//
|
|
101
|
+
// expect(result).toEqual(expected);
|
|
102
|
+
// });
|
|
103
|
+
// });
|
|
104
|
+
//
|
|
105
|
+
// describe('defaultAgentConfig', () => {
|
|
106
|
+
// it('should merge DEFAULT_AGENT_CONFIG and defaultAgent(s).config correctly', () => {
|
|
107
|
+
// const s: GlobalStore = {
|
|
108
|
+
// settings: {
|
|
109
|
+
// defaultAgent: {
|
|
110
|
+
// config: {
|
|
111
|
+
// model: 'gpt-3.5-turbo',
|
|
112
|
+
// maxTokens: 100,
|
|
113
|
+
// },
|
|
114
|
+
// },
|
|
115
|
+
// },
|
|
116
|
+
// };
|
|
117
|
+
//
|
|
118
|
+
// const result = globalSelectors.defaultAgentConfig(s);
|
|
119
|
+
//
|
|
120
|
+
// const defaultAgent = globalSelectors.defaultAgent(s);
|
|
121
|
+
// const expected = merge({}, DEFAULT_AGENT_CONFIG, defaultAgent.config);
|
|
122
|
+
//
|
|
123
|
+
// expect(result).toEqual(expected);
|
|
124
|
+
// });
|
|
125
|
+
// });
|
|
126
|
+
//
|
|
127
|
+
// describe('defaultAgentMeta', () => {
|
|
128
|
+
// it('should merge DEFAULT_AGENT_META and defaultAgent(s).meta correctly', () => {
|
|
129
|
+
// const s: GlobalStore = {
|
|
130
|
+
// settings: {
|
|
131
|
+
// defaultAgent: {
|
|
132
|
+
// meta: {
|
|
133
|
+
// name: 'Default Agent',
|
|
134
|
+
// description: 'Default agent for testing',
|
|
135
|
+
// },
|
|
136
|
+
// },
|
|
137
|
+
// },
|
|
138
|
+
// };
|
|
139
|
+
//
|
|
140
|
+
// const result = globalSelectors.defaultAgentMeta(s);
|
|
141
|
+
//
|
|
142
|
+
// const defaultAgent = globalSelectors.defaultAgent(s);
|
|
143
|
+
// const expected = merge({}, DEFAULT_AGENT_META, defaultAgent.meta);
|
|
144
|
+
//
|
|
145
|
+
// expect(result).toEqual(expected);
|
|
146
|
+
// });
|
|
147
|
+
// });
|
|
148
|
+
//
|
|
149
|
+
// describe('exportSettings', () => {
|
|
150
|
+
// it('should remove OPENAI_API_KEY and password fields from s.settings', () => {
|
|
151
|
+
// const s: GlobalStore = {
|
|
152
|
+
// settings: {
|
|
153
|
+
// OPENAI_API_KEY: 'openai-api-key',
|
|
154
|
+
// password: 'password123',
|
|
155
|
+
// avatar: 'avatar.jpg',
|
|
156
|
+
// fontSize: 14,
|
|
157
|
+
// language: 'en',
|
|
158
|
+
// neutralColor: 'white',
|
|
159
|
+
// primaryColor: 'blue',
|
|
160
|
+
// themeMode: 'light',
|
|
161
|
+
// defaultAgent: {
|
|
162
|
+
// config: {
|
|
163
|
+
// model: 'gpt-3.5-turbo',
|
|
164
|
+
// maxTokens: 100,
|
|
165
|
+
// },
|
|
166
|
+
// meta: {
|
|
167
|
+
// name: 'Default Agent',
|
|
168
|
+
// description: 'Default agent for testing',
|
|
169
|
+
// },
|
|
170
|
+
// },
|
|
171
|
+
// languageModel: {
|
|
172
|
+
// azureOpenAI: {
|
|
173
|
+
// AZURE_API_KEY: 'azure-api-key',
|
|
174
|
+
// apiVersion: 'v1',
|
|
175
|
+
// endpoint: 'https://azure-openai-endpoint.com',
|
|
176
|
+
// models: ['gpt-3.5-turbo'],
|
|
177
|
+
// },
|
|
178
|
+
// openAI: {
|
|
179
|
+
// OPENAI_API_KEY: 'openai-api-key',
|
|
180
|
+
// endpoint: 'https://openai-endpoint.com',
|
|
181
|
+
// models: ['gpt-3.5-turbo'],
|
|
182
|
+
// },
|
|
183
|
+
// },
|
|
184
|
+
// },
|
|
185
|
+
// };
|
|
186
|
+
//
|
|
187
|
+
// const result = globalSelectors.exportSettings(s);
|
|
188
|
+
//
|
|
189
|
+
// const expected = {
|
|
190
|
+
// avatar: 'avatar.jpg',
|
|
191
|
+
// fontSize: 14,
|
|
192
|
+
// language: 'en',
|
|
193
|
+
// neutralColor: 'white',
|
|
194
|
+
// primaryColor: 'blue',
|
|
195
|
+
// themeMode: 'light',
|
|
196
|
+
// defaultAgent: {
|
|
197
|
+
// config: {
|
|
198
|
+
// model: 'gpt-3.5-turbo',
|
|
199
|
+
// maxTokens: 100,
|
|
200
|
+
// },
|
|
201
|
+
// meta: {
|
|
202
|
+
// name: 'Default Agent',
|
|
203
|
+
// description: 'Default agent for testing',
|
|
204
|
+
// },
|
|
205
|
+
// },
|
|
206
|
+
// languageModel: {
|
|
207
|
+
// azureOpenAI: {
|
|
208
|
+
// AZURE_API_KEY: 'azure-api-key',
|
|
209
|
+
// apiVersion: 'v1',
|
|
210
|
+
// endpoint: 'https://azure-openai-endpoint.com',
|
|
211
|
+
// models: ['gpt-3.5-turbo'],
|
|
212
|
+
// },
|
|
213
|
+
// openAI: {
|
|
214
|
+
// endpoint: 'https://openai-endpoint.com',
|
|
215
|
+
// models: ['gpt-3.5-turbo'],
|
|
216
|
+
// },
|
|
217
|
+
// },
|
|
218
|
+
// };
|
|
219
|
+
//
|
|
220
|
+
// expect(result).toEqual(expected);
|
|
221
|
+
// });
|
|
222
|
+
//
|
|
223
|
+
// it('should return the result as GlobalSettings type', () => {
|
|
224
|
+
// const s: GlobalStore = {
|
|
225
|
+
// settings: {
|
|
226
|
+
// avatar: 'avatar.jpg',
|
|
227
|
+
// fontSize: 14,
|
|
228
|
+
// language: 'en',
|
|
229
|
+
// neutralColor: 'white',
|
|
230
|
+
// password: 'password123',
|
|
231
|
+
// primaryColor: 'blue',
|
|
232
|
+
// themeMode: 'light',
|
|
233
|
+
// defaultAgent: {
|
|
234
|
+
// config: {
|
|
235
|
+
// model: 'gpt-3.5-turbo',
|
|
236
|
+
// maxTokens: 100,
|
|
237
|
+
// },
|
|
238
|
+
// meta: {
|
|
239
|
+
// name: 'Default Agent',
|
|
240
|
+
// description: 'Default agent for testing',
|
|
241
|
+
// },
|
|
242
|
+
// },
|
|
243
|
+
// languageModel: {
|
|
244
|
+
// azureOpenAI: {
|
|
245
|
+
// AZURE_API_KEY: 'azure-api-key',
|
|
246
|
+
// apiVersion: 'v1',
|
|
247
|
+
// endpoint: 'https://azure-openai-endpoint.com',
|
|
248
|
+
// models: ['gpt-3.5-turbo'],
|
|
249
|
+
// },
|
|
250
|
+
// openAI: {
|
|
251
|
+
// OPENAI_API_KEY: 'openai-api-key',
|
|
252
|
+
// endpoint: 'https://openai-endpoint.com',
|
|
253
|
+
// models: ['gpt-3.5-turbo'],
|
|
254
|
+
// },
|
|
255
|
+
// },
|
|
256
|
+
// },
|
|
257
|
+
// };
|
|
258
|
+
//
|
|
259
|
+
// const result = globalSelectors.exportSettings(s);
|
|
260
|
+
//
|
|
261
|
+
// expect(result).toBeInstanceOf(GlobalSettings);
|
|
262
|
+
// });
|
|
263
|
+
// });
|
|
264
|
+
});
|
|
@@ -5,14 +5,13 @@ import { merge } from '@/utils/merge';
|
|
|
5
5
|
|
|
6
6
|
import { GlobalStore } from './store';
|
|
7
7
|
|
|
8
|
-
const currentSettings = (s: GlobalStore) => merge(
|
|
8
|
+
const currentSettings = (s: GlobalStore) => merge(DEFAULT_SETTINGS, s.settings);
|
|
9
9
|
|
|
10
|
-
const defaultAgent = (s: GlobalStore) => merge(
|
|
10
|
+
const defaultAgent = (s: GlobalStore) => merge(DEFAULT_AGENT, s.settings.defaultAgent);
|
|
11
11
|
|
|
12
|
-
const defaultAgentConfig = (s: GlobalStore) =>
|
|
13
|
-
merge({}, DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
12
|
+
const defaultAgentConfig = (s: GlobalStore) => merge(DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
14
13
|
|
|
15
|
-
const defaultAgentMeta = (s: GlobalStore) => merge(
|
|
14
|
+
const defaultAgentMeta = (s: GlobalStore) => merge(DEFAULT_AGENT_META, defaultAgent(s).meta);
|
|
16
15
|
|
|
17
16
|
export const exportSettings = (s: GlobalStore) => {
|
|
18
17
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { ThemeMode } from 'antd-style';
|
|
2
|
+
import isEqual from 'fast-deep-equal';
|
|
2
3
|
import { produce } from 'immer';
|
|
3
|
-
import {
|
|
4
|
+
import { DeepPartial } from 'utility-types';
|
|
4
5
|
import type { StateCreator } from 'zustand/vanilla';
|
|
5
6
|
|
|
6
7
|
import { DEFAULT_AGENT, DEFAULT_SETTINGS } from '@/const/settings';
|
|
8
|
+
import { SettingsTabs } from '@/store/global/initialState';
|
|
7
9
|
import type { GlobalSettings } from '@/types/settings';
|
|
10
|
+
import { merge } from '@/utils/merge';
|
|
8
11
|
import { setNamespace } from '@/utils/storeDebug';
|
|
9
12
|
|
|
10
13
|
import type { GlobalStore } from '../store';
|
|
@@ -24,7 +27,8 @@ export interface SettingsAction {
|
|
|
24
27
|
* 设置部分配置设置
|
|
25
28
|
* @param settings - 部分配置设置
|
|
26
29
|
*/
|
|
27
|
-
setSettings: (settings:
|
|
30
|
+
setSettings: (settings: DeepPartial<GlobalSettings>) => void;
|
|
31
|
+
switchSettingTabs: (tab: SettingsTabs) => void;
|
|
28
32
|
/**
|
|
29
33
|
* 设置主题模式
|
|
30
34
|
* @param themeMode - 主题模式
|
|
@@ -58,11 +62,19 @@ export const createSettingsSlice: StateCreator<
|
|
|
58
62
|
resetSettings: () => {
|
|
59
63
|
set({ settings: DEFAULT_SETTINGS }, false, t('resetSettings'));
|
|
60
64
|
},
|
|
61
|
-
|
|
62
65
|
setSettings: (settings) => {
|
|
63
66
|
const oldSetting = get().settings;
|
|
64
|
-
|
|
67
|
+
const nextSettings = merge(oldSetting, settings);
|
|
68
|
+
|
|
69
|
+
if (isEqual(oldSetting, nextSettings)) return;
|
|
70
|
+
|
|
71
|
+
set({ settings: merge(oldSetting, settings) }, false, t('setSettings', settings));
|
|
65
72
|
},
|
|
73
|
+
|
|
74
|
+
switchSettingTabs: (tab) => {
|
|
75
|
+
set({ settingsTab: tab });
|
|
76
|
+
},
|
|
77
|
+
|
|
66
78
|
switchThemeMode: (themeMode) => {
|
|
67
79
|
get().setSettings({ themeMode });
|
|
68
80
|
},
|
|
@@ -4,9 +4,10 @@ import { shallow } from 'zustand/shallow';
|
|
|
4
4
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
5
5
|
import { StateCreator } from 'zustand/vanilla';
|
|
6
6
|
|
|
7
|
-
import { DEFAULT_AGENT } from '@/const/settings';
|
|
7
|
+
import { DEFAULT_AGENT, DEFAULT_LLM_CONFIG } from '@/const/settings';
|
|
8
8
|
import { isDev } from '@/utils/env';
|
|
9
9
|
|
|
10
|
+
import { createHyperStorage } from '../middleware/createHyperStorage';
|
|
10
11
|
import { type GlobalState, initialState } from './initialState';
|
|
11
12
|
import { type AgentAction, createAgentSlice } from './slices/agent';
|
|
12
13
|
import { type CommonAction, createCommonSlice } from './slices/common';
|
|
@@ -29,6 +30,7 @@ type GlobalPersist = Pick<GlobalStore, 'preference' | 'settings'>;
|
|
|
29
30
|
const persistOptions: PersistOptions<GlobalStore, GlobalPersist> = {
|
|
30
31
|
merge: (persistedState, currentState) => {
|
|
31
32
|
const state = persistedState as GlobalPersist;
|
|
33
|
+
|
|
32
34
|
return {
|
|
33
35
|
...currentState,
|
|
34
36
|
...state,
|
|
@@ -36,15 +38,42 @@ const persistOptions: PersistOptions<GlobalStore, GlobalPersist> = {
|
|
|
36
38
|
if (!draft.defaultAgent) {
|
|
37
39
|
draft.defaultAgent = DEFAULT_AGENT;
|
|
38
40
|
}
|
|
41
|
+
delete draft.enableMaxTokens;
|
|
42
|
+
delete draft.enableHistoryCount;
|
|
43
|
+
delete draft.historyCount;
|
|
44
|
+
delete draft.enableCompressThreshold;
|
|
45
|
+
delete draft.compressThreshold;
|
|
46
|
+
|
|
47
|
+
// migration to new data model
|
|
48
|
+
if (!draft.languageModel) {
|
|
49
|
+
draft.languageModel = {
|
|
50
|
+
openAI: {
|
|
51
|
+
...DEFAULT_LLM_CONFIG.openAI,
|
|
52
|
+
OPENAI_API_KEY: draft.OPENAI_API_KEY || DEFAULT_LLM_CONFIG.openAI.OPENAI_API_KEY,
|
|
53
|
+
endpoint: draft.endpoint || DEFAULT_LLM_CONFIG.openAI.OPENAI_API_KEY,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
delete draft.OPENAI_API_KEY;
|
|
58
|
+
delete draft.endpoint;
|
|
59
|
+
}
|
|
39
60
|
}),
|
|
40
61
|
};
|
|
41
62
|
},
|
|
42
63
|
name: 'LOBE_SETTINGS',
|
|
43
|
-
|
|
44
|
-
preference: s.preference,
|
|
45
|
-
settings: s.settings,
|
|
46
|
-
}),
|
|
64
|
+
|
|
47
65
|
skipHydration: true,
|
|
66
|
+
|
|
67
|
+
storage: createHyperStorage({
|
|
68
|
+
localStorage: {
|
|
69
|
+
dbName: 'LobeHub',
|
|
70
|
+
selectors: ['preference', 'settings'],
|
|
71
|
+
},
|
|
72
|
+
url: {
|
|
73
|
+
mode: 'hash',
|
|
74
|
+
selectors: [{ settingsTab: 'tab' }],
|
|
75
|
+
},
|
|
76
|
+
}),
|
|
48
77
|
};
|
|
49
78
|
|
|
50
79
|
// =============== 实装 useStore ============ //
|
package/src/types/settings.ts
CHANGED
|
@@ -5,15 +5,37 @@ import type { Locales } from '@/locales/resources';
|
|
|
5
5
|
import type { LobeAgentSession } from '@/types/session';
|
|
6
6
|
|
|
7
7
|
export interface GlobalBaseSettings {
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated
|
|
10
|
+
*/
|
|
11
|
+
OPENAI_API_KEY?: string;
|
|
12
|
+
|
|
9
13
|
avatar: string;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated
|
|
16
|
+
*/
|
|
17
|
+
compressThreshold?: number;
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated
|
|
20
|
+
*/
|
|
21
|
+
enableCompressThreshold?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
*/
|
|
25
|
+
enableHistoryCount?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated
|
|
28
|
+
*/
|
|
29
|
+
enableMaxTokens?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated
|
|
32
|
+
*/
|
|
33
|
+
endpoint?: string;
|
|
15
34
|
fontSize: number;
|
|
16
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated
|
|
37
|
+
*/
|
|
38
|
+
historyCount?: number;
|
|
17
39
|
language: Locales;
|
|
18
40
|
neutralColor: NeutralColors | '';
|
|
19
41
|
password: string;
|
|
@@ -21,13 +43,28 @@ export interface GlobalBaseSettings {
|
|
|
21
43
|
themeMode: ThemeMode;
|
|
22
44
|
}
|
|
23
45
|
|
|
24
|
-
export type GlobalDefaultAgent =
|
|
46
|
+
export type GlobalDefaultAgent = Pick<LobeAgentSession, 'config' | 'meta'>;
|
|
47
|
+
|
|
48
|
+
interface OpenAIConfig {
|
|
49
|
+
OPENAI_API_KEY: string;
|
|
50
|
+
azureApiVersion?: string;
|
|
51
|
+
endpoint?: string;
|
|
52
|
+
models?: string[];
|
|
53
|
+
useAzure?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type GlobalLLMConfig = {
|
|
57
|
+
openAI: OpenAIConfig;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type LLMBrand = keyof GlobalLLMConfig;
|
|
25
61
|
|
|
26
62
|
/**
|
|
27
63
|
* 配置设置
|
|
28
64
|
*/
|
|
29
65
|
export interface GlobalSettings extends GlobalBaseSettings {
|
|
30
66
|
defaultAgent: GlobalDefaultAgent;
|
|
67
|
+
languageModel: GlobalLLMConfig;
|
|
31
68
|
}
|
|
32
69
|
|
|
33
70
|
export type ConfigKeys = keyof GlobalSettings;
|
package/src/utils/fetch.ts
CHANGED
|
@@ -74,7 +74,7 @@ interface FetchAITaskResultParams<T> {
|
|
|
74
74
|
/**
|
|
75
75
|
* 错误处理函数
|
|
76
76
|
*/
|
|
77
|
-
onError?: (e: Error) => void;
|
|
77
|
+
onError?: (e: Error, rawError?: any) => void;
|
|
78
78
|
/**
|
|
79
79
|
* 加载状态变化处理函数
|
|
80
80
|
* @param loading - 是否处于加载状态
|
|
@@ -101,27 +101,19 @@ export const fetchAIFactory =
|
|
|
101
101
|
onLoadingChange,
|
|
102
102
|
abortController,
|
|
103
103
|
}: FetchAITaskResultParams<T>) => {
|
|
104
|
-
const errorHandle = (error: Error) => {
|
|
104
|
+
const errorHandle = (error: Error, errorContent?: any) => {
|
|
105
105
|
onLoadingChange?.(false);
|
|
106
106
|
if (abortController?.signal.aborted) {
|
|
107
|
-
// notification.primaryInfo({
|
|
108
|
-
// message: '已中断当前节点的执行任务',
|
|
109
|
-
// });
|
|
110
107
|
return;
|
|
111
108
|
}
|
|
112
|
-
|
|
113
|
-
// notification?.error({
|
|
114
|
-
// message: `请求失败(${error.message})`,
|
|
115
|
-
// placement: 'bottomRight',
|
|
116
|
-
// });
|
|
117
|
-
onError?.(error);
|
|
109
|
+
onError?.(error, errorContent);
|
|
118
110
|
};
|
|
119
111
|
|
|
120
112
|
onLoadingChange?.(true);
|
|
121
113
|
|
|
122
114
|
const data = await fetchSSE(() => fetcher(params, { signal: abortController?.signal }), {
|
|
123
115
|
onErrorHandle: (error) => {
|
|
124
|
-
errorHandle(new Error(error.message));
|
|
116
|
+
errorHandle(new Error(error.message), error);
|
|
125
117
|
},
|
|
126
118
|
onMessageHandle,
|
|
127
119
|
}).catch(errorHandle);
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY, OPENAI_END_POINT } from '@/const/fetch';
|
|
2
|
-
import { ErrorType } from '@/types/fetch';
|
|
3
|
-
import { OpenAIStreamPayload } from '@/types/openai';
|
|
4
|
-
|
|
5
|
-
import { checkAuth } from './auth';
|
|
6
|
-
import { createErrorResponse } from './error';
|
|
7
|
-
import { createChatCompletion } from './openai';
|
|
8
|
-
|
|
9
|
-
export const runtime = 'edge';
|
|
10
|
-
|
|
11
|
-
export default async function handler(req: Request) {
|
|
12
|
-
const payload = (await req.json()) as OpenAIStreamPayload;
|
|
13
|
-
const apiKey = req.headers.get(OPENAI_API_KEY_HEADER_KEY);
|
|
14
|
-
const accessCode = req.headers.get(LOBE_CHAT_ACCESS_CODE);
|
|
15
|
-
const endpoint = req.headers.get(OPENAI_END_POINT);
|
|
16
|
-
|
|
17
|
-
const result = checkAuth({ accessCode, apiKey });
|
|
18
|
-
|
|
19
|
-
if (!result.auth) {
|
|
20
|
-
return createErrorResponse(result.error as ErrorType);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return createChatCompletion({ OPENAI_API_KEY: apiKey, endpoint, payload });
|
|
24
|
-
}
|