@lobehub/chat 0.161.22 → 0.161.23

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 (74) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/package.json +1 -1
  3. package/src/app/(main)/chat/settings/features/SubmitAgentButton/SubmitAgentModal.tsx +3 -3
  4. package/src/app/(main)/settings/common/features/Common.tsx +1 -1
  5. package/src/app/(main)/settings/common/features/Theme/ThemeSwatches/ThemeSwatchesNeutral.tsx +5 -5
  6. package/src/app/(main)/settings/common/features/Theme/ThemeSwatches/ThemeSwatchesPrimary.tsx +5 -5
  7. package/src/app/(main)/settings/common/features/Theme/index.tsx +5 -4
  8. package/src/app/(main)/settings/llm/Azure/index.tsx +4 -4
  9. package/src/app/(main)/settings/llm/Bedrock/index.tsx +4 -4
  10. package/src/app/(main)/settings/llm/Ollama/Checker.tsx +1 -1
  11. package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +5 -4
  12. package/src/app/(main)/settings/llm/const.ts +2 -1
  13. package/src/const/settings/common.ts +2 -2
  14. package/src/const/settings/index.ts +2 -1
  15. package/src/const/settings/llm.ts +0 -19
  16. package/src/database/client/core/db.ts +19 -0
  17. package/src/database/client/core/schemas.ts +3 -2
  18. package/src/database/client/models/__tests__/user.test.ts +5 -5
  19. package/src/database/client/models/user.ts +2 -3
  20. package/src/database/client/schemas/user.ts +10 -4
  21. package/src/features/AgentSetting/AgentMeta/index.tsx +3 -3
  22. package/src/features/AgentSetting/AgentTTS/index.tsx +2 -2
  23. package/src/features/ChatInput/STT/browser.tsx +2 -2
  24. package/src/features/ChatInput/STT/openai.tsx +2 -2
  25. package/src/features/Conversation/Error/APIKeyForm/Bedrock.tsx +5 -5
  26. package/src/features/Conversation/Error/APIKeyForm/ProviderApiKeyForm.tsx +4 -4
  27. package/src/features/Conversation/Error/AccessCodeForm.tsx +4 -4
  28. package/src/features/Conversation/Extras/TTS/index.tsx +2 -2
  29. package/src/features/Conversation/Plugins/Render/MarkdownType/index.tsx +2 -2
  30. package/src/features/Conversation/components/ChatItem/index.tsx +2 -2
  31. package/src/features/PluginDevModal/LocalForm.tsx +2 -2
  32. package/src/features/PluginStore/index.tsx +6 -2
  33. package/src/features/User/UserPanel/LangButton.tsx +2 -2
  34. package/src/features/User/UserPanel/ThemeButton.tsx +2 -2
  35. package/src/hooks/_header.ts +6 -3
  36. package/src/hooks/useTTS.ts +2 -2
  37. package/src/layout/GlobalProvider/AppTheme.tsx +4 -4
  38. package/src/libs/agent-runtime/types/type.ts +3 -2
  39. package/src/migrations/FromV6ToV7/fixtures/output-v7-from-v1.json +203 -0
  40. package/src/migrations/FromV6ToV7/fixtures/provider-input-v6.json +103 -0
  41. package/src/migrations/FromV6ToV7/fixtures/provider-output-v7.json +118 -0
  42. package/src/migrations/FromV6ToV7/index.ts +101 -0
  43. package/src/migrations/FromV6ToV7/migrations.test.ts +64 -0
  44. package/src/migrations/FromV6ToV7/types/v6.ts +61 -0
  45. package/src/migrations/FromV6ToV7/types/v7.ts +71 -0
  46. package/src/migrations/index.ts +9 -3
  47. package/src/services/__tests__/chat.test.ts +19 -19
  48. package/src/services/__tests__/share.test.ts +2 -2
  49. package/src/services/_auth.test.ts +10 -5
  50. package/src/services/_auth.ts +11 -7
  51. package/src/services/_header.ts +6 -3
  52. package/src/services/ollama.ts +3 -3
  53. package/src/services/user/client.test.ts +1 -1
  54. package/src/store/user/helpers.ts +3 -2
  55. package/src/store/user/selectors.ts +10 -2
  56. package/src/store/user/slices/common/action.test.ts +3 -3
  57. package/src/store/user/slices/common/action.ts +2 -2
  58. package/src/store/user/slices/modelList/action.test.ts +2 -2
  59. package/src/store/user/slices/modelList/action.ts +15 -3
  60. package/src/store/user/slices/modelList/selectors/index.ts +1 -0
  61. package/src/store/user/slices/modelList/selectors/keyVaults.ts +25 -0
  62. package/src/store/user/slices/modelList/selectors/modelConfig.test.ts +1 -1
  63. package/src/store/user/slices/modelList/selectors/modelConfig.ts +0 -5
  64. package/src/store/user/slices/settings/action.test.ts +14 -12
  65. package/src/store/user/slices/settings/action.ts +12 -6
  66. package/src/store/user/slices/settings/selectors/general.test.ts +45 -0
  67. package/src/store/user/slices/settings/selectors/general.ts +40 -0
  68. package/src/store/user/slices/settings/selectors/index.ts +1 -0
  69. package/src/store/user/slices/settings/selectors/settings.test.ts +0 -39
  70. package/src/store/user/slices/settings/selectors/settings.ts +6 -32
  71. package/src/types/user/settings/general.ts +1 -1
  72. package/src/types/user/settings/index.ts +7 -29
  73. package/src/types/user/settings/keyVaults.ts +36 -0
  74. package/src/types/user/settings/modelProvider.ts +4 -40
