@lobehub/chat 0.160.7 → 0.161.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/locales/ar/setting.json +9 -0
  3. package/locales/bg-BG/setting.json +9 -0
  4. package/locales/de-DE/setting.json +9 -0
  5. package/locales/en-US/setting.json +9 -0
  6. package/locales/es-ES/setting.json +9 -0
  7. package/locales/fr-FR/setting.json +9 -0
  8. package/locales/it-IT/setting.json +9 -0
  9. package/locales/ja-JP/setting.json +9 -0
  10. package/locales/ko-KR/setting.json +9 -0
  11. package/locales/nl-NL/setting.json +9 -0
  12. package/locales/pl-PL/setting.json +30 -20
  13. package/locales/pt-BR/setting.json +9 -0
  14. package/locales/ru-RU/setting.json +29 -20
  15. package/locales/tr-TR/setting.json +29 -20
  16. package/locales/vi-VN/setting.json +9 -0
  17. package/locales/zh-CN/setting.json +9 -0
  18. package/locales/zh-TW/setting.json +9 -0
  19. package/package.json +1 -1
  20. package/src/app/(main)/settings/common/page.tsx +1 -0
  21. package/src/app/(main)/settings/hooks/useCategory.tsx +49 -12
  22. package/src/app/(main)/settings/llm/components/ProviderModelList/ModelFetcher.tsx +1 -0
  23. package/src/app/(main)/settings/llm/components/ProviderModelList/index.tsx +8 -1
  24. package/src/app/(main)/settings/system-agent/features/Translation.tsx +60 -0
  25. package/src/app/(main)/settings/system-agent/index.tsx +9 -0
  26. package/src/app/(main)/settings/system-agent/page.tsx +14 -0
  27. package/src/app/@modal/(.)settings/modal/index.tsx +5 -0
  28. package/src/components/ModelSelect/index.tsx +13 -5
  29. package/src/const/settings/agent.ts +36 -0
  30. package/src/const/settings/common.ts +8 -0
  31. package/src/const/settings/index.ts +15 -172
  32. package/src/const/settings/llm.ts +110 -0
  33. package/src/const/settings/sync.ts +5 -0
  34. package/src/const/settings/systemAgent.ts +12 -0
  35. package/src/const/settings/tool.ts +5 -0
  36. package/src/const/settings/tts.ts +10 -0
  37. package/src/features/AgentSetting/AgentMeta/index.tsx +1 -1
  38. package/src/features/AgentSetting/AgentModal/ModelSelect.tsx +4 -52
  39. package/src/features/ModelSelect/index.tsx +67 -0
  40. package/src/features/PluginStore/index.tsx +1 -1
  41. package/src/locales/default/setting.ts +16 -7
  42. package/src/store/chat/slices/enchance/action.ts +9 -2
  43. package/src/store/global/initialState.ts +1 -0
  44. package/src/store/user/selectors.ts +1 -0
  45. package/src/store/user/slices/settings/actions/general.test.ts +22 -0
  46. package/src/store/user/slices/settings/actions/general.ts +11 -0
  47. package/src/store/user/slices/settings/selectors/index.ts +1 -0
  48. package/src/store/user/slices/settings/selectors/settings.ts +10 -1
  49. package/src/store/user/slices/settings/selectors/systemAgent.ts +14 -0
  50. package/src/types/settings/index.ts +3 -0
  51. package/src/types/settings/systemAgent.ts +8 -0
@@ -1,65 +1,17 @@
1
- import { Select, SelectProps } from 'antd';
2
- import { createStyles } from 'antd-style';
3
- import isEqual from 'fast-deep-equal';
4
- import { memo, useMemo } from 'react';
1
+ import { memo } from 'react';
5
2
 
6
- import { ModelItemRender, ProviderItemRender } from '@/components/ModelSelect';
7
- import { useUserStore } from '@/store/user';
8
- import { modelProviderSelectors } from '@/store/user/selectors';
9
- import { ModelProviderCard } from '@/types/llm';
3
+ import Select from '@/features/ModelSelect';
10
4
 
11
5
  import { useStore } from '../store';
12
6
 
