@lobehub/chat 0.149.4 → 0.149.6
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/.github/FUNDING.yml +1 -1
- package/CHANGELOG.md +58 -0
- package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +15 -21
- package/package.json +1 -1
- package/src/app/chat/(desktop)/features/ChatHeader/Main.tsx +5 -5
- package/src/app/chat/(desktop)/features/ChatHeader/Tags.tsx +3 -3
- package/src/app/chat/(desktop)/features/ChatInput/Footer/DragUpload.tsx +9 -9
- package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +3 -3
- package/src/app/chat/(desktop)/features/SideBar/SystemRole/index.tsx +8 -3
- package/src/app/chat/(mobile)/mobile/ChatHeader/ChatHeaderTitle.tsx +2 -2
- package/src/app/chat/(mobile)/mobile/page.tsx +0 -6
- package/src/app/chat/_layout/Desktop/SessionList.tsx +2 -0
- package/src/app/chat/features/PageTitle/index.tsx +3 -3
- package/src/app/chat/features/PluginTag/PluginStatus.tsx +2 -2
- package/src/app/chat/features/SessionListContent/DefaultMode.tsx +4 -2
- package/src/app/chat/features/SessionListContent/List/Item/index.tsx +10 -17
- package/src/app/chat/features/SessionListContent/index.tsx +2 -0
- package/src/app/chat/features/ShareButton/Preview.tsx +15 -11
- package/src/app/chat/features/ShareButton/useScreenshot.ts +2 -2
- package/src/app/chat/settings/features/EditPage.tsx +10 -7
- package/src/app/chat/settings/features/SubmitAgentButton/SubmitAgentModal.tsx +5 -3
- package/src/app/metadata.ts +3 -3
- package/src/app/settings/(mobile)/features/AvatarBanner.tsx +1 -0
- package/src/config/modelProviders/ollama.ts +11 -12
- package/src/const/session.ts +1 -0
- package/src/database/client/models/session.ts +1 -0
- package/src/database/client/models/user.ts +6 -0
- package/src/features/ChatInput/ActionBar/FileUpload.tsx +11 -5
- package/src/features/ChatInput/ActionBar/History.tsx +3 -3
- package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +2 -0
- package/src/features/ChatInput/ActionBar/Temperature.tsx +3 -3
- package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +4 -4
- package/src/features/ChatInput/ActionBar/Token/index.tsx +3 -3
- package/src/features/ChatInput/ActionBar/Tools/ToolItem.tsx +3 -3
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +4 -4
- package/src/features/ChatInput/STT/browser.tsx +3 -3
- package/src/features/ChatInput/STT/openai.tsx +3 -3
- package/src/features/ChatInput/useChatInput.ts +3 -3
- package/src/features/Conversation/Extras/Assistant.test.tsx +7 -7
- package/src/features/Conversation/Extras/Assistant.tsx +3 -3
- package/src/features/Conversation/Extras/TTS/index.tsx +3 -3
- package/src/features/Conversation/components/ChatItem/ActionsBar.tsx +2 -2
- package/src/features/Conversation/components/ChatItem/index.tsx +6 -4
- package/src/features/Conversation/hooks/useInitConversation.ts +10 -7
- package/src/features/Conversation/index.tsx +6 -3
- package/src/features/ModelSwitchPanel/index.tsx +6 -4
- package/src/hooks/useTTS.ts +4 -4
- package/src/libs/agent-runtime/ollama/index.ts +1 -1
- package/src/services/chat.ts +3 -3
- package/src/services/ollama.ts +1 -2
- package/src/services/session/client.ts +19 -0
- package/src/services/session/type.ts +2 -0
- package/src/store/agent/index.ts +2 -0
- package/src/store/agent/initialState.ts +7 -0
- package/src/store/agent/selectors.ts +1 -0
- package/src/store/{session/slices/agent → agent/slices/chat}/action.test.ts +26 -63
- package/src/store/agent/slices/chat/action.ts +107 -0
- package/src/store/agent/slices/chat/initialState.ts +14 -0
- package/src/store/agent/slices/chat/selectors.test.ts +82 -0
- package/src/store/agent/slices/chat/selectors.ts +81 -0
- package/src/store/agent/store.ts +27 -0
- package/src/store/chat/slices/message/action.test.ts +3 -2
- package/src/store/chat/slices/message/action.ts +3 -3
- package/src/store/chat/slices/message/selectors.test.ts +9 -2
- package/src/store/chat/slices/message/selectors.ts +6 -4
- package/src/store/chat/slices/share/action.ts +5 -3
- package/src/store/global/slices/preference/selectors.ts +3 -1
- package/src/store/session/selectors.ts +1 -2
- package/src/store/session/slices/session/action.test.ts +43 -0
- package/src/store/session/slices/session/action.ts +28 -18
- package/src/store/session/slices/session/helpers.ts +2 -3
- package/src/store/session/slices/session/initialState.ts +1 -17
- package/src/store/session/slices/session/selectors/index.ts +1 -0
- package/src/store/session/slices/session/selectors/list.test.ts +5 -3
- package/src/store/session/slices/session/selectors/list.ts +2 -3
- package/src/store/session/slices/session/selectors/meta.test.ts +108 -0
- package/src/store/session/slices/session/selectors/meta.ts +45 -0
- package/src/store/session/store.ts +1 -7
- package/src/types/session.ts +1 -0
- package/src/store/session/slices/agent/action.ts +0 -84
- package/src/store/session/slices/agent/selectors.test.ts +0 -180
- package/src/store/session/slices/agent/selectors.ts +0 -129
- /package/src/store/{session/slices/agent → agent/slices/chat}/index.ts +0 -0
|
@@ -2,6 +2,17 @@ import { ModelProviderCard } from '@/types/llm';
|
|
|
2
2
|
|
|
3
3
|
const Ollama: ModelProviderCard = {
|
|
4
4
|
chatModels: [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Llama3 8B',
|
|
7
|
+
enabled: true,
|
|
8
|
+
id: 'llama3',
|
|
9
|
+
tokens: 8000,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
displayName: 'Llama3 70B',
|
|
13
|
+
id: 'llama3:70b',
|
|
14
|
+
tokens: 8000,
|
|
15
|
+
},
|
|
5
16
|
{
|
|
6
17
|
displayName: 'Command R 35B',
|
|
7
18
|
enabled: true,
|
|
@@ -21,7 +32,6 @@ const Ollama: ModelProviderCard = {
|
|
|
21
32
|
},
|
|
22
33
|
{
|
|
23
34
|
displayName: 'Gemma 2B',
|
|
24
|
-
enabled: true,
|
|
25
35
|
id: 'gemma:2b',
|
|
26
36
|
tokens: 4000,
|
|
27
37
|
},
|
|
@@ -50,17 +60,6 @@ const Ollama: ModelProviderCard = {
|
|
|
50
60
|
id: 'llama2-chinese',
|
|
51
61
|
tokens: 4000,
|
|
52
62
|
},
|
|
53
|
-
{
|
|
54
|
-
displayName: 'Llama3 8B',
|
|
55
|
-
enabled: true,
|
|
56
|
-
id: 'llama3',
|
|
57
|
-
tokens: 8000,
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
displayName: 'Llama3 70B',
|
|
61
|
-
id: 'llama3:70b',
|
|
62
|
-
tokens: 8000,
|
|
63
|
-
},
|
|
64
63
|
{
|
|
65
64
|
displayName: 'WizardLM 2 7B',
|
|
66
65
|
enabled: true,
|
package/src/const/session.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DeepPartial } from 'utility-types';
|
|
2
2
|
|
|
3
3
|
import { BaseModel } from '@/database/client/core';
|
|
4
|
+
import { LobeAgentConfig } from '@/types/agent';
|
|
4
5
|
import { GlobalSettings } from '@/types/settings';
|
|
5
6
|
import { uuid } from '@/utils/uuid';
|
|
6
7
|
|
|
@@ -22,6 +23,11 @@ class _UserModel extends BaseModel {
|
|
|
22
23
|
return list[0];
|
|
23
24
|
};
|
|
24
25
|
|
|
26
|
+
getAgentConfig = async () => {
|
|
27
|
+
const user = await this.getUser();
|
|
28
|
+
|
|
29
|
+
return user.settings?.defaultAgent?.config as LobeAgentConfig;
|
|
30
|
+
};
|
|
25
31
|
// **************** Create *************** //
|
|
26
32
|
|
|
27
33
|
create = async (user: DB_User) => {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { ActionIcon, Icon } from '@lobehub/ui';
|
|
2
2
|
import { Upload } from 'antd';
|
|
3
3
|
import { useTheme } from 'antd-style';
|
|
4
|
-
import {
|
|
4
|
+
import { FileUp, LucideImage, LucideLoader2 } from 'lucide-react';
|
|
5
5
|
import { memo, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Center } from 'react-layout-kit';
|
|
8
8
|
|
|
9
|
+
import { useAgentStore } from '@/store/agent';
|
|
10
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
9
11
|
import { useFileStore } from '@/store/file';
|
|
10
12
|
import { useGlobalStore } from '@/store/global';
|
|
11
13
|
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
12
|
-
import { useSessionStore } from '@/store/session';
|
|
13
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
14
14
|
|
|
15
15
|
const FileUpload = memo(() => {
|
|
16
16
|
const { t } = useTranslation('chat');
|
|
@@ -18,7 +18,7 @@ const FileUpload = memo(() => {
|
|
|
18
18
|
const theme = useTheme();
|
|
19
19
|
const upload = useFileStore((s) => s.uploadFile);
|
|
20
20
|
|
|
21
|
-
const model =
|
|
21
|
+
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
22
22
|
const [canUpload, enabledFiles] = useGlobalStore((s) => [
|
|
23
23
|
modelProviderSelectors.isModelEnabledUpload(model)(s),
|
|
24
24
|
modelProviderSelectors.isModelEnabledFiles(model)(s),
|
|
@@ -53,7 +53,13 @@ const FileUpload = memo(() => {
|
|
|
53
53
|
disable={!canUpload}
|
|
54
54
|
icon={enabledFiles ? FileUp : LucideImage}
|
|
55
55
|
placement={'bottom'}
|
|
56
|
-
title={t(
|
|
56
|
+
title={t(
|
|
57
|
+
canUpload
|
|
58
|
+
? enabledFiles
|
|
59
|
+
? 'upload.actionFiletip'
|
|
60
|
+
: 'upload.actionTooltip'
|
|
61
|
+
: 'upload.disabled',
|
|
62
|
+
)}
|
|
57
63
|
/>
|
|
58
64
|
)}
|
|
59
65
|
</Upload>
|
|
@@ -5,13 +5,13 @@ import { memo } from 'react';
|
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Flexbox } from 'react-layout-kit';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import { agentSelectors } from '@/store/
|
|
8
|
+
import { useAgentStore } from '@/store/agent';
|
|
9
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
10
10
|
|
|
11
11
|
const History = memo(() => {
|
|
12
12
|
const { t } = useTranslation('setting');
|
|
13
13
|
|
|
14
|
-
const [historyCount, unlimited, updateAgentConfig] =
|
|
14
|
+
const [historyCount, unlimited, updateAgentConfig] = useAgentStore((s) => {
|
|
15
15
|
const config = agentSelectors.currentAgentConfig(s);
|
|
16
16
|
return [config.historyCount, !config.enableHistoryCount, s.updateAgentConfig];
|
|
17
17
|
});
|
|
@@ -4,13 +4,13 @@ import { Thermometer } from 'lucide-react';
|
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { agentSelectors } from '@/store/
|
|
7
|
+
import { useAgentStore } from '@/store/agent';
|
|
8
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
9
9
|
|
|
10
10
|
const Temperature = memo(() => {
|
|
11
11
|
const { t } = useTranslation('setting');
|
|
12
12
|
|
|
13
|
-
const [temperature, updateAgentConfig] =
|
|
13
|
+
const [temperature, updateAgentConfig] = useAgentStore((s) => {
|
|
14
14
|
const config = agentSelectors.currentAgentConfig(s);
|
|
15
15
|
return [config.params.temperature, s.updateAgentConfig];
|
|
16
16
|
});
|
|
@@ -5,12 +5,12 @@ import { useTranslation } from 'react-i18next';
|
|
|
5
5
|
import { Flexbox } from 'react-layout-kit';
|
|
6
6
|
|
|
7
7
|
import { useTokenCount } from '@/hooks/useTokenCount';
|
|
8
|
+
import { useAgentStore } from '@/store/agent';
|
|
9
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
8
10
|
import { useChatStore } from '@/store/chat';
|
|
9
11
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
10
12
|
import { useGlobalStore } from '@/store/global';
|
|
11
13
|
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
12
|
-
import { useSessionStore } from '@/store/session';
|
|
13
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
14
14
|
import { useToolStore } from '@/store/tool';
|
|
15
15
|
import { toolSelectors } from '@/store/tool/selectors';
|
|
16
16
|
|
|
@@ -24,7 +24,7 @@ const Token = memo(() => {
|
|
|
24
24
|
chatSelectors.chatsMessageString(s),
|
|
25
25
|
]);
|
|
26
26
|
|
|
27
|
-
const [systemRole, model] =
|
|
27
|
+
const [systemRole, model] = useAgentStore((s) => [
|
|
28
28
|
agentSelectors.currentAgentSystemRole(s),
|
|
29
29
|
agentSelectors.currentAgentModel(s) as string,
|
|
30
30
|
]);
|
|
@@ -33,7 +33,7 @@ const Token = memo(() => {
|
|
|
33
33
|
|
|
34
34
|
// Tool usage token
|
|
35
35
|
const canUseTool = useGlobalStore(modelProviderSelectors.isModelEnabledFunctionCall(model));
|
|
36
|
-
const plugins =
|
|
36
|
+
const plugins = useAgentStore(agentSelectors.currentAgentPlugins);
|
|
37
37
|
const toolsString = useToolStore((s) => {
|
|
38
38
|
const pluginSystemRoles = toolSelectors.enabledSystemRoles(plugins)(s);
|
|
39
39
|
const schemaNumber = toolSelectors
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import dynamic from 'next/dynamic';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
+
import { useAgentStore } from '@/store/agent';
|
|
5
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
4
6
|
import { useGlobalStore } from '@/store/global';
|
|
5
7
|
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
6
|
-
import { useSessionStore } from '@/store/session';
|
|
7
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
8
8
|
|
|
9
9
|
const LargeTokenContent = dynamic(() => import('./TokenTag'), { ssr: false });
|
|
10
10
|
|
|
11
11
|
const Token = memo(() => {
|
|
12
|
-
const model =
|
|
12
|
+
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
13
13
|
const showTag = useGlobalStore(modelProviderSelectors.isModelHasMaxToken(model));
|
|
14
14
|
|
|
15
15
|
return showTag && <LargeTokenContent />;
|
|
@@ -3,13 +3,13 @@ import { memo } from 'react';
|
|
|
3
3
|
import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
5
5
|
import PluginTag from '@/features/PluginStore/PluginItem/PluginTag';
|
|
6
|
-
import {
|
|
7
|
-
import { agentSelectors } from '@/store/
|
|
6
|
+
import { useAgentStore } from '@/store/agent';
|
|
7
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
8
8
|
import { useToolStore } from '@/store/tool';
|
|
9
9
|
import { customPluginSelectors } from '@/store/tool/selectors';
|
|
10
10
|
|
|
11
11
|
const ToolItem = memo<{ identifier: string; label: string }>(({ identifier, label }) => {
|
|
12
|
-
const [checked, togglePlugin] =
|
|
12
|
+
const [checked, togglePlugin] = useAgentStore((s) => [
|
|
13
13
|
agentSelectors.currentAgentPlugins(s).includes(identifier),
|
|
14
14
|
s.togglePlugin,
|
|
15
15
|
]);
|
|
@@ -8,10 +8,10 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
8
|
import { Flexbox } from 'react-layout-kit';
|
|
9
9
|
|
|
10
10
|
import PluginStore from '@/features/PluginStore';
|
|
11
|
+
import { useAgentStore } from '@/store/agent';
|
|
12
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
11
13
|
import { useGlobalStore } from '@/store/global';
|
|
12
14
|
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
13
|
-
import { useSessionStore } from '@/store/session';
|
|
14
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
15
15
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
16
16
|
import { builtinToolSelectors, pluginSelectors } from '@/store/tool/selectors';
|
|
17
17
|
|
|
@@ -35,7 +35,7 @@ const Tools = memo(() => {
|
|
|
35
35
|
const list = useToolStore(pluginSelectors.installedPluginMetaList, isEqual);
|
|
36
36
|
const builtinList = useToolStore(builtinToolSelectors.metaList, isEqual);
|
|
37
37
|
|
|
38
|
-
const enablePluginCount =
|
|
38
|
+
const enablePluginCount = useAgentStore(
|
|
39
39
|
(s) =>
|
|
40
40
|
agentSelectors
|
|
41
41
|
.currentAgentPlugins(s)
|
|
@@ -45,7 +45,7 @@ const Tools = memo(() => {
|
|
|
45
45
|
const [open, setOpen] = useState(false);
|
|
46
46
|
const { styles } = useStyles();
|
|
47
47
|
|
|
48
|
-
const model =
|
|
48
|
+
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
49
49
|
const enableFC = useGlobalStore(modelProviderSelectors.isModelEnabledFunctionCall(model));
|
|
50
50
|
|
|
51
51
|
return (
|
|
@@ -4,11 +4,11 @@ import { memo, useCallback, useState } from 'react';
|
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { SWRConfiguration } from 'swr';
|
|
6
6
|
|
|
7
|
+
import { useAgentStore } from '@/store/agent';
|
|
8
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
7
9
|
import { useChatStore } from '@/store/chat';
|
|
8
10
|
import { useGlobalStore } from '@/store/global';
|
|
9
11
|
import { settingsSelectors } from '@/store/global/selectors';
|
|
10
|
-
import { useSessionStore } from '@/store/session';
|
|
11
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
12
12
|
import { ChatMessageError } from '@/types/message';
|
|
13
13
|
import { getMessageError } from '@/utils/fetch';
|
|
14
14
|
|
|
@@ -20,7 +20,7 @@ interface STTConfig extends SWRConfiguration {
|
|
|
20
20
|
|
|
21
21
|
const useBrowserSTT = (config: STTConfig) => {
|
|
22
22
|
const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
|
|
23
|
-
const ttsAgentSettings =
|
|
23
|
+
const ttsAgentSettings = useAgentStore(agentSelectors.currentAgentTTS, isEqual);
|
|
24
24
|
const locale = useGlobalStore(settingsSelectors.currentLanguage);
|
|
25
25
|
|
|
26
26
|
const autoStop = ttsSettings.sttAutoStop;
|
|
@@ -7,11 +7,11 @@ import { SWRConfiguration } from 'swr';
|
|
|
7
7
|
|
|
8
8
|
import { createHeaderWithOpenAI } from '@/services/_header';
|
|
9
9
|
import { API_ENDPOINTS } from '@/services/_url';
|
|
10
|
+
import { useAgentStore } from '@/store/agent';
|
|
11
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
10
12
|
import { useChatStore } from '@/store/chat';
|
|
11
13
|
import { useGlobalStore } from '@/store/global';
|
|
12
14
|
import { settingsSelectors } from '@/store/global/selectors';
|
|
13
|
-
import { useSessionStore } from '@/store/session';
|
|
14
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
15
15
|
import { ChatMessageError } from '@/types/message';
|
|
16
16
|
import { getMessageError } from '@/utils/fetch';
|
|
17
17
|
|
|
@@ -23,7 +23,7 @@ interface STTConfig extends SWRConfiguration {
|
|
|
23
23
|
|
|
24
24
|
const useOpenaiSTT = (config: STTConfig) => {
|
|
25
25
|
const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
|
|
26
|
-
const ttsAgentSettings =
|
|
26
|
+
const ttsAgentSettings = useAgentStore(agentSelectors.currentAgentTTS, isEqual);
|
|
27
27
|
const locale = useGlobalStore(settingsSelectors.currentLanguage);
|
|
28
28
|
|
|
29
29
|
const autoStop = ttsSettings.sttAutoStop;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { TextAreaRef } from 'antd/es/input/TextArea';
|
|
2
2
|
import { useCallback, useRef, useState } from 'react';
|
|
3
3
|
|
|
4
|
+
import { useAgentStore } from '@/store/agent';
|
|
5
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
4
6
|
import { useChatStore } from '@/store/chat';
|
|
5
7
|
import { useGlobalStore } from '@/store/global';
|
|
6
8
|
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
7
|
-
import { useSessionStore } from '@/store/session';
|
|
8
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
9
9
|
|
|
10
10
|
import { useSendMessage } from './useSend';
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ export const useChatInput = () => {
|
|
|
14
14
|
const [expand, setExpand] = useState<boolean>(false);
|
|
15
15
|
const onSend = useSendMessage();
|
|
16
16
|
|
|
17
|
-
const model =
|
|
17
|
+
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
18
18
|
const canUpload = useGlobalStore(modelProviderSelectors.isModelEnabledUpload(model));
|
|
19
19
|
|
|
20
20
|
const [loading, value, onInput, onStop] = useChatStore((s) => [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { render, screen } from '@testing-library/react';
|
|
2
2
|
import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { agentSelectors } from '@/store/
|
|
4
|
+
import { useAgentStore } from '@/store/agent';
|
|
5
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
6
6
|
import { ChatMessage } from '@/types/message';
|
|
7
7
|
|
|
8
8
|
import { AssistantMessageExtra } from './Assistant';
|
|
@@ -16,10 +16,10 @@ vi.mock('./Translate', () => ({
|
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
18
|
// Mock dependencies
|
|
19
|
-
vi.mock('@/store/
|
|
20
|
-
|
|
19
|
+
vi.mock('@/store/agent', () => ({
|
|
20
|
+
useAgentStore: vi.fn(),
|
|
21
21
|
}));
|
|
22
|
-
vi.mock('@/store/
|
|
22
|
+
vi.mock('@/store/agent/selectors', () => ({
|
|
23
23
|
agentSelectors: {
|
|
24
24
|
currentAgentModel: vi.fn(),
|
|
25
25
|
},
|
|
@@ -37,7 +37,7 @@ const mockData: ChatMessage = {
|
|
|
37
37
|
describe('AssistantMessageExtra', () => {
|
|
38
38
|
beforeEach(() => {
|
|
39
39
|
// Set default mock return values
|
|
40
|
-
(
|
|
40
|
+
(useAgentStore as unknown as Mock).mockImplementation(() => ({
|
|
41
41
|
chatLoadingId: null,
|
|
42
42
|
}));
|
|
43
43
|
(agentSelectors.currentAgentModel as Mock).mockReturnValue('defaultModel');
|
|
@@ -76,7 +76,7 @@ describe('AssistantMessageExtra', () => {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
it('should receive the correct loading attribute if loading is true for TTS and Translate components', async () => {
|
|
79
|
-
(
|
|
79
|
+
(useAgentStore as unknown as Mock).mockImplementation(() => ({
|
|
80
80
|
chatLoadingId: 'test-id',
|
|
81
81
|
}));
|
|
82
82
|
render(<AssistantMessageExtra {...mockData} extra={{ translate: { to: 'abc' }, tts: {} }} />);
|
|
@@ -2,9 +2,9 @@ import { memo } from 'react';
|
|
|
2
2
|
import { Flexbox } from 'react-layout-kit';
|
|
3
3
|
|
|
4
4
|
import ModelTag from '@/components/ModelTag';
|
|
5
|
+
import { useAgentStore } from '@/store/agent';
|
|
6
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
5
7
|
import { useChatStore } from '@/store/chat';
|
|
6
|
-
import { useSessionStore } from '@/store/session';
|
|
7
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
8
8
|
import { ChatMessage } from '@/types/message';
|
|
9
9
|
|
|
10
10
|
import { RenderMessageExtra } from '../types';
|
|
@@ -14,7 +14,7 @@ import Translate from './Translate';
|
|
|
14
14
|
|
|
15
15
|
export const AssistantMessageExtra: RenderMessageExtra = memo<ChatMessage>(
|
|
16
16
|
({ extra, id, content }) => {
|
|
17
|
-
const model =
|
|
17
|
+
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
18
18
|
const loading = useChatStore((s) => s.chatLoadingId === id);
|
|
19
19
|
|
|
20
20
|
const showModelTag = extra?.fromModel && model !== extra?.fromModel;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { memo, useMemo } from 'react';
|
|
2
2
|
import { Md5 } from 'ts-md5';
|
|
3
3
|
|
|
4
|
+
import { useAgentStore } from '@/store/agent';
|
|
5
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
4
6
|
import { useGlobalStore } from '@/store/global';
|
|
5
7
|
import { settingsSelectors } from '@/store/global/selectors';
|
|
6
|
-
import { useSessionStore } from '@/store/session';
|
|
7
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
8
8
|
|
|
9
9
|
import FilePlayer from './FilePlayer';
|
|
10
10
|
import InitPlayer, { TTSProps } from './InitPlayer';
|
|
@@ -13,7 +13,7 @@ const TTS = memo<TTSProps>(
|
|
|
13
13
|
(props) => {
|
|
14
14
|
const { file, voice, content, contentMd5 } = props;
|
|
15
15
|
const lang = useGlobalStore(settingsSelectors.currentLanguage);
|
|
16
|
-
const currentVoice =
|
|
16
|
+
const currentVoice = useAgentStore(agentSelectors.currentAgentTTSVoice(lang));
|
|
17
17
|
|
|
18
18
|
const md5 = useMemo(() => Md5.hashStr(content).toString(), [content]);
|
|
19
19
|
|
|
@@ -5,7 +5,7 @@ import { memo, useCallback } from 'react';
|
|
|
5
5
|
import { useChatStore } from '@/store/chat';
|
|
6
6
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
7
7
|
import { useSessionStore } from '@/store/session';
|
|
8
|
-
import {
|
|
8
|
+
import { sessionMetaSelectors } from '@/store/session/selectors';
|
|
9
9
|
|
|
10
10
|
import { renderActions, useActionsClick } from '../../Actions';
|
|
11
11
|
import { useChatListActionsBar } from '../../hooks/useChatListActionsBar';
|
|
@@ -29,7 +29,7 @@ interface ActionsProps {
|
|
|
29
29
|
setEditing: (edit: boolean) => void;
|
|
30
30
|
}
|
|
31
31
|
const Actions = memo<ActionsProps>(({ index, setEditing }) => {
|
|
32
|
-
const meta = useSessionStore(
|
|
32
|
+
const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
|
|
33
33
|
|
|
34
34
|
const item = useChatStore(
|
|
35
35
|
(s) => chatSelectors.currentChatsWithGuideMessage(meta)(s)[index],
|
|
@@ -4,12 +4,14 @@ import isEqual from 'fast-deep-equal';
|
|
|
4
4
|
import { ReactNode, memo, useCallback, useMemo, useState } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
|
|
7
|
+
import { useAgentStore } from '@/store/agent';
|
|
8
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
7
9
|
import { useChatStore } from '@/store/chat';
|
|
8
10
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
9
11
|
import { useGlobalStore } from '@/store/global';
|
|
10
12
|
import { settingsSelectors } from '@/store/global/selectors';
|
|
11
13
|
import { useSessionStore } from '@/store/session';
|
|
12
|
-
import {
|
|
14
|
+
import { sessionMetaSelectors } from '@/store/session/selectors';
|
|
13
15
|
import { ChatMessage } from '@/types/message';
|
|
14
16
|
|
|
15
17
|
import ErrorMessageExtra, { getErrorAlertConfig } from '../../Error';
|
|
@@ -40,12 +42,12 @@ const Item = memo<ChatListItemProps>(({ index, id }) => {
|
|
|
40
42
|
const { t } = useTranslation('common');
|
|
41
43
|
const { styles, cx } = useStyles();
|
|
42
44
|
const [editing, setEditing] = useState(false);
|
|
43
|
-
const [type = 'chat'] =
|
|
45
|
+
const [type = 'chat'] = useAgentStore((s) => {
|
|
44
46
|
const config = agentSelectors.currentAgentConfig(s);
|
|
45
47
|
return [config.displayMode];
|
|
46
48
|
});
|
|
47
49
|
|
|
48
|
-
const meta = useSessionStore(
|
|
50
|
+
const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
|
|
49
51
|
const item = useChatStore((s) => {
|
|
50
52
|
const chats = chatSelectors.currentChatsWithGuideMessage(meta)(s);
|
|
51
53
|
|
|
@@ -99,7 +101,7 @@ const Item = memo<ChatListItemProps>(({ index, id }) => {
|
|
|
99
101
|
return { message: errorT(`response.${messageError.type}` as any), ...alertConfig };
|
|
100
102
|
}, [item?.error]);
|
|
101
103
|
|
|
102
|
-
const enableHistoryDivider =
|
|
104
|
+
const enableHistoryDivider = useAgentStore((s) => {
|
|
103
105
|
const config = agentSelectors.currentAgentConfig(s);
|
|
104
106
|
return (
|
|
105
107
|
config.enableHistoryCount &&
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useAgentStore } from '@/store/agent';
|
|
4
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
3
5
|
import { useChatStore } from '@/store/chat';
|
|
4
6
|
import { useSessionStore } from '@/store/session';
|
|
5
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
6
7
|
import { useToolStore } from '@/store/tool';
|
|
7
8
|
|
|
8
9
|
export const useInitConversation = () => {
|
|
9
10
|
const [sessionId] = useSessionStore((s) => [s.activeId]);
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const [useFetchAgentConfig] = useAgentStore((s) => [s.useFetchAgentConfig]);
|
|
12
|
+
const plugins = useAgentStore((s) => agentSelectors.currentAgentPlugins(s));
|
|
13
|
+
const [activeTopicId, switchTopic, useFetchMessages, useFetchTopics] = useChatStore((s) => [
|
|
13
14
|
s.activeTopicId,
|
|
14
15
|
s.switchTopic,
|
|
15
16
|
s.useFetchMessages,
|
|
@@ -18,6 +19,7 @@ export const useInitConversation = () => {
|
|
|
18
19
|
|
|
19
20
|
useFetchMessages(sessionId, activeTopicId);
|
|
20
21
|
useFetchTopics(sessionId);
|
|
22
|
+
useFetchAgentConfig(sessionId);
|
|
21
23
|
|
|
22
24
|
const [useFetchPluginStore, useFetchInstalledPlugins, checkPluginsIsInstalled] = useToolStore(
|
|
23
25
|
(s) => [s.useFetchPluginStore, s.useFetchInstalledPlugins, s.useCheckPluginsIsInstalled],
|
|
@@ -31,14 +33,15 @@ export const useInitConversation = () => {
|
|
|
31
33
|
// // when activeId changed, switch topic to undefined
|
|
32
34
|
const unsubscribe = useSessionStore.subscribe(
|
|
33
35
|
(s) => s.activeId,
|
|
34
|
-
() => {
|
|
36
|
+
(activeId) => {
|
|
35
37
|
switchTopic();
|
|
38
|
+
|
|
39
|
+
useAgentStore.setState({ activeId }, false, 'updateActiveId');
|
|
36
40
|
},
|
|
37
41
|
);
|
|
42
|
+
|
|
38
43
|
return () => {
|
|
39
44
|
unsubscribe();
|
|
40
45
|
};
|
|
41
46
|
}, []);
|
|
42
|
-
|
|
43
|
-
return init;
|
|
44
47
|
};
|
|
@@ -3,6 +3,7 @@ import { ReactNode, memo } from 'react';
|
|
|
3
3
|
import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
5
5
|
import ChatHydration from '@/components/StoreHydration/ChatHydration';
|
|
6
|
+
import { useChatStore } from '@/store/chat';
|
|
6
7
|
|
|
7
8
|
import SkeletonList from './components/SkeletonList';
|
|
8
9
|
import ChatList from './components/VirtualizedList';
|
|
@@ -29,16 +30,18 @@ interface ConversationProps {
|
|
|
29
30
|
const Conversation = memo<ConversationProps>(({ chatInput, mobile }) => {
|
|
30
31
|
const { styles } = useStyles();
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
useInitConversation();
|
|
34
|
+
|
|
35
|
+
const [messagesInit] = useChatStore((s) => [s.messagesInit]);
|
|
33
36
|
|
|
34
37
|
return (
|
|
35
38
|
<Flexbox
|
|
36
39
|
flex={1}
|
|
37
|
-
//
|
|
40
|
+
// `relative` is required, ChatInput's absolute position needs it
|
|
38
41
|
style={{ position: 'relative' }}
|
|
39
42
|
>
|
|
40
43
|
<div className={styles}>
|
|
41
|
-
{
|
|
44
|
+
{messagesInit ? <ChatList mobile={mobile} /> : <SkeletonList mobile={mobile} />}
|
|
42
45
|
</div>
|
|
43
46
|
{chatInput}
|
|
44
47
|
<ChatHydration />
|
|
@@ -9,10 +9,10 @@ import { useTranslation } from 'react-i18next';
|
|
|
9
9
|
import { Flexbox } from 'react-layout-kit';
|
|
10
10
|
|
|
11
11
|
import { ModelItemRender, ProviderItemRender } from '@/components/ModelSelect';
|
|
12
|
+
import { useAgentStore } from '@/store/agent';
|
|
13
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
12
14
|
import { useGlobalStore } from '@/store/global';
|
|
13
15
|
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
14
|
-
import { useSessionStore } from '@/store/session';
|
|
15
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
16
16
|
import { ModelProviderCard } from '@/types/llm';
|
|
17
17
|
import { withBasePath } from '@/utils/basePath';
|
|
18
18
|
|
|
@@ -40,8 +40,10 @@ const useStyles = createStyles(({ css, prefixCls }) => ({
|
|
|
40
40
|
const ModelSwitchPanel = memo<PropsWithChildren>(({ children }) => {
|
|
41
41
|
const { t } = useTranslation('components');
|
|
42
42
|
const { styles, theme } = useStyles();
|
|
43
|
-
const model =
|
|
44
|
-
|
|
43
|
+
const [model, updateAgentConfig] = useAgentStore((s) => [
|
|
44
|
+
agentSelectors.currentAgentModel(s),
|
|
45
|
+
s.updateAgentConfig,
|
|
46
|
+
]);
|
|
45
47
|
|
|
46
48
|
const router = useRouter();
|
|
47
49
|
const enabledList = useGlobalStore(
|
package/src/hooks/useTTS.ts
CHANGED
|
@@ -11,10 +11,10 @@ import isEqual from 'fast-deep-equal';
|
|
|
11
11
|
|
|
12
12
|
import { createHeaderWithOpenAI } from '@/services/_header';
|
|
13
13
|
import { API_ENDPOINTS } from '@/services/_url';
|
|
14
|
+
import { useAgentStore } from '@/store/agent';
|
|
15
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
14
16
|
import { useGlobalStore } from '@/store/global';
|
|
15
17
|
import { settingsSelectors } from '@/store/global/selectors';
|
|
16
|
-
import { useSessionStore } from '@/store/session';
|
|
17
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
18
18
|
import { TTSServer } from '@/types/agent';
|
|
19
19
|
|
|
20
20
|
interface TTSConfig extends TTSOptions {
|
|
@@ -25,9 +25,9 @@ interface TTSConfig extends TTSOptions {
|
|
|
25
25
|
|
|
26
26
|
export const useTTS = (content: string, config?: TTSConfig) => {
|
|
27
27
|
const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
|
|
28
|
-
const ttsAgentSettings =
|
|
28
|
+
const ttsAgentSettings = useAgentStore(agentSelectors.currentAgentTTS, isEqual);
|
|
29
29
|
const lang = useGlobalStore(settingsSelectors.currentLanguage);
|
|
30
|
-
const voice =
|
|
30
|
+
const voice = useAgentStore(agentSelectors.currentAgentTTSVoice(lang));
|
|
31
31
|
let useSelectedTTS;
|
|
32
32
|
let options: any = {};
|
|
33
33
|
switch (config?.server || ttsAgentSettings.ttsService) {
|
|
@@ -24,7 +24,7 @@ export class LobeOllamaAI implements LobeRuntimeAI {
|
|
|
24
24
|
throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidOllamaArgs);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
this.client = new Ollama(!baseURL ? undefined : { host:
|
|
27
|
+
this.client = new Ollama(!baseURL ? undefined : { host: baseURL });
|
|
28
28
|
|
|
29
29
|
if (baseURL) this.baseURL = baseURL;
|
|
30
30
|
}
|