@lobehub/chat 0.122.1 → 0.122.3
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/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/docs/Deployment/Docker-Deployment.md +118 -0
- package/docs/Deployment/Docker-Deployment.zh-CN.md +118 -0
- package/package.json +1 -4
- package/src/app/api/config/route.ts +3 -1
- package/src/app/chat/(mobile)/features/SessionHeader.tsx +2 -1
- package/src/app/chat/features/ChatHeader/ShareButton/ShareModal.tsx +2 -1
- package/src/app/chat/features/TopicListContent/Topic/TopicContent.tsx +2 -1
- package/src/app/chat/settings/features/SubmitAgentButton/SubmitAgentModal.tsx +2 -1
- package/src/app/settings/(mobile)/mobile/index.tsx +2 -1
- package/src/app/settings/common/Common.tsx +14 -3
- package/src/app/settings/features/ThemeSwatches/ThemeSwatchesNeutral.tsx +2 -1
- package/src/app/settings/features/ThemeSwatches/ThemeSwatchesPrimary.tsx +2 -1
- package/src/app/settings/llm/LLM/index.tsx +17 -10
- package/src/const/settings.ts +0 -1
- package/src/database/core/db.ts +41 -2
- package/src/database/core/migrations/migrateSettingsToUser/fixtures/input.json +55 -0
- package/src/database/core/migrations/migrateSettingsToUser/fixtures/output.json +60 -0
- package/src/database/core/migrations/migrateSettingsToUser/index.test.ts +13 -0
- package/src/database/core/migrations/migrateSettingsToUser/index.ts +39 -0
- package/src/database/core/schemas.ts +10 -0
- package/src/database/models/user.ts +54 -0
- package/src/database/schemas/user.ts +57 -0
- package/src/features/AgentSetting/AgentConfig/index.tsx +2 -2
- package/src/features/AvatarWithUpload/index.tsx +6 -2
- package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +2 -2
- package/src/features/Conversation/Error/ApiKeyForm.tsx +3 -3
- package/src/features/Conversation/Error/InvalidAccess.tsx +5 -1
- package/src/features/Conversation/Extras/Translate.tsx +3 -4
- package/src/layout/GlobalLayout/AppTheme.tsx +4 -3
- package/src/layout/GlobalLayout/Locale.tsx +2 -1
- package/src/layout/GlobalLayout/StoreHydration.tsx +7 -2
- package/src/services/_header.ts +3 -2
- package/src/services/user.ts +31 -0
- package/src/store/chat/slices/message/selectors.test.ts +7 -2
- package/src/store/chat/slices/message/selectors.ts +2 -1
- package/src/store/global/hooks/index.ts +0 -1
- package/src/store/global/initialState.ts +3 -1
- package/src/store/global/selectors.ts +1 -0
- package/src/store/global/slices/common/action.test.ts +2 -79
- package/src/store/global/slices/common/action.ts +37 -61
- package/src/store/global/slices/common/initialState.ts +0 -34
- package/src/store/global/slices/common/selectors.ts +2 -7
- package/src/store/global/slices/preference/action.test.ts +92 -0
- package/src/store/global/slices/preference/action.ts +75 -0
- package/src/store/global/slices/preference/initialState.ts +45 -0
- package/src/store/global/slices/preference/selectors.ts +10 -0
- package/src/store/global/slices/settings/action.test.ts +68 -39
- package/src/store/global/slices/settings/action.ts +26 -50
- package/src/store/global/slices/settings/initialState.ts +8 -6
- package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +100 -0
- package/src/store/global/slices/settings/selectors/__snapshots__/selectors.test.ts.snap +132 -0
- package/src/store/global/slices/settings/selectors/index.ts +2 -0
- package/src/store/global/slices/settings/selectors/modelProvider.test.ts +100 -0
- package/src/store/global/slices/settings/selectors/modelProvider.ts +64 -0
- package/src/store/global/slices/settings/{selectors.test.ts → selectors/selectors.test.ts} +2 -97
- package/src/store/global/slices/settings/selectors/settings.ts +58 -0
- package/src/store/global/store.ts +11 -36
- package/src/store/session/slices/agent/action.ts +1 -1
- package/src/types/settings/base.ts +13 -0
- package/src/types/settings/index.ts +34 -0
- package/src/types/settings/modelProvider.ts +17 -0
- package/src/types/settings/tts.ts +10 -0
- package/src/utils/difference.ts +12 -0
- package/tests/utils.tsx +8 -0
- package/tsconfig.json +9 -8
- package/vitest.config.ts +1 -0
- package/src/store/global/hooks/useHydrated.ts +0 -18
- package/src/store/global/slices/settings/selectors.ts +0 -105
- package/src/types/settings.ts +0 -68
|
@@ -1,75 +1,102 @@
|
|
|
1
|
-
import { act, renderHook } from '@testing-library/react';
|
|
1
|
+
import { act, renderHook, waitFor } from '@testing-library/react';
|
|
2
2
|
import { DeepPartial } from 'utility-types';
|
|
3
3
|
import { describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { withSWR } from '~test-utils';
|
|
4
5
|
|
|
5
6
|
import { DEFAULT_AGENT, DEFAULT_SETTINGS } from '@/const/settings';
|
|
7
|
+
import { userService } from '@/services/user';
|
|
6
8
|
import { useGlobalStore } from '@/store/global';
|
|
7
9
|
import { SettingsTabs } from '@/store/global/initialState';
|
|
8
10
|
import { LobeAgentSettings } from '@/types/session';
|
|
9
11
|
import { GlobalSettings, OpenAIConfig } from '@/types/settings';
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
vi.
|
|
16
|
-
|
|
13
|
+
// Mock userService
|
|
14
|
+
vi.mock('@/services/user', () => ({
|
|
15
|
+
userService: {
|
|
16
|
+
updateUserSettings: vi.fn(),
|
|
17
|
+
resetUserSettings: vi.fn(),
|
|
18
|
+
},
|
|
17
19
|
}));
|
|
18
20
|
|
|
19
21
|
describe('SettingsAction', () => {
|
|
20
22
|
describe('importAppSettings', () => {
|
|
21
|
-
it('should import app settings', () => {
|
|
23
|
+
it('should import app settings', async () => {
|
|
22
24
|
const { result } = renderHook(() => useGlobalStore());
|
|
23
25
|
const newSettings: GlobalSettings = {
|
|
24
26
|
...DEFAULT_SETTINGS,
|
|
25
27
|
themeMode: 'dark',
|
|
26
28
|
};
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// Mock the internal setSettings function call
|
|
31
|
+
const setSettingsSpy = vi.spyOn(result.current, 'setSettings');
|
|
32
|
+
|
|
33
|
+
// Perform the action
|
|
34
|
+
await act(async () => {
|
|
35
|
+
await result.current.importAppSettings(newSettings);
|
|
30
36
|
});
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
// Assert that setSettings was called with the correct settings
|
|
39
|
+
expect(setSettingsSpy).toHaveBeenCalledWith({
|
|
40
|
+
...DEFAULT_SETTINGS,
|
|
41
|
+
password: undefined,
|
|
42
|
+
themeMode: 'dark',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Assert that the state has been updated
|
|
46
|
+
expect(userService.updateUserSettings).toHaveBeenCalledWith({ themeMode: 'dark' });
|
|
47
|
+
|
|
48
|
+
// Restore the spy
|
|
49
|
+
setSettingsSpy.mockRestore();
|
|
33
50
|
});
|
|
34
51
|
});
|
|
35
52
|
|
|
36
53
|
describe('resetSettings', () => {
|
|
37
|
-
it('should reset settings to default', () => {
|
|
54
|
+
it('should reset settings to default', async () => {
|
|
38
55
|
const { result } = renderHook(() => useGlobalStore());
|
|
39
56
|
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
// Perform the action
|
|
58
|
+
await act(async () => {
|
|
59
|
+
await result.current.resetSettings();
|
|
42
60
|
});
|
|
43
61
|
|
|
44
|
-
|
|
62
|
+
// Assert that resetUserSettings was called
|
|
63
|
+
expect(userService.resetUserSettings).toHaveBeenCalled();
|
|
64
|
+
|
|
65
|
+
// Assert that the state has been updated to default settings
|
|
66
|
+
expect(result.current.settings).toEqual({});
|
|
45
67
|
});
|
|
46
68
|
});
|
|
47
69
|
|
|
48
70
|
describe('setOpenAIConfig', () => {
|
|
49
|
-
it('should set OpenAI configuration', () => {
|
|
71
|
+
it('should set OpenAI configuration', async () => {
|
|
50
72
|
const { result } = renderHook(() => useGlobalStore());
|
|
51
|
-
const openAIConfig: Partial<OpenAIConfig> = { OPENAI_API_KEY: 'test' };
|
|
73
|
+
const openAIConfig: Partial<OpenAIConfig> = { OPENAI_API_KEY: 'test-key' };
|
|
52
74
|
|
|
53
|
-
|
|
54
|
-
|
|
75
|
+
// Perform the action
|
|
76
|
+
await act(async () => {
|
|
77
|
+
await result.current.setOpenAIConfig(openAIConfig);
|
|
55
78
|
});
|
|
56
79
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
// Assert that updateUserSettings was called with the correct OpenAI configuration
|
|
81
|
+
expect(userService.updateUserSettings).toHaveBeenCalledWith({
|
|
82
|
+
languageModel: {
|
|
83
|
+
openAI: openAIConfig,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
60
86
|
});
|
|
61
87
|
});
|
|
62
|
-
|
|
63
88
|
describe('setSettings', () => {
|
|
64
|
-
it('should set partial settings', () => {
|
|
89
|
+
it('should set partial settings', async () => {
|
|
65
90
|
const { result } = renderHook(() => useGlobalStore());
|
|
66
91
|
const partialSettings: Partial<GlobalSettings> = { themeMode: 'dark' };
|
|
67
92
|
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
// Perform the action
|
|
94
|
+
await act(async () => {
|
|
95
|
+
await result.current.setSettings(partialSettings);
|
|
70
96
|
});
|
|
71
97
|
|
|
72
|
-
|
|
98
|
+
// Assert that updateUserSettings was called with the correct settings
|
|
99
|
+
expect(userService.updateUserSettings).toHaveBeenCalledWith(partialSettings);
|
|
73
100
|
});
|
|
74
101
|
});
|
|
75
102
|
|
|
@@ -86,32 +113,34 @@ describe('SettingsAction', () => {
|
|
|
86
113
|
});
|
|
87
114
|
|
|
88
115
|
describe('switchThemeMode', () => {
|
|
89
|
-
it('should switch theme mode', () => {
|
|
116
|
+
it('should switch theme mode', async () => {
|
|
90
117
|
const { result } = renderHook(() => useGlobalStore());
|
|
118
|
+
const themeMode = 'light';
|
|
91
119
|
|
|
92
|
-
|
|
93
|
-
|
|
120
|
+
// Perform the action
|
|
121
|
+
await act(async () => {
|
|
122
|
+
await result.current.switchThemeMode(themeMode);
|
|
94
123
|
});
|
|
95
124
|
|
|
96
|
-
|
|
125
|
+
// Assert that updateUserSettings was called with the correct theme mode
|
|
126
|
+
expect(userService.updateUserSettings).toHaveBeenCalledWith({ themeMode });
|
|
97
127
|
});
|
|
98
128
|
});
|
|
99
129
|
|
|
100
130
|
describe('updateDefaultAgent', () => {
|
|
101
|
-
it('should update default agent settings', () => {
|
|
131
|
+
it('should update default agent settings', async () => {
|
|
102
132
|
const { result } = renderHook(() => useGlobalStore());
|
|
103
|
-
const updatedAgent:
|
|
133
|
+
const updatedAgent: Partial<LobeAgentSettings> = {
|
|
104
134
|
meta: { title: 'docs' },
|
|
105
135
|
};
|
|
106
136
|
|
|
107
|
-
|
|
108
|
-
|
|
137
|
+
// Perform the action
|
|
138
|
+
await act(async () => {
|
|
139
|
+
await result.current.updateDefaultAgent(updatedAgent);
|
|
109
140
|
});
|
|
110
141
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
...updatedAgent,
|
|
114
|
-
});
|
|
142
|
+
// Assert that updateUserSettings was called with the merged agent settings
|
|
143
|
+
expect(userService.updateUserSettings).toHaveBeenCalledWith({ defaultAgent: updatedAgent });
|
|
115
144
|
});
|
|
116
145
|
});
|
|
117
146
|
});
|
|
@@ -1,42 +1,27 @@
|
|
|
1
1
|
import { ThemeMode } from 'antd-style';
|
|
2
2
|
import isEqual from 'fast-deep-equal';
|
|
3
|
-
import { produce } from 'immer';
|
|
4
3
|
import { DeepPartial } from 'utility-types';
|
|
5
4
|
import type { StateCreator } from 'zustand/vanilla';
|
|
6
5
|
|
|
7
|
-
import {
|
|
6
|
+
import { userService } from '@/services/user';
|
|
8
7
|
import type { GlobalStore } from '@/store/global';
|
|
9
8
|
import { SettingsTabs } from '@/store/global/initialState';
|
|
10
9
|
import { LobeAgentSettings } from '@/types/session';
|
|
11
10
|
import type { GlobalSettings, OpenAIConfig } from '@/types/settings';
|
|
11
|
+
import { difference } from '@/utils/difference';
|
|
12
12
|
import { merge } from '@/utils/merge';
|
|
13
|
-
import { setNamespace } from '@/utils/storeDebug';
|
|
14
|
-
|
|
15
|
-
const n = setNamespace('settings');
|
|
16
13
|
|
|
17
14
|
/**
|
|
18
15
|
* 设置操作
|
|
19
16
|
*/
|
|
20
17
|
export interface SettingsAction {
|
|
21
|
-
importAppSettings: (settings: GlobalSettings) => void
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
resetSettings: () => void;
|
|
26
|
-
setOpenAIConfig: (config: Partial<OpenAIConfig>) => void;
|
|
27
|
-
/**
|
|
28
|
-
* 设置部分配置设置
|
|
29
|
-
* @param settings - 部分配置设置
|
|
30
|
-
*/
|
|
31
|
-
setSettings: (settings: DeepPartial<GlobalSettings>) => void;
|
|
32
|
-
|
|
18
|
+
importAppSettings: (settings: GlobalSettings) => Promise<void>;
|
|
19
|
+
resetSettings: () => Promise<void>;
|
|
20
|
+
setOpenAIConfig: (config: Partial<OpenAIConfig>) => Promise<void>;
|
|
21
|
+
setSettings: (settings: DeepPartial<GlobalSettings>) => Promise<void>;
|
|
33
22
|
switchSettingTabs: (tab: SettingsTabs) => void;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* @param themeMode - 主题模式
|
|
37
|
-
*/
|
|
38
|
-
switchThemeMode: (themeMode: ThemeMode) => void;
|
|
39
|
-
updateDefaultAgent: (agent: DeepPartial<LobeAgentSettings>) => void;
|
|
23
|
+
switchThemeMode: (themeMode: ThemeMode) => Promise<void>;
|
|
24
|
+
updateDefaultAgent: (agent: DeepPartial<LobeAgentSettings>) => Promise<void>;
|
|
40
25
|
}
|
|
41
26
|
|
|
42
27
|
export const createSettingsSlice: StateCreator<
|
|
@@ -45,49 +30,40 @@ export const createSettingsSlice: StateCreator<
|
|
|
45
30
|
[],
|
|
46
31
|
SettingsAction
|
|
47
32
|
> = (set, get) => ({
|
|
48
|
-
importAppSettings: (importAppSettings) => {
|
|
33
|
+
importAppSettings: async (importAppSettings) => {
|
|
49
34
|
const { setSettings } = get();
|
|
50
35
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
36
|
const { password: _, ...settings } = importAppSettings;
|
|
52
37
|
|
|
53
|
-
setSettings(
|
|
54
|
-
...settings,
|
|
55
|
-
// 如果用户存在用户头像,那么不做导入
|
|
56
|
-
avatar: !get().settings.avatar ? settings.avatar : get().settings.avatar,
|
|
57
|
-
});
|
|
58
|
-
},
|
|
59
|
-
resetDefaultAgent: () => {
|
|
60
|
-
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
61
|
-
draft.defaultAgent = DEFAULT_AGENT;
|
|
62
|
-
});
|
|
63
|
-
set({ settings }, false, n('resetDefaultAgent'));
|
|
38
|
+
await setSettings(settings);
|
|
64
39
|
},
|
|
65
|
-
resetSettings: () => {
|
|
66
|
-
|
|
40
|
+
resetSettings: async () => {
|
|
41
|
+
await userService.resetUserSettings();
|
|
42
|
+
await get().refreshUserConfig();
|
|
67
43
|
},
|
|
68
|
-
setOpenAIConfig: (config) => {
|
|
69
|
-
get().setSettings({ languageModel: { openAI: config } });
|
|
44
|
+
setOpenAIConfig: async (config) => {
|
|
45
|
+
await get().setSettings({ languageModel: { openAI: config } });
|
|
70
46
|
},
|
|
71
|
-
setSettings: (settings) => {
|
|
72
|
-
const prevSetting = get()
|
|
47
|
+
setSettings: async (settings) => {
|
|
48
|
+
const { settings: prevSetting, defaultSettings } = get();
|
|
49
|
+
|
|
73
50
|
const nextSettings = merge(prevSetting, settings);
|
|
74
51
|
|
|
75
52
|
if (isEqual(prevSetting, nextSettings)) return;
|
|
76
53
|
|
|
77
|
-
|
|
54
|
+
const diffs = difference(nextSettings, defaultSettings);
|
|
55
|
+
|
|
56
|
+
await userService.updateUserSettings(diffs);
|
|
57
|
+
await get().refreshUserConfig();
|
|
78
58
|
},
|
|
79
59
|
|
|
80
60
|
switchSettingTabs: (tab) => {
|
|
81
61
|
set({ settingsTab: tab });
|
|
82
62
|
},
|
|
83
|
-
switchThemeMode: (themeMode) => {
|
|
84
|
-
get().setSettings({ themeMode });
|
|
63
|
+
switchThemeMode: async (themeMode) => {
|
|
64
|
+
await get().setSettings({ themeMode });
|
|
85
65
|
},
|
|
86
|
-
updateDefaultAgent: (
|
|
87
|
-
|
|
88
|
-
draft.defaultAgent = merge(draft.defaultAgent, agent);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
set({ settings }, false, n('updateDefaultAgent', agent));
|
|
66
|
+
updateDefaultAgent: async (defaultAgent) => {
|
|
67
|
+
await get().setSettings({ defaultAgent });
|
|
92
68
|
},
|
|
93
69
|
});
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { DeepPartial } from 'utility-types';
|
|
2
|
+
|
|
1
3
|
import { DEFAULT_SETTINGS } from '@/const/settings';
|
|
2
|
-
import
|
|
4
|
+
import { GlobalServerConfig, GlobalSettings } from '@/types/settings';
|
|
3
5
|
|
|
4
6
|
export interface GlobalSettingsState {
|
|
7
|
+
avatar?: string;
|
|
8
|
+
defaultSettings: GlobalSettings;
|
|
5
9
|
serverConfig: GlobalServerConfig;
|
|
6
|
-
|
|
7
|
-
* @localStorage
|
|
8
|
-
*/
|
|
9
|
-
settings: GlobalSettings;
|
|
10
|
+
settings: DeepPartial<GlobalSettings>;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export const initialSettingsState: GlobalSettingsState = {
|
|
14
|
+
defaultSettings: DEFAULT_SETTINGS,
|
|
13
15
|
serverConfig: {},
|
|
14
|
-
settings:
|
|
16
|
+
settings: {},
|
|
15
17
|
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`modelProviderSelectors > CUSTOM_MODELS > custom deletion, addition, and renaming of models 1`] = `
|
|
4
|
+
[
|
|
5
|
+
{
|
|
6
|
+
"displayName": "llama",
|
|
7
|
+
"name": "llama",
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"displayName": "claude-2",
|
|
11
|
+
"name": "claude-2",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"displayName": "gpt-4-32k",
|
|
15
|
+
"name": "gpt-4-1106-preview",
|
|
16
|
+
},
|
|
17
|
+
]
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
exports[`modelProviderSelectors > CUSTOM_MODELS > duplicate naming model 1`] = `
|
|
21
|
+
[
|
|
22
|
+
{
|
|
23
|
+
"displayName": "gpt-3.5-turbo",
|
|
24
|
+
"name": "gpt-3.5-turbo",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"displayName": "gpt-3.5-turbo-1106",
|
|
28
|
+
"name": "gpt-3.5-turbo-1106",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"displayName": "gpt-3.5-turbo-16k",
|
|
32
|
+
"name": "gpt-3.5-turbo-16k",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"displayName": "gpt-4",
|
|
36
|
+
"name": "gpt-4",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"displayName": "gpt-4-32k",
|
|
40
|
+
"name": "gpt-4-32k",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"displayName": "gpt-4-vision-preview",
|
|
44
|
+
"name": "gpt-4-vision-preview",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"displayName": "gpt-4-32k",
|
|
48
|
+
"name": "gpt-4-1106-preview",
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
exports[`modelProviderSelectors > CUSTOM_MODELS > only add the model 1`] = `
|
|
54
|
+
[
|
|
55
|
+
{
|
|
56
|
+
"displayName": "gpt-3.5-turbo",
|
|
57
|
+
"name": "gpt-3.5-turbo",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"displayName": "gpt-3.5-turbo-1106",
|
|
61
|
+
"name": "gpt-3.5-turbo-1106",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"displayName": "gpt-3.5-turbo-16k",
|
|
65
|
+
"name": "gpt-3.5-turbo-16k",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"displayName": "gpt-4",
|
|
69
|
+
"name": "gpt-4",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"displayName": "gpt-4-32k",
|
|
73
|
+
"name": "gpt-4-32k",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"displayName": "gpt-4-1106-preview",
|
|
77
|
+
"name": "gpt-4-1106-preview",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"displayName": "gpt-4-vision-preview",
|
|
81
|
+
"name": "gpt-4-vision-preview",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"displayName": "model1",
|
|
85
|
+
"name": "model1",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"displayName": "model2",
|
|
89
|
+
"name": "model2",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"displayName": "model3",
|
|
93
|
+
"name": "model3",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"displayName": "model4",
|
|
97
|
+
"name": "model4",
|
|
98
|
+
},
|
|
99
|
+
]
|
|
100
|
+
`;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`settingsSelectors > currentSettings > should merge DEFAULT_SETTINGS and s.settings correctly 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"avatar": "avatar.jpg",
|
|
6
|
+
"defaultAgent": {
|
|
7
|
+
"config": {
|
|
8
|
+
"model": "gpt-3.5-turbo",
|
|
9
|
+
"params": {},
|
|
10
|
+
"systemRole": "",
|
|
11
|
+
"tts": {
|
|
12
|
+
"showAllLocaleVoice": false,
|
|
13
|
+
"sttLocale": "auto",
|
|
14
|
+
"ttsService": "openai",
|
|
15
|
+
"voice": {
|
|
16
|
+
"openai": "alloy",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
"meta": {
|
|
21
|
+
"avatar": "Default Agent",
|
|
22
|
+
"description": "Default agent for testing",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
"fontSize": 14,
|
|
26
|
+
"language": "en-US",
|
|
27
|
+
"languageModel": {
|
|
28
|
+
"openAI": {
|
|
29
|
+
"OPENAI_API_KEY": "openai-api-key",
|
|
30
|
+
"endpoint": "https://openai-endpoint.com",
|
|
31
|
+
"models": [
|
|
32
|
+
"gpt-3.5-turbo",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
"neutralColor": "sand",
|
|
37
|
+
"password": "password123",
|
|
38
|
+
"primaryColor": "blue",
|
|
39
|
+
"themeMode": "light",
|
|
40
|
+
"tts": {
|
|
41
|
+
"openAI": {
|
|
42
|
+
"sttModel": "whisper-1",
|
|
43
|
+
"ttsModel": "tts-1",
|
|
44
|
+
},
|
|
45
|
+
"sttAutoStop": true,
|
|
46
|
+
"sttServer": "openai",
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
exports[`settingsSelectors > currentTTS > should merge DEFAULT_TTS_CONFIG and s.settings.tts correctly 1`] = `
|
|
52
|
+
{
|
|
53
|
+
"openAI": {
|
|
54
|
+
"sttModel": "whisper-2",
|
|
55
|
+
"ttsModel": "tts-1",
|
|
56
|
+
},
|
|
57
|
+
"sttAutoStop": false,
|
|
58
|
+
"sttServer": "openai",
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
exports[`settingsSelectors > dalleConfig > should return the dalle configuration 1`] = `
|
|
63
|
+
{
|
|
64
|
+
"apiKey": "dalle-api-key",
|
|
65
|
+
"autoGenerate": true,
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
exports[`settingsSelectors > defaultAgent > should merge DEFAULT_AGENT and s.settings.defaultAgent correctly 1`] = `
|
|
70
|
+
{
|
|
71
|
+
"config": {
|
|
72
|
+
"autoCreateTopicThreshold": 2,
|
|
73
|
+
"displayMode": "chat",
|
|
74
|
+
"enableAutoCreateTopic": true,
|
|
75
|
+
"historyCount": 1,
|
|
76
|
+
"model": "gpt-3.5-turbo",
|
|
77
|
+
"params": {
|
|
78
|
+
"frequency_penalty": 0,
|
|
79
|
+
"presence_penalty": 0,
|
|
80
|
+
"temperature": 0.6,
|
|
81
|
+
"top_p": 1,
|
|
82
|
+
},
|
|
83
|
+
"plugins": [],
|
|
84
|
+
"systemRole": "user",
|
|
85
|
+
"tts": {
|
|
86
|
+
"showAllLocaleVoice": false,
|
|
87
|
+
"sttLocale": "auto",
|
|
88
|
+
"ttsService": "openai",
|
|
89
|
+
"voice": {
|
|
90
|
+
"openai": "alloy",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
"meta": {
|
|
95
|
+
"avatar": "agent-avatar.jpg",
|
|
96
|
+
"description": "Test agent",
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
`;
|
|
100
|
+
|
|
101
|
+
exports[`settingsSelectors > defaultAgentConfig > should merge DEFAULT_AGENT_CONFIG and defaultAgent(s).config correctly 1`] = `
|
|
102
|
+
{
|
|
103
|
+
"autoCreateTopicThreshold": 2,
|
|
104
|
+
"displayMode": "chat",
|
|
105
|
+
"enableAutoCreateTopic": true,
|
|
106
|
+
"historyCount": 1,
|
|
107
|
+
"model": "gpt-3.5-turbo",
|
|
108
|
+
"params": {
|
|
109
|
+
"frequency_penalty": 0,
|
|
110
|
+
"presence_penalty": 0,
|
|
111
|
+
"temperature": 0.7,
|
|
112
|
+
"top_p": 1,
|
|
113
|
+
},
|
|
114
|
+
"plugins": [],
|
|
115
|
+
"systemRole": "user",
|
|
116
|
+
"tts": {
|
|
117
|
+
"showAllLocaleVoice": false,
|
|
118
|
+
"sttLocale": "auto",
|
|
119
|
+
"ttsService": "openai",
|
|
120
|
+
"voice": {
|
|
121
|
+
"openai": "alloy",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
exports[`settingsSelectors > defaultAgentMeta > should merge DEFAULT_AGENT_META and defaultAgent(s).meta correctly 1`] = `
|
|
128
|
+
{
|
|
129
|
+
"avatar": "agent-avatar.jpg",
|
|
130
|
+
"description": "Test agent",
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { GlobalStore } from '../../../store';
|
|
2
|
+
import { modelProviderSelectors } from './modelProvider';
|
|
3
|
+
|
|
4
|
+
describe('modelProviderSelectors', () => {
|
|
5
|
+
describe('CUSTOM_MODELS', () => {
|
|
6
|
+
it('custom deletion, addition, and renaming of models', () => {
|
|
7
|
+
const s = {
|
|
8
|
+
serverConfig: {
|
|
9
|
+
customModelName:
|
|
10
|
+
'-all,+llama,+claude-2,-gpt-3.5-turbo,gpt-4-1106-preview=gpt-4-turbo,gpt-4-1106-preview=gpt-4-32k',
|
|
11
|
+
},
|
|
12
|
+
settings: {
|
|
13
|
+
languageModel: {
|
|
14
|
+
openAI: {},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
} as unknown as GlobalStore;
|
|
18
|
+
|
|
19
|
+
const result = modelProviderSelectors.modelList(s);
|
|
20
|
+
|
|
21
|
+
expect(result).toMatchSnapshot();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('duplicate naming model', () => {
|
|
25
|
+
const s = {
|
|
26
|
+
serverConfig: {},
|
|
27
|
+
settings: {
|
|
28
|
+
languageModel: {
|
|
29
|
+
openAI: {
|
|
30
|
+
customModelName: 'gpt-4-1106-preview=gpt-4-turbo,gpt-4-1106-preview=gpt-4-32k',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
} as unknown as GlobalStore;
|
|
35
|
+
|
|
36
|
+
const result = modelProviderSelectors.modelList(s);
|
|
37
|
+
|
|
38
|
+
expect(result).toMatchSnapshot();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should delete model', () => {
|
|
42
|
+
const s = {
|
|
43
|
+
serverConfig: {
|
|
44
|
+
customModelName: '-gpt-4',
|
|
45
|
+
},
|
|
46
|
+
settings: {
|
|
47
|
+
languageModel: {
|
|
48
|
+
openAI: {},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
} as unknown as GlobalStore;
|
|
52
|
+
|
|
53
|
+
const result = modelProviderSelectors.modelList(s);
|
|
54
|
+
|
|
55
|
+
expect(result).toEqual([
|
|
56
|
+
{
|
|
57
|
+
displayName: 'gpt-3.5-turbo',
|
|
58
|
+
name: 'gpt-3.5-turbo',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
displayName: 'gpt-3.5-turbo-1106',
|
|
62
|
+
name: 'gpt-3.5-turbo-1106',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
displayName: 'gpt-3.5-turbo-16k',
|
|
66
|
+
name: 'gpt-3.5-turbo-16k',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
displayName: 'gpt-4-32k',
|
|
70
|
+
name: 'gpt-4-32k',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
displayName: 'gpt-4-1106-preview',
|
|
74
|
+
name: 'gpt-4-1106-preview',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
displayName: 'gpt-4-vision-preview',
|
|
78
|
+
name: 'gpt-4-vision-preview',
|
|
79
|
+
},
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('only add the model', () => {
|
|
84
|
+
const s = {
|
|
85
|
+
serverConfig: {},
|
|
86
|
+
settings: {
|
|
87
|
+
languageModel: {
|
|
88
|
+
openAI: {
|
|
89
|
+
customModelName: 'model1,model2,model3,model4',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
} as unknown as GlobalStore;
|
|
94
|
+
|
|
95
|
+
const result = modelProviderSelectors.modelList(s);
|
|
96
|
+
|
|
97
|
+
expect(result).toMatchSnapshot();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|