@lobehub/chat 0.122.2 → 0.122.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +8 -8
  3. package/README.zh-CN.md +8 -8
  4. package/docs/Deployment/Docker-Deployment.md +118 -0
  5. package/docs/Deployment/Docker-Deployment.zh-CN.md +118 -0
  6. package/package.json +1 -4
  7. package/src/app/api/config/route.ts +3 -1
  8. package/src/app/api/openai/chat/createChatCompletion.ts +1 -1
  9. package/src/app/api/openai/createBizOpenAI/index.ts +1 -1
  10. package/src/app/api/plugin/gateway/route.ts +31 -5
  11. package/src/app/chat/(mobile)/features/SessionHeader.tsx +2 -1
  12. package/src/app/chat/features/ChatHeader/SettingButton.tsx +1 -1
  13. package/src/app/chat/features/ChatHeader/ShareButton/ShareModal.tsx +2 -1
  14. package/src/app/chat/settings/(desktop)/index.tsx +9 -5
  15. package/src/app/chat/settings/features/SubmitAgentButton/SubmitAgentModal.tsx +2 -1
  16. package/src/app/settings/(mobile)/mobile/index.tsx +2 -1
  17. package/src/app/settings/common/Common.tsx +14 -3
  18. package/src/app/settings/features/ThemeSwatches/ThemeSwatchesNeutral.tsx +2 -1
  19. package/src/app/settings/features/ThemeSwatches/ThemeSwatchesPrimary.tsx +2 -1
  20. package/src/app/settings/llm/LLM/index.tsx +17 -10
  21. package/src/const/settings.ts +0 -1
  22. package/src/database/core/db.ts +41 -2
  23. package/src/database/core/migrations/migrateSettingsToUser/fixtures/input.json +55 -0
  24. package/src/database/core/migrations/migrateSettingsToUser/fixtures/output.json +60 -0
  25. package/src/database/core/migrations/migrateSettingsToUser/index.test.ts +13 -0
  26. package/src/database/core/migrations/migrateSettingsToUser/index.ts +39 -0
  27. package/src/database/core/schemas.ts +10 -0
  28. package/src/database/models/user.ts +54 -0
  29. package/src/database/schemas/user.ts +57 -0
  30. package/src/features/AgentSetting/AgentConfig/index.tsx +2 -2
  31. package/src/features/AvatarWithUpload/index.tsx +6 -2
  32. package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +2 -2
  33. package/src/features/Conversation/Error/ApiKeyForm.tsx +3 -3
  34. package/src/features/Conversation/Error/InvalidAccess.tsx +5 -1
  35. package/src/features/Conversation/Extras/Translate.tsx +3 -4
  36. package/src/layout/GlobalLayout/AppTheme.tsx +4 -3
  37. package/src/layout/GlobalLayout/Locale.tsx +2 -1
  38. package/src/layout/GlobalLayout/StoreHydration.tsx +7 -2
  39. package/src/services/_header.ts +3 -2
  40. package/src/services/chat.ts +2 -1
  41. package/src/services/user.ts +31 -0
  42. package/src/store/chat/slices/message/selectors.test.ts +7 -2
  43. package/src/store/chat/slices/message/selectors.ts +2 -1
  44. package/src/store/global/hooks/index.ts +0 -1
  45. package/src/store/global/initialState.ts +3 -1
  46. package/src/store/global/selectors.ts +1 -0
  47. package/src/store/global/slices/common/action.test.ts +2 -79
  48. package/src/store/global/slices/common/action.ts +37 -61
  49. package/src/store/global/slices/common/initialState.ts +0 -34
  50. package/src/store/global/slices/common/selectors.ts +2 -7
  51. package/src/store/global/slices/preference/action.test.ts +92 -0
  52. package/src/store/global/slices/preference/action.ts +75 -0
  53. package/src/store/global/slices/preference/initialState.ts +45 -0
  54. package/src/store/global/slices/preference/selectors.ts +10 -0
  55. package/src/store/global/slices/settings/action.test.ts +68 -39
  56. package/src/store/global/slices/settings/action.ts +26 -50
  57. package/src/store/global/slices/settings/initialState.ts +8 -6
  58. package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +100 -0
  59. package/src/store/global/slices/settings/{__snapshots__ → selectors/__snapshots__}/selectors.test.ts.snap +1 -115
  60. package/src/store/global/slices/settings/selectors/index.ts +2 -0
  61. package/src/store/global/slices/settings/selectors/modelProvider.test.ts +100 -0
  62. package/src/store/global/slices/settings/selectors/modelProvider.ts +64 -0
  63. package/src/store/global/slices/settings/{selectors.test.ts → selectors/selectors.test.ts} +2 -97
  64. package/src/store/global/slices/settings/selectors/settings.ts +58 -0
  65. package/src/store/global/store.ts +11 -36
  66. package/src/store/session/slices/agent/action.ts +1 -1
  67. package/src/types/settings/base.ts +13 -0
  68. package/src/types/settings/index.ts +34 -0
  69. package/src/types/settings/modelProvider.ts +17 -0
  70. package/src/types/settings/tts.ts +10 -0
  71. package/src/utils/difference.ts +12 -0
  72. package/tests/utils.tsx +8 -0
  73. package/tsconfig.json +9 -8
  74. package/vitest.config.ts +1 -0
  75. package/src/store/global/hooks/useHydrated.ts +0 -18
  76. package/src/store/global/slices/settings/selectors.ts +0 -105
  77. package/src/types/settings.ts +0 -68
  78. /package/src/app/api/{openai/errorResponse.test.ts → errorResponse.test.ts} +0 -0
  79. /package/src/app/api/{openai/errorResponse.ts → errorResponse.ts} +0 -0