13
- const useStyles = createStyles(({ css, prefixCls }) => ({
14
- select: css`
15
- .${prefixCls}-select-dropdown .${prefixCls}-select-item-option-grouped {
16
- padding-inline-start: 12px;
17
- }
18
- `,
19
- }));
20
- interface ModelOption {
21
- label: any;
22
- provider: string;
23
- value: string;
24
- }
25
-
26
7
  const ModelSelect = memo(() => {
27
8
  const [model, updateConfig] = useStore((s) => [s.config.model, s.setAgentConfig]);
28
- const enabledList = useUserStore(modelProviderSelectors.modelProviderListForModelSelect, isEqual);
29
-
30
- const { styles } = useStyles();
31
-
32
- const options = useMemo<SelectProps['options']>(() => {
33
- const getChatModels = (provider: ModelProviderCard) =>
34
- provider.chatModels.map((model) => ({
35
- label: <ModelItemRender {...model} />,
36
- provider: provider.id,
37
- value: model.id,
38
- }));
39
-
40
- if (enabledList.length === 1) {
41
- const provider = enabledList[0];
42
-
43
- return getChatModels(provider);
44
- }
45
-
46
- return enabledList.map((provider) => ({
47
- label: <ProviderItemRender provider={provider.id} />,
48
- options: getChatModels(provider),
49
- }));
50
- }, [enabledList]);
51
9
 
52
10
  return (
53
11
  <Select
54
- className={styles.select}
55
- onChange={(model, option) => {
56
- updateConfig({
57
- model,
58
- provider: (option as unknown as ModelOption).provider,
59
- });
12
+ onChange={(props) => {
13
+ updateConfig(props);
60
14
  }}
61
- options={options}
62
- popupMatchSelectWidth={false}
63
15
  value={model}
64
16
  />
65
17
  );
@@ -0,0 +1,67 @@
1
+ import { Select, SelectProps } from 'antd';
2
+ import { createStyles } from 'antd-style';
3
+ import isEqual from 'fast-deep-equal';
4
+ import { memo, useMemo } from 'react';
5
+
6
+ import { ModelItemRender, ProviderItemRender } from '@/components/ModelSelect';
7
+ import { useUserStore } from '@/store/user';
8
+ import { modelProviderSelectors } from '@/store/user/selectors';
9
+ import { ModelProviderCard } from '@/types/llm';
10
+
11
+ const useStyles = createStyles(({ css, prefixCls }) => ({
12
+ select: css`
13
+ .${prefixCls}-select-dropdown .${prefixCls}-select-item-option-grouped {
14
+ padding-inline-start: 12px;
15
+ }
16
+ `,
17
+ }));
18
+ interface ModelOption {
19
+ label: any;
20
+ provider: string;
21
+ value: string;
22
+ }
23
+
24
+ interface ModelSelectProps {
25
+ onChange?: (props: { model: string; provider: string }) => void;
26
+ value?: string;
27
+ }
28
+
29
+ const ModelSelect = memo<ModelSelectProps>(({ value, onChange }) => {
30
+ const enabledList = useUserStore(modelProviderSelectors.modelProviderListForModelSelect, isEqual);
31
+
32
+ const { styles } = useStyles();
33
+
34
+ const options = useMemo<SelectProps['options']>(() => {
35
+ const getChatModels = (provider: ModelProviderCard) =>
36
+ provider.chatModels.map((model) => ({
37
+ label: <ModelItemRender {...model} />,
38
+ provider: provider.id,
39
+ value: model.id,
40
+ }));
41
+
42
+ if (enabledList.length === 1) {
43
+ const provider = enabledList[0];
44
+
45
+ return getChatModels(provider);
46
+ }
47
+
48
+ return enabledList.map((provider) => ({
49
+ label: <ProviderItemRender provider={provider.id} />,
50
+ options: getChatModels(provider),
51
+ }));
52
+ }, [enabledList]);
53
+
54
+ return (
55
+ <Select
56
+ className={styles.select}
57
+ onChange={(model, option) => {
58
+ onChange?.({ model, provider: (option as unknown as ModelOption).provider });
59
+ }}
60
+ options={options}
61
+ popupMatchSelectWidth={false}
62
+ value={value}
63
+ />
64
+ );
65
+ });
66
+
67
+ export default ModelSelect;
@@ -50,4 +50,4 @@ export const PluginStore = memo<PluginStoreProps>(({ setOpen, open }) => {
50
50
  );
51
51
  });
52
52
 
53
- export default PluginStore;
53
+ export default PluginStore;
@@ -363,14 +363,23 @@ export default {
363
363
  title: 'WebRTC 同步',
364
364
  },
365
365
  },
366
+ systemAgent: {
367
+ title: '系统助手',
368
+ translation: {
369
+ label: '翻译模型',
370
+ modelDesc: '指定用于翻译的模型',
371
+ title: '翻译助手设置',
372
+ },
373
+ },
366
374
  tab: {
367
- about: '关于',
368
- agent: '默认助手',
369
- common: '通用设置',
370
- experiment: '实验',
371
- llm: '语言模型',
372
- sync: '云端同步',
373
- tts: '语音服务',
375
+ 'about': '关于',
376
+ 'agent': '默认助手',
377
+ 'common': '通用设置',
378
+ 'experiment': '实验',
379
+ 'llm': '语言模型',
380
+ 'sync': '云端同步',
381
+ 'system-agent': '系统助手',
382
+ 'tts': '语音服务',
374
383
  },
375
384
  tools: {
376
385
  builtins: {
@@ -9,7 +9,10 @@ import { chatService } from '@/services/chat';
9
9
  import { messageService } from '@/services/message';
10
10
  import { chatSelectors } from '@/store/chat/selectors';
11
11
  import { ChatStore } from '@/store/chat/store';
12
+ import { useUserStore } from '@/store/user';
13
+ import { systemAgentSelectors } from '@/store/user/selectors';
12
14
  import { ChatTTS, ChatTranslate } from '@/types/message';
15
+ import { merge } from '@/utils/merge';
13
16
  import { setNamespace } from '@/utils/storeDebug';
14
17
 
15
18
  const n = setNamespace('enhance');
@@ -48,12 +51,16 @@ export const chatEnhance: StateCreator<
48
51
  topicId: get().activeTopicId,
49
52
  ...data,
50
53
  }),
54
+
51
55
  translateMessage: async (id, targetLang) => {
52
56
  const { internal_toggleChatLoading, updateMessageTranslate, internal_dispatchMessage } = get();
53
57
 
54
58
  const message = chatSelectors.getMessageById(id)(get());
55
59
  if (!message) return;
56
60
 
61
+ // Get current agent for translation
62
+ const translationSetting = systemAgentSelectors.translation(useUserStore.getState());
63
+
57
64
  // create translate extra
58
65
  await updateMessageTranslate(id, { content: '', from: '', to: targetLang });
59
66
 
@@ -69,7 +76,7 @@ export const chatEnhance: StateCreator<
69
76
 
70
77
  await updateMessageTranslate(id, { content, from, to: targetLang });
71
78
  },
72
- params: chainLangDetect(message.content),
79
+ params: merge(translationSetting, chainLangDetect(message.content)),
73
80
  trace: get().getCurrentTracePayload({ traceName: TraceNameMap.LanguageDetect }),
74
81
  });