package/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.161.23](https://github.com/lobehub/lobe-chat/compare/v0.161.22...v0.161.23)
6
+
7
+ <sup>Released on **2024-05-27**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor `keyVaults` and rename `endpoint` to `baseURL`.
12
+
13
+ #### 💄 Styles
14
+
15
+ - **misc**: Fix PluginStore layout.
16
+
17
+ <br/>
18
+
19
+ <details>
20
+ <summary><kbd>Improvements and Fixes</kbd></summary>
21
+
22
+ #### Code refactoring
23
+
24
+ - **misc**: Refactor `keyVaults` and rename `endpoint` to `baseURL`, closes [#2673](https://github.com/lobehub/lobe-chat/issues/2673) ([4049bc7](https://github.com/lobehub/lobe-chat/commit/4049bc7))
25
+
26
+ #### Styles
27
+
28
+ - **misc**: Fix PluginStore layout, closes [#2590](https://github.com/lobehub/lobe-chat/issues/2590) [#2511](https://github.com/lobehub/lobe-chat/issues/2511) ([e1ae39b](https://github.com/lobehub/lobe-chat/commit/e1ae39b))
29
+
30
+ </details>
31
+
32
+ <div align="right">
33
+
34
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
35
+
36
+ </div>
37
+
5
38
  ### [Version 0.161.22](https://github.com/lobehub/lobe-chat/compare/v0.161.21...v0.161.22)
6
39
 
7
40
  <sup>Released on **2024-05-26**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.161.22",
3
+ "version": "0.161.23",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -17,7 +17,7 @@ import { agentSelectors } from '@/store/agent/selectors';
17
17
  import { useSessionStore } from '@/store/session';
18
18
  import { sessionMetaSelectors } from '@/store/session/selectors';
19
19
  import { useUserStore } from '@/store/user';
20
- import { settingsSelectors } from '@/store/user/selectors';
20
+ import { userGeneralSettingsSelectors } from '@/store/user/selectors';
21
21
 
22
22
  const SubmitAgentModal = memo<ModalProps>(({ open, onCancel }) => {
23
23
  const { t } = useTranslation('setting');
@@ -25,7 +25,7 @@ const SubmitAgentModal = memo<ModalProps>(({ open, onCancel }) => {
25
25
  const systemRole = useAgentStore(agentSelectors.currentAgentSystemRole);
26
26
  const theme = useTheme();
27
27
  const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
28
- const language = useUserStore((s) => settingsSelectors.currentSettings(s).language);
28
+ const language = useUserStore((s) => userGeneralSettingsSelectors.currentLanguage(s));
29
29
 
30
30
  const isMetaPass = Boolean(
31
31
  meta && meta.title && meta.description && (meta.tags as string[])?.length > 0 && meta.avatar,
@@ -46,7 +46,7 @@ const SubmitAgentModal = memo<ModalProps>(({ open, onCancel }) => {
46
46
  '### tags',
47
47
  (meta.tags as string[]).join(', '),
48
48
  '### locale',
49
- language === 'auto' ? navigator.language : language,
49
+ language,
50
50
  ].join('\n\n');
51
51
 
52
52
  const url = qs.stringifyUrl({
@@ -110,7 +110,7 @@ const Common = memo(() => {
110
110
  desc: t('settingSystem.accessCode.desc'),
111
111
  hidden: !showAccessCodeConfig,
112
112
  label: t('settingSystem.accessCode.title'),
113
- name: 'password',
113
+ name: ['keyVaults', 'password'],
114
114
  },
115
115
  {
116
116
  children: isSignedIn ? (
@@ -8,17 +8,17 @@ import {
8
8
  import { memo } from 'react';
9
9
 
10
10
  import { useUserStore } from '@/store/user';
11
- import { settingsSelectors } from '@/store/user/selectors';
11
+ import { userGeneralSettingsSelectors } from '@/store/user/selectors';
12
12
 
13
13
  const ThemeSwatchesNeutral = memo(() => {
14
- const [neutralColor, setSettings] = useUserStore((s) => [
15
- settingsSelectors.currentSettings(s).neutralColor,
16
- s.setSettings,
14
+ const [neutralColor, updateGeneralConfig] = useUserStore((s) => [
15
+ userGeneralSettingsSelectors.neutralColor(s),
16
+ s.updateGeneralConfig,
17
17
  ]);
18
18
 
19
19
  const handleSelect = (v: any) => {
20
20
  const name = findCustomThemeName('neutral', v) as NeutralColors;
21
- setSettings({ neutralColor: name || '' });
21
+ updateGeneralConfig({ neutralColor: name || '' });
22
22
  };
23
23
 
24
24
  return (
@@ -8,17 +8,17 @@ import {
8
8
  import { memo } from 'react';
9
9
 
10
10
  import { useUserStore } from '@/store/user';
11
- import { settingsSelectors } from '@/store/user/selectors';
11
+ import { userGeneralSettingsSelectors } from '@/store/user/selectors';
12
12
 
13
13
  const ThemeSwatchesPrimary = memo(() => {
14
- const [primaryColor, setSettings] = useUserStore((s) => [
15
- settingsSelectors.currentSettings(s).primaryColor,
16
- s.setSettings,
14
+ const [primaryColor, updateGeneralConfig] = useUserStore((s) => [
15
+ userGeneralSettingsSelectors.primaryColor(s),
16
+ s.updateGeneralConfig,
17
17
  ]);
18
18
 
19
19
  const handleSelect = (v: any) => {
20
20
  const name = findCustomThemeName('primary', v) as PrimaryColors;
21
- setSettings({ primaryColor: name || '' });
21
+ updateGeneralConfig({ primaryColor: name || '' });
22
22
  };
23
23
 
24
24
  return (
@@ -14,7 +14,7 @@ import { imageUrl } from '@/const/url';
14
14
  import AvatarWithUpload from '@/features/AvatarWithUpload';
15
15
  import { localeOptions } from '@/locales/resources';
16
16
  import { useUserStore } from '@/store/user';
17
- import { settingsSelectors } from '@/store/user/selectors';
17
+ import { settingsSelectors, userGeneralSettingsSelectors } from '@/store/user/selectors';
18
18
  import { switchLang } from '@/utils/client/switchLang';
19
19
 
20
20
  import { ThemeSwatchesNeutral, ThemeSwatchesPrimary } from './ThemeSwatches';
@@ -25,6 +25,7 @@ const Theme = memo(() => {
25
25
  const { t } = useTranslation('setting');
26
26
  const [form] = Form.useForm();
27
27
  const settings = useUserStore(settingsSelectors.currentSettings, isEqual);
28
+ const themeMode = useUserStore(userGeneralSettingsSelectors.currentThemeMode);
28
29
  const [setThemeMode, setSettings] = useUserStore((s) => [s.switchThemeMode, s.setSettings]);
29
30
 
30
31
  useSyncSettings(form);
@@ -40,7 +41,7 @@ const Theme = memo(() => {
40
41
  {
41
42
  children: (
42
43
  <SelectWithImg
43
- defaultValue={settings.themeMode}
44
+ defaultValue={themeMode}
44
45
  height={60}
45
46
  onChange={setThemeMode}
46
47
  options={[
@@ -78,7 +79,7 @@ const Theme = memo(() => {
78
79
  />
79
80
  ),
80
81
  label: t('settingTheme.lang.title'),
81
- name: 'language',
82
+ name: ['general', 'language'],
82
83
  },
83
84
  {
84
85
  children: (
@@ -113,7 +114,7 @@ const Theme = memo(() => {
113
114
  ),
114
115
  desc: t('settingTheme.fontSize.desc'),
115
116
  label: t('settingTheme.fontSize.title'),
116
- name: 'fontSize',
117
+ name: ['general', 'fontSize'],
117
118
  },
118
119
  {
119
120
  children: <ThemeSwatchesPrimary />,
@@ -13,7 +13,7 @@ import { useUserStore } from '@/store/user';
13
13
  import { modelProviderSelectors } from '@/store/user/selectors';
14
14
 
15
15
  import ProviderConfig from '../components/ProviderConfig';
16
- import { LLMProviderApiTokenKey, LLMProviderBaseUrlKey, LLMProviderConfigKey } from '../const';
16
+ import { KeyVaultsConfigKey, LLMProviderApiTokenKey } from '../const';
17
17
 
18
18
  const useStyles = createStyles(({ css, token }) => ({
19
19
  markdown: css`
@@ -57,13 +57,13 @@ const AzureOpenAIProvider = memo(() => {
57
57
  ),
58
58
  desc: t('azure.token.desc'),
59
59
  label: t('azure.token.title'),
60
- name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
60
+ name: [KeyVaultsConfigKey, providerKey, LLMProviderApiTokenKey],
61
61
  },
62
62
  {
63
63
  children: <Input allowClear placeholder={t('azure.endpoint.placeholder')} />,
64
64
  desc: t('azure.endpoint.desc'),
65
65
  label: t('azure.endpoint.title'),
66
- name: [LLMProviderConfigKey, providerKey, LLMProviderBaseUrlKey],
66
+ name: [KeyVaultsConfigKey, providerKey, 'endpoint'],
67
67
  },
68
68
  {
69
69
  children: (
@@ -85,7 +85,7 @@ const AzureOpenAIProvider = memo(() => {
85
85
  </Markdown>
86
86
  ),
87
87
  label: t('azure.azureApiVersion.title'),
88
- name: [LLMProviderConfigKey, providerKey, 'apiVersion'],
88
+ name: [KeyVaultsConfigKey, providerKey, 'apiVersion'],
89
89
  },
90
90
  ]}
91
91
  checkModel={checkModel}
@@ -10,7 +10,7 @@ import { ModelProvider } from '@/libs/agent-runtime';
10
10
  import { GlobalLLMProviderKey } from '@/types/user/settings';
11
11
 
12
12
  import ProviderConfig from '../components/ProviderConfig';
13
- import { LLMProviderConfigKey } from '../const';
13
+ import { KeyVaultsConfigKey } from '../const';
14
14
 
15
15
  const providerKey: GlobalLLMProviderKey = 'bedrock';
16
16
 
@@ -29,7 +29,7 @@ const BedrockProvider = memo(() => {
29
29
  ),
30
30
  desc: t(`${providerKey}.accessKeyId.desc`),
31
31
  label: t(`${providerKey}.accessKeyId.title`),
32
- name: [LLMProviderConfigKey, providerKey, 'accessKeyId'],
32
+ name: [KeyVaultsConfigKey, providerKey, 'accessKeyId'],
33
33
  },
34
34
  {
35
35
  children: (
@@ -40,7 +40,7 @@ const BedrockProvider = memo(() => {
40
40
  ),
41
41
  desc: t(`${providerKey}.secretAccessKey.desc`),
42
42
  label: t(`${providerKey}.secretAccessKey.title`),
43
- name: [LLMProviderConfigKey, providerKey, 'secretAccessKey'],
43
+ name: [KeyVaultsConfigKey, providerKey, 'secretAccessKey'],
44
44
  },
45
45
  {
46
46
  children: (
@@ -55,7 +55,7 @@ const BedrockProvider = memo(() => {
55
55
  ),
56
56
  desc: t(`${providerKey}.region.desc`),
57
57
  label: t(`${providerKey}.region.title`),
58
- name: [LLMProviderConfigKey, providerKey, 'region'],
58
+ name: [KeyVaultsConfigKey, providerKey, 'region'],
59
59
  },
60
60
  ]}
61
61
  checkModel={'anthropic.claude-instant-v1'}
@@ -27,7 +27,7 @@ const OllamaChecker = memo(() => {
27
27
  );
28
28
 
29
29
  const checkConnection = () => {
30
- mutate();
30
+ mutate().catch();
31
31
  };
32
32
 
33
33
  const isMobile = useIsMobile();
@@ -10,6 +10,7 @@ import { Flexbox } from 'react-layout-kit';
10
10
 
11
11
  import { useSyncSettings } from '@/app/(main)/settings/hooks/useSyncSettings';
12
12
  import {
13
+ KeyVaultsConfigKey,
13
14
  LLMProviderApiTokenKey,
14
15
  LLMProviderBaseUrlKey,
15
16
  LLMProviderConfigKey,
@@ -17,7 +18,7 @@ import {
17
18
  } from '@/app/(main)/settings/llm/const';
18
19
  import { FORM_STYLE } from '@/const/layoutTokens';
19
20
  import { useUserStore } from '@/store/user';
20
- import { modelConfigSelectors } from '@/store/user/selectors';
21
+ import { keyVaultsConfigSelectors, modelConfigSelectors } from '@/store/user/selectors';
21
22
  import { GlobalLLMProviderKey } from '@/types/user/settings';
22
23
 
23
24
  import Checker from '../Checker';
@@ -100,7 +101,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
100
101
  s.setSettings,
101
102
  modelConfigSelectors.isProviderEnabled(provider)(s),
102
103
  modelConfigSelectors.isProviderFetchOnClient(provider)(s),
103
- modelConfigSelectors.isProviderEndpointNotEmpty(provider)(s),
104
+ keyVaultsConfigSelectors.isProviderEndpointNotEmpty(provider)(s),
104
105
  ]);
105
106
 
106
107
  useSyncSettings(form);
@@ -117,7 +118,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
117
118
  ),
118
119
  desc: modelT(`${provider}.token.desc` as any),
119
120
  label: modelT(`${provider}.token.title` as any),
120
- name: [LLMProviderConfigKey, provider, LLMProviderApiTokenKey],
121
+ name: [KeyVaultsConfigKey, provider, LLMProviderApiTokenKey],
121
122
  },
122
123
  ];
123
124
 
@@ -128,7 +129,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
128
129
  children: <Input allowClear placeholder={proxyUrl?.placeholder} />,
129
130
  desc: proxyUrl?.desc || t('llm.proxyUrl.desc'),
130
131
  label: proxyUrl?.title || t('llm.proxyUrl.title'),
131
- name: [LLMProviderConfigKey, provider, LLMProviderBaseUrlKey],
132
+ name: [KeyVaultsConfigKey, provider, LLMProviderBaseUrlKey],
132
133
  },
133
134
  (showBrowserRequest || (showEndpoint && isProviderEndpointNotEmpty)) && {
134
135
  children: (
@@ -1,4 +1,5 @@
1
1
  export const LLMProviderConfigKey = 'languageModel';
2
+ export const KeyVaultsConfigKey = 'keyVaults';
2
3
 
3
4
  /**
4
5
  * we use this key to define default api key
@@ -10,7 +11,7 @@ export const LLMProviderApiTokenKey = 'apiKey';
10
11
  * we use this key to define the baseURL
11
12
  * equal OPENAI_PROXY_URL
12
13
  */
13
- export const LLMProviderBaseUrlKey = 'endpoint';
14
+ export const LLMProviderBaseUrlKey = 'baseURL';
14
15
 
15
16
  /**
16
17
  * we use this key to define the custom model name
@@ -1,6 +1,6 @@
1
- import { UserGeneralSettings } from '@/types/user/settings';
1
+ import { UserGeneralConfig } from '@/types/user/settings';
2
2
 
3
- export const DEFAULT_COMMON_SETTINGS: UserGeneralSettings = {
3
+ export const DEFAULT_COMMON_SETTINGS: UserGeneralConfig = {
4
4
  fontSize: 14,
5
5
  language: 'auto',
6
6
  password: '',
@@ -18,10 +18,11 @@ export * from './tts';
18
18
 
19
19
  export const DEFAULT_SETTINGS: UserSettings = {
20
20
  defaultAgent: DEFAULT_AGENT,
21
+ general: DEFAULT_COMMON_SETTINGS,
22
+ keyVaults: {},
21
23
  languageModel: DEFAULT_LLM_CONFIG,
22
24
  sync: DEFAULT_SYNC_CONFIG,
23
25
  systemAgent: DEFAULT_SYSTEM_AGENT_CONFIG,
24
26
  tool: DEFAULT_TOOL_CONFIG,
25
27
  tts: DEFAULT_TTS_CONFIG,
26
- ...DEFAULT_COMMON_SETTINGS,
27
28
  };
@@ -21,85 +21,66 @@ import { UserModelProviderConfig } from '@/types/user/settings';
21
21
 
22
22
  export const DEFAULT_LLM_CONFIG: UserModelProviderConfig = {
23
23
  anthropic: {
24
- apiKey: '',
25
24
  enabled: false,
26
25
  enabledModels: filterEnabledModels(AnthropicProviderCard),
27
26
  },
28
27
  azure: {
29
- apiKey: '',
30
28
  enabled: false,
31
- endpoint: '',
32
29
  },
33
30
  bedrock: {
34
- accessKeyId: '',
35
31
  enabled: false,
36
32
  enabledModels: filterEnabledModels(BedrockProviderCard),
37
- region: 'us-east-1',
38
- secretAccessKey: '',
39
33
  },
40
34
  deepseek: {
41
- apiKey: '',
42
35
  enabled: false,
43
36
  enabledModels: filterEnabledModels(DeepSeekProviderCard),
44
37
  },
45
38
  google: {
46
- apiKey: '',
47
39
  enabled: false,
48
40
  enabledModels: filterEnabledModels(GoogleProviderCard),
49
41
  },
50
42
  groq: {
51
- apiKey: '',
52
43
  enabled: false,
53
44
  enabledModels: filterEnabledModels(GroqProviderCard),
54
45
  },
55
46
  minimax: {
56
- apiKey: '',
57
47
  enabled: false,
58
48
  enabledModels: filterEnabledModels(MinimaxProviderCard),
59
49
  },
60
50
  mistral: {
61
- apiKey: '',
62
51
  enabled: false,
63
52
  enabledModels: filterEnabledModels(MistralProviderCard),
64
53
  },
65
54
  moonshot: {
66
- apiKey: '',
67
55
  enabled: false,
68
56
  enabledModels: filterEnabledModels(MoonshotProviderCard),
69
57
  },
70
58
  ollama: {
71
59
  enabled: true,
72
60
  enabledModels: filterEnabledModels(OllamaProviderCard),
73
- endpoint: '',
74
61
  fetchOnClient: true,
75
62
  },
76
63
  openai: {
77
- apiKey: '',
78
64
  enabled: true,
79
65
  enabledModels: filterEnabledModels(OpenAIProviderCard),
80
66
  },
81
67
  openrouter: {
82
- apiKey: '',
83
68
  enabled: false,
84
69
  enabledModels: filterEnabledModels(OpenRouterProviderCard),
85
70
  },
86
71
  perplexity: {
87
- apiKey: '',
88
72
  enabled: false,
89
73
  enabledModels: filterEnabledModels(PerplexityProviderCard),
90
74
  },
91
75
  togetherai: {
92
- apiKey: '',
93
76
  enabled: false,
94
77
  enabledModels: filterEnabledModels(TogetherAIProviderCard),
95
78
  },
96
79
  zeroone: {
97
- apiKey: '',
98
80
  enabled: false,
99
81
  enabledModels: filterEnabledModels(ZeroOneProviderCard),
100
82
  },
101
83
  zhipu: {
102
- apiKey: '',
103
84
  enabled: false,
104
85
  enabledModels: filterEnabledModels(ZhiPuProviderCard),
105
86
  },
@@ -2,6 +2,7 @@ import Dexie, { Transaction } from 'dexie';
2
2
 
3
3
  import { MigrationLLMSettings } from '@/migrations/FromV3ToV4';
4
4
  import { MigrationAgentChatConfig } from '@/migrations/FromV5ToV6';
5
+ import { MigrationKeyValueSettings } from '@/migrations/FromV6ToV7';
5
6
  import { uuid } from '@/utils/uuid';
6
7
 
7
8
  import { DB_File } from '../schemas/files';
@@ -77,6 +78,10 @@ export class BrowserDB extends Dexie {
77
78
  .stores(dbSchemaV9)
78
79
  .upgrade((trans) => this.upgradeToV10(trans));
79
80
 
81
+ this.version(11)
82
+ .stores(dbSchemaV9)
83
+ .upgrade((trans) => this.upgradeToV11(trans));
84
+
80
85
  this.files = this.table('files');
81
86
  this.sessions = this.table('sessions');
82
87
  this.messages = this.table('messages');
@@ -207,6 +212,20 @@ export class BrowserDB extends Dexie {
207
212
  session.config = MigrationAgentChatConfig.migrateChatConfig(session.config as any);
208
213
  });
209
214
  };
215
+
216
+ /**
217
+ * 2024.05.27
218
+ * migrate apiKey in languageModel to keyVaults
219
+ */
220
+ upgradeToV11 = async (trans: Transaction) => {
221
+ const users = trans.table('users');
222
+
223
+ await users.toCollection().modify((user: DB_User) => {
224
+ if (user.settings) {
225
+ user.settings = MigrationKeyValueSettings.migrateSettings(user.settings as any);
226
+ }
227
+ });
228
+ };
210
229
  }
211
230
 
212
231
  export const browserDB = new BrowserDB();
@@ -76,10 +76,11 @@ export const dbSchemaV7 = {
76
76
  plugins:
77
77
  '&identifier, id, type, manifest.type, manifest.meta.title, manifest.meta.description, manifest.meta.author, createdAt, updatedAt',
78
78
  };
79
+
79
80
  // ************************************** //
80
- // ******* Version 9 - 2024-03-14 ******* //
81
+ // ******* Version 9 - 2024-05-11 ******* //
81
82
  // ************************************** //
82
- // - Added id to `plugins` table
83
+ // - Added tool_call_id to `messages` table
83
84
  export const dbSchemaV9 = {
84
85
  ...dbSchemaV7,
85
86
  messages:
@@ -1,7 +1,5 @@
1
1
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
2
2
 
3
- import { UserSettings } from '@/types/user/settings';
4
-
5
3
  import { UserModel } from '../user';
6
4
 
7
5
  describe('UserModel', () => {
@@ -51,17 +49,19 @@ describe('UserModel', () => {
51
49
  it('should update user settings', async () => {
52
50
  await UserModel.create(userData);
53
51
 
54
- await UserModel.updateSettings({ themeMode: 'dark' });
52
+ await UserModel.updateSettings({ general: { themeMode: 'dark' } });
55
53
 
56
54
  const userInDb = await UserModel.getUser();
57
55
 
58
- expect(userInDb).toHaveProperty('settings', { themeMode: 'dark' });
56
+ expect(userInDb).toHaveProperty('settings', {
57
+ general: { themeMode: 'dark' },
58
+ });
59
59
  });
60
60
 
61
61
  it('should reset user settings', async () => {
62
62
  await UserModel.create(userData);
63
63
 
64
- await UserModel.updateSettings({ themeMode: 'dark' });
64
+ await UserModel.updateSettings({ general: { themeMode: 'dark' } });
65
65
 
66
66
  await UserModel.resetSettings();
67
67
 
@@ -2,10 +2,9 @@ import { DeepPartial } from 'utility-types';
2
2
 
3
3
  import { BaseModel } from '@/database/client/core';
4
4
  import { LobeAgentConfig } from '@/types/agent';
5
- import { UserSettings } from '@/types/user/settings';
6
5
  import { uuid } from '@/utils/uuid';
7
6
 
8
- import { DB_User, DB_UserSchema } from '../schemas/user';
7
+ import { DB_Settings, DB_User, DB_UserSchema } from '../schemas/user';
9
8
 
10
9
  class _UserModel extends BaseModel {
11
10
  constructor() {
@@ -42,7 +41,7 @@ class _UserModel extends BaseModel {
42
41
 
43
42
  // **************** Update *************** //
44
43
 
45
- async updateSettings(settings: DeepPartial<UserSettings>) {
44
+ async updateSettings(settings: DeepPartial<DB_Settings>) {
46
45
  const user = await this.getUser();
47
46
 
48
47
  return this.update(user.id, { settings: settings as any });
@@ -3,16 +3,22 @@ import { z } from 'zod';
3
3
  import { AgentSchema } from '@/database/client/schemas/session';
4
4
  import { LobeMetaDataSchema } from '@/types/meta';
5
5
 
6
+ const generalSechma = z.object({
7
+ fontSize: z.number().default(14),
8
+ language: z.string(),
9
+ neutralColor: z.string().optional(),
10
+ password: z.string(),
11
+ themeMode: z.string(),
12
+ });
13
+
6
14
  const settingsSchema = z.object({
7
15
  defaultAgent: z.object({
8
16
  config: AgentSchema,
9
17
  meta: LobeMetaDataSchema,
10
18
  }),
11
- fontSize: z.number().default(14),
12
- language: z.string(),
19
+ general: generalSechma.partial().optional(),
20
+ keyVaults: z.any().optional(),
13
21
  languageModel: z.any().optional(),
14
- password: z.string(),
15
- themeMode: z.string(),
16
22
  tts: z.object({
17
23
  openAI: z.object({
18
24
  sttModel: z.string(),
@@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
11
11
 
12
12
  import { FORM_STYLE } from '@/const/layoutTokens';
13
13
  import { useUserStore } from '@/store/user';
14
- import { settingsSelectors } from '@/store/user/selectors';
14
+ import { userGeneralSettingsSelectors } from '@/store/user/selectors';
15
15
 
16
16
  import { useStore } from '../store';
17
17
  import { SessionLoadingState } from '../store/initialState';
@@ -30,7 +30,7 @@ const AgentMeta = memo(() => {
30
30
  s.autocompleteMeta,
31
31
  s.autocompleteAllMeta,
32
32
  ]);
33
- const locale = useUserStore(settingsSelectors.currentLanguage);
33
+ const locale = useUserStore(userGeneralSettingsSelectors.currentLanguage);
34
34
  const loading = useStore((s) => s.autocompleteLoading);
35
35
  const meta = useStore((s) => s.meta, isEqual);
36
36
 
@@ -132,4 +132,4 @@ const AgentMeta = memo(() => {
132
132
  return <Form items={[metaData]} itemsType={'group'} variant={'pure'} {...FORM_STYLE} />;
133
133
  });
134
134
 
135
- export default AgentMeta;
135
+ export default AgentMeta;
@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
10
10
 
11
11
  import { FORM_STYLE } from '@/const/layoutTokens';
12
12
  import { useUserStore } from '@/store/user';
13
- import { settingsSelectors } from '@/store/user/selectors';
13
+ import { userGeneralSettingsSelectors } from '@/store/user/selectors';
14
14
 
15
15
  import { useStore } from '../store';
16
16
  import { useAgentSyncSettings } from '../useSyncAgemtSettings';
@@ -24,7 +24,7 @@ const AgentTTS = memo(() => {
24
24
  const { t } = useTranslation('setting');
25
25
  const [form] = Form.useForm();
26
26
  const voiceList = useUserStore((s) => {
27
- const locale = settingsSelectors.currentLanguage(s);
27
+ const locale = userGeneralSettingsSelectors.currentLanguage(s);
28
28
  return (all?: boolean) => new VoiceList(all ? undefined : locale);
29
29
  });
30
30
  const [showAllLocaleVoice, ttsService, updateConfig] = useStore((s) => [
@@ -9,7 +9,7 @@ import { agentSelectors } from '@/store/agent/slices/chat';
9
9
  import { useChatStore } from '@/store/chat';
10
10
  import { chatSelectors } from '@/store/chat/selectors';
11
11
  import { useUserStore } from '@/store/user';
12
- import { settingsSelectors } from '@/store/user/selectors';
12
+ import { settingsSelectors, userGeneralSettingsSelectors } from '@/store/user/selectors';
13
13
  import { ChatMessageError } from '@/types/message';
14
14
  import { getMessageError } from '@/utils/fetch';
15
15
 
@@ -22,7 +22,7 @@ interface STTConfig extends SWRConfiguration {
22
22
  const useBrowserSTT = (config: STTConfig) => {
23
23
  const ttsSettings = useUserStore(settingsSelectors.currentTTS, isEqual);
24
24
  const ttsAgentSettings = useAgentStore(agentSelectors.currentAgentTTS, isEqual);
25
- const locale = useUserStore(settingsSelectors.currentLanguage);
25
+ const locale = useUserStore(userGeneralSettingsSelectors.currentLanguage);
26
26
 
27
27
  const autoStop = ttsSettings.sttAutoStop;
28
28
  const sttLocale =
@@ -12,7 +12,7 @@ import { agentSelectors } from '@/store/agent/selectors';
12
12
  import { useChatStore } from '@/store/chat';
13
13
  import { chatSelectors } from '@/store/chat/slices/message/selectors';
14
14
  import { useUserStore } from '@/store/user';
15
- import { settingsSelectors } from '@/store/user/selectors';
15
+ import { settingsSelectors, userGeneralSettingsSelectors } from '@/store/user/selectors';
16
16
  import { ChatMessageError } from '@/types/message';
17
17
  import { getMessageError } from '@/utils/fetch';
18
18
 
@@ -25,7 +25,7 @@ interface STTConfig extends SWRConfiguration {
25
25
  const useOpenaiSTT = (config: STTConfig) => {
26
26
  const ttsSettings = useUserStore(settingsSelectors.currentTTS, isEqual);
27
27
  const ttsAgentSettings = useAgentStore(agentSelectors.currentAgentTTS, isEqual);
28
- const locale = useUserStore(settingsSelectors.currentLanguage);
28
+ const locale = useUserStore(userGeneralSettingsSelectors.currentLanguage);
29
29
 
30
30
  const autoStop = ttsSettings.sttAutoStop;
31
31
  const sttLocale =