@@ -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
- beforeEach(() => {
12
- vi.clearAllMocks();
13
- });
14
-
15
- vi.mock('@/utils/uuid', () => ({
16
- nanoid: vi.fn(() => 'unique-id'),
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
- act(() => {
29
- result.current.importAppSettings(newSettings);
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
- expect(result.current.settings).toEqual(newSettings);
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
- act(() => {
41
- result.current.resetSettings();
57
+ // Perform the action
58
+ await act(async () => {
59
+ await result.current.resetSettings();
42
60
  });
43
61
 
44
- expect(result.current.settings).toEqual(DEFAULT_SETTINGS);
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
- act(() => {
54
- result.current.setOpenAIConfig(openAIConfig);
75
+ // Perform the action
76
+ await act(async () => {
77
+ await result.current.setOpenAIConfig(openAIConfig);
55
78
  });
56
79
 
57
- expect(result.current.settings.languageModel.openAI.OPENAI_API_KEY).toEqual(
58
- openAIConfig.OPENAI_API_KEY,
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
- act(() => {
69
- result.current.setSettings(partialSettings);
93
+ // Perform the action
94
+ await act(async () => {
95
+ await result.current.setSettings(partialSettings);
70
96
  });
71
97
 
72
- expect(result.current.settings.themeMode).toEqual('dark');
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
- act(() => {
93
- result.current.switchThemeMode('light');
120
+ // Perform the action
121
+ await act(async () => {
122
+ await result.current.switchThemeMode(themeMode);
94
123
  });
95
124
 
96
- expect(result.current.settings.themeMode).toEqual('light');
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: DeepPartial<LobeAgentSettings> = {
133
+ const updatedAgent: Partial<LobeAgentSettings> = {
104
134
  meta: { title: 'docs' },
105
135
  };
106
136
 
107
- act(() => {
108
- result.current.updateDefaultAgent(updatedAgent);
137
+ // Perform the action
138
+ await act(async () => {
139
+ await result.current.updateDefaultAgent(updatedAgent);
109
140
  });
110
141
 
111
- expect(result.current.settings.defaultAgent).toEqual({
112
- ...DEFAULT_AGENT,
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 { DEFAULT_AGENT, DEFAULT_SETTINGS } from '@/const/settings';
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
- set({ settings: DEFAULT_SETTINGS }, false, n('resetSettings'));
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().settings;
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
- set({ settings: merge(prevSetting, settings) }, false, n('setSettings', settings));
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: (agent) => {
87
- const settings = produce(get().settings, (draft: GlobalSettings) => {
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 type { GlobalServerConfig, GlobalSettings } from '@/types/settings';
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: DEFAULT_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
+ `;
@@ -1,121 +1,12 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`settingsSelectors > 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[`settingsSelectors > 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[`settingsSelectors > 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
- `;
101
-
102
3
  exports[`settingsSelectors > currentSettings > should merge DEFAULT_SETTINGS and s.settings correctly 1`] = `
103
4
  {
104
5
  "avatar": "avatar.jpg",
105
6
  "defaultAgent": {
106
7
  "config": {
107
- "autoCreateTopicThreshold": 2,
108
- "displayMode": "chat",
109
- "enableAutoCreateTopic": true,
110
- "historyCount": 1,
111
8
  "model": "gpt-3.5-turbo",
112
- "params": {
113
- "frequency_penalty": 0,
114
- "presence_penalty": 0,
115
- "temperature": 0.6,
116
- "top_p": 1,
117
- },
118
- "plugins": [],
9
+ "params": {},
119
10
  "systemRole": "",
120
11
  "tts": {
121
12
  "showAllLocaleVoice": false,
@@ -146,11 +37,6 @@ exports[`settingsSelectors > currentSettings > should merge DEFAULT_SETTINGS and
146
37
  "password": "password123",
147
38
  "primaryColor": "blue",
148
39
  "themeMode": "light",
149
- "tool": {
150
- "dalle": {
151
- "autoGenerate": false,
152
- },
153
- },
154
40
  "tts": {
155
41
  "openAI": {
156
42
  "sttModel": "whisper-1",
@@ -0,0 +1,2 @@
1
+ export { modelProviderSelectors } from './modelProvider';
2
+ export { settingsSelectors } from './settings';
@@ -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
+ });