75
82
 
@@ -95,7 +102,7 @@ export const chatEnhance: StateCreator<
95
102
  }
96
103
  }
97
104
  },
98
- params: chainTranslate(message.content, targetLang),
105
+ params: merge(translationSetting, chainTranslate(message.content, targetLang)),
99
106
  trace: get().getCurrentTracePayload({ traceName: TraceNameMap.Translator }),
100
107
  });
101
108
  },
@@ -25,6 +25,7 @@ export enum SettingsTabs {
25
25
  Common = 'common',
26
26
  LLM = 'llm',
27
27
  Sync = 'sync',
28
+ SystemAgent = 'system-agent',
28
29
  TTS = 'tts',
29
30
  }
30
31
 
@@ -5,4 +5,5 @@ export {
5
5
  modelProviderSelectors,
6
6
  settingsSelectors,
7
7
  syncSettingsSelectors,
8
+ systemAgentSelectors,
8
9
  } from './slices/settings/selectors';
@@ -112,4 +112,26 @@ describe('SettingsAction', () => {
112
112
  expect(userService.updateUserSettings).toHaveBeenCalledWith({ defaultAgent: updatedAgent });
113
113
  });
114
114
  });
115
+
116
+ describe('setTranslationSystemAgent', () => {
117
+ it('should set partial settings', async () => {
118
+ const { result } = renderHook(() => useUserStore());
119
+ const systemAgentSettings: Partial<GlobalSettings> = {
120
+ systemAgent: {
121
+ translation: {
122
+ model: 'testmodel',
123
+ provider: 'provider',
124
+ },
125
+ },
126
+ };
127
+
128
+ // Perform the action
129
+ await act(async () => {
130
+ await result.current.setTranslationSystemAgent('provider', 'testmodel');
131
+ });
132
+
133
+ // Assert that updateUserSettings was called with the correct settings
134
+ expect(userService.updateUserSettings).toHaveBeenCalledWith(systemAgentSettings);
135
+ });
136
+ });
115
137
  });
@@ -16,6 +16,7 @@ export interface GeneralSettingsAction {
16
16
  importAppSettings: (settings: GlobalSettings) => Promise<void>;
17
17
  resetSettings: () => Promise<void>;
18
18
  setSettings: (settings: DeepPartial<GlobalSettings>) => Promise<void>;
19
+ setTranslationSystemAgent: (provider: string, model: string) => Promise<void>;
19
20
  switchLocale: (locale: LocaleMode) => Promise<void>;
20
21
  switchThemeMode: (themeMode: ThemeMode) => Promise<void>;
21
22
  updateDefaultAgent: (agent: DeepPartial<LobeAgentSettings>) => Promise<void>;
@@ -50,6 +51,16 @@ export const generalSettingsSlice: StateCreator<
50
51
  await userService.updateUserSettings(diffs);
51
52
  await get().refreshUserConfig();
52
53
  },
54
+ setTranslationSystemAgent: async (provider, model) => {
55
+ await get().setSettings({
56
+ systemAgent: {
57
+ translation: {
58
+ model: model,
59
+ provider: provider,
60
+ },
61
+ },
62
+ });
63
+ },
53
64
  switchLocale: async (locale) => {
54
65
  await get().setSettings({ language: locale });
55
66
 
@@ -2,3 +2,4 @@ export { modelConfigSelectors } from './modelConfig';
2
2
  export { modelProviderSelectors } from './modelProvider';
3
3
  export { settingsSelectors } from './settings';
4
4
  export { syncSettingsSelectors } from './sync';
5
+ export { systemAgentSelectors } from './systemAgent';
@@ -1,6 +1,11 @@
1
1
  import { DEFAULT_LANG } from '@/const/locale';
2
2
  import { DEFAULT_AGENT_META } from '@/const/meta';
3
- import { DEFAULT_AGENT, DEFAULT_AGENT_CONFIG, DEFAULT_TTS_CONFIG } from '@/const/settings';
3
+ import {
4
+ DEFAULT_AGENT,
5
+ DEFAULT_AGENT_CONFIG,
6
+ DEFAULT_SYSTEM_AGENT_CONFIG,
7
+ DEFAULT_TTS_CONFIG,
8
+ } from '@/const/settings';
4
9
  import { Locales } from '@/locales/resources';
5
10
  import { GeneralModelProviderConfig, GlobalLLMProviderKey, GlobalSettings } from '@/types/settings';
6
11
  import { isOnServerSide } from '@/utils/env';
@@ -53,9 +58,13 @@ export const currentThemeMode = (s: UserStore) => {
53
58
  const dalleConfig = (s: UserStore) => currentSettings(s).tool?.dalle || {};
54
59
  const isDalleAutoGenerating = (s: UserStore) => currentSettings(s).tool?.dalle?.autoGenerate;
55
60
 
61
+ const currentSystemAgent = (s: UserStore) =>
62
+ merge(DEFAULT_SYSTEM_AGENT_CONFIG, currentSettings(s).systemAgent);
63
+
56
64
  export const settingsSelectors = {
57
65
  currentLanguage,
58
66
  currentSettings,
67
+ currentSystemAgent,
59
68
  currentTTS,
60
69
  currentThemeMode,
61
70
  dalleConfig,
@@ -0,0 +1,14 @@
1
+ import { DEFAULT_SYSTEM_AGENT_CONFIG } from '@/const/settings';
2
+ import type { UserStore } from '@/store/user';
3
+ import { merge } from '@/utils/merge';
4
+
5
+ import { currentSettings } from './settings';
6
+
7
+ const currentSystemAgent = (s: UserStore) =>
8
+ merge(DEFAULT_SYSTEM_AGENT_CONFIG, currentSettings(s).systemAgent);
9
+
10
+ const translation = (s: UserStore) => currentSystemAgent(s).translation;
11
+
12
+ export const systemAgentSelectors = {
13
+ translation,
14
+ };
@@ -3,6 +3,7 @@ import type { LobeAgentSession } from '@/types/session';
3
3
  import { GlobalBaseSettings } from './base';
4
4
  import { GlobalLLMConfig } from './modelProvider';
5
5
  import { GlobalSyncSettings } from './sync';
6
+ import { GlobalSystemAgentConfig } from './systemAgent';
6
7
  import { GlobalTTSConfig } from './tts';
7
8
 
8
9
  export type GlobalDefaultAgent = Pick<LobeAgentSession, 'config' | 'meta'>;
@@ -10,6 +11,7 @@ export type GlobalDefaultAgent = Pick<LobeAgentSession, 'config' | 'meta'>;
10
11
  export * from './base';
11
12
  export * from './modelProvider';
12
13
  export * from './sync';
14
+ export * from './systemAgent';
13
15
  export * from './tts';
14
16
 
15
17
  export interface GlobalTool {
@@ -25,6 +27,7 @@ export interface GlobalSettings extends GlobalBaseSettings {
25
27
  defaultAgent: GlobalDefaultAgent;
26
28
  languageModel: GlobalLLMConfig;
27
29
  sync: GlobalSyncSettings;
30
+ systemAgent: GlobalSystemAgentConfig;
28
31
  tool: GlobalTool;
29
32
  tts: GlobalTTSConfig;
30
33
  }
@@ -0,0 +1,8 @@
1
+ export interface GlobalTranslationConfig {
2
+ model: string;
3
+ provider: string;
4
+ }
5
+
6
+ export interface GlobalSystemAgentConfig {
7
+ translation: GlobalTranslationConfig;
8
+ }