@lobehub/chat 0.43.0 → 0.44.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.
- package/.github/workflows/release.yml +1 -1
- package/CHANGELOG.md +49 -0
- package/package.json +5 -2
- package/src/const/meta.ts +3 -0
- package/src/const/session.ts +1 -0
- package/src/helpers/export.ts +15 -9
- package/src/locales/default/common.ts +8 -1
- package/src/pages/chat/SessionList/Inbox.tsx +23 -0
- package/src/pages/chat/SessionList/List/SessionItem.tsx +15 -4
- package/src/pages/chat/SessionList/List/index.tsx +3 -2
- package/src/pages/chat/SessionList/index.tsx +13 -1
- package/src/pages/chat/[id]/index.page.tsx +7 -9
- package/src/pages/chat/[id]/layout.tsx +7 -23
- package/src/pages/chat/[id]/setting/index.page.tsx +3 -3
- package/src/pages/chat/features/Conversation/ChatList/SkeletonList.tsx +43 -0
- package/src/pages/chat/{[id] → features}/Conversation/ChatList/index.tsx +35 -5
- package/src/pages/chat/{[id] → features}/Conversation/Input/index.tsx +1 -1
- package/src/pages/chat/{[id] → features}/Header/index.tsx +32 -34
- package/src/pages/chat/features/Sidebar/Inner.tsx +42 -0
- package/src/pages/chat/{[id]/Sidebar/Inner.tsx → features/Sidebar/SystemRole.tsx} +7 -37
- package/src/pages/chat/{[id] → features}/Sidebar/index.tsx +8 -4
- package/src/pages/chat/index.page.tsx +39 -1
- package/src/pages/chat/layout.tsx +27 -0
- package/src/pages/welcome/Footer/index.tsx +1 -0
- package/src/services/chatModel.ts +1 -1
- package/src/store/global/hooks/useOnFinishHydrationGlobal.ts +18 -0
- package/src/store/global/hooks/useSwitchSideBarOnInit.ts +4 -8
- package/src/store/session/hooks/index.ts +2 -0
- package/src/store/session/hooks/useOnFinishHydrationSession.ts +18 -0
- package/src/store/session/hooks/useSessionHydrated.ts +1 -1
- package/src/store/session/index.ts +1 -3
- package/src/store/session/initialState.ts +6 -3
- package/src/store/session/selectors.ts +3 -3
- package/src/store/session/slices/agentConfig/action.ts +2 -1
- package/src/store/session/slices/agentConfig/selectors.ts +11 -11
- package/src/store/session/slices/chat/actions/message.ts +13 -20
- package/src/store/session/slices/chat/actions/topic.ts +3 -1
- package/src/store/session/slices/chat/selectors/chat.ts +1 -1
- package/src/store/session/slices/chat/selectors/token.ts +1 -1
- package/src/store/session/slices/chat/selectors/topic.ts +4 -2
- package/src/store/session/slices/session/action.ts +29 -15
- package/src/store/session/slices/session/initialState.ts +18 -4
- package/src/store/session/slices/session/selectors/export.ts +13 -8
- package/src/store/session/slices/session/selectors/list.test.ts +303 -0
- package/src/store/session/slices/session/selectors/list.ts +8 -3
- package/src/store/session/store.ts +5 -5
- package/src/types/exportConfig.ts +93 -31
- package/src/utils/config.ts +9 -0
- package/src/pages/chat/SessionList/List/style.ts +0 -36
- package/src/store/session/slices/chat/index.ts +0 -3
- package/src/store/session/slices/session/index.ts +0 -3
- package/src/pages/chat/{[id] → features}/Conversation/ChatList/Error/ApiKeyForm.tsx +0 -0
- package/src/pages/chat/{[id] → features}/Conversation/ChatList/Error/ErrorActionContainer.tsx +0 -0
- package/src/pages/chat/{[id] → features}/Conversation/ChatList/Error/InvalidAccess.tsx +1 -1
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/Error/OpenAiBizError.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/Error/style.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/MessageExtra.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/OTPInput.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/Plugins/FunctionCall.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/Plugins/PluginMessage.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/Plugins/PluginResultRender.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/ChatList/Plugins/style.ts +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/Input/Action.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/Input/ActionRight.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/Input/Token.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Conversation/index.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Header/PluginTag.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Sidebar/Header.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Sidebar/Topic/DefaultContent.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Sidebar/Topic/TopicContent.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Sidebar/Topic/TopicItem.tsx +0 -0
- /package/src/pages/chat/{[id] → features}/Sidebar/Topic/index.tsx +0 -0
|
@@ -9,30 +9,37 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
9
9
|
|
|
10
10
|
import HeaderTitle from '@/components/HeaderTitle';
|
|
11
11
|
import Tag from '@/components/Tag';
|
|
12
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
|
12
13
|
import { useGlobalStore } from '@/store/global';
|
|
13
14
|
import { agentSelectors, useSessionHydrated, useSessionStore } from '@/store/session';
|
|
14
15
|
|
|
15
16
|
import PluginTag from './PluginTag';
|
|
16
17
|
|
|
17
|
-
const Header = memo(() => {
|
|
18
|
+
const Header = memo<{ settings?: boolean }>(({ settings = true }) => {
|
|
18
19
|
const init = useSessionHydrated();
|
|
20
|
+
|
|
19
21
|
const { t } = useTranslation('common');
|
|
20
22
|
|
|
21
|
-
const [title, description, avatar, backgroundColor,
|
|
23
|
+
const [id, title, description, avatar, backgroundColor, model, plugins] = useSessionStore((s) => [
|
|
24
|
+
s.activeId,
|
|
25
|
+
|
|
22
26
|
agentSelectors.currentAgentTitle(s),
|
|
23
27
|
agentSelectors.currentAgentDescription(s),
|
|
24
28
|
agentSelectors.currentAgentAvatar(s),
|
|
25
29
|
agentSelectors.currentAgentBackgroundColor(s),
|
|
26
|
-
s.activeId,
|
|
27
30
|
agentSelectors.currentAgentModel(s),
|
|
28
31
|
agentSelectors.currentAgentPlugins(s),
|
|
29
32
|
]);
|
|
30
33
|
|
|
34
|
+
const isInbox = id === INBOX_SESSION_ID;
|
|
31
35
|
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
32
36
|
s.preference.showChatSideBar,
|
|
33
37
|
s.toggleChatSideBar,
|
|
34
38
|
]);
|
|
35
39
|
|
|
40
|
+
const displayTitle = isInbox ? t('inbox.title') : title;
|
|
41
|
+
const displayDesc = isInbox ? t('inbox.desc') : description;
|
|
42
|
+
|
|
36
43
|
return (
|
|
37
44
|
<ChatHeader
|
|
38
45
|
left={
|
|
@@ -48,49 +55,40 @@ const Header = memo(() => {
|
|
|
48
55
|
</Flexbox>
|
|
49
56
|
) : (
|
|
50
57
|
<Flexbox align={'flex-start'} gap={12} horizontal>
|
|
51
|
-
<Avatar
|
|
52
|
-
avatar={avatar}
|
|
53
|
-
background={backgroundColor}
|
|
54
|
-
onClick={() => {
|
|
55
|
-
Router.push(`/chat/${id}/setting`);
|
|
56
|
-
}}
|
|
57
|
-
size={40}
|
|
58
|
-
style={{ cursor: 'pointer', flex: 'none' }}
|
|
59
|
-
title={title}
|
|
60
|
-
/>
|
|
58
|
+
<Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
|
|
61
59
|
<HeaderTitle
|
|
62
|
-
desc={
|
|
60
|
+
desc={displayDesc}
|
|
63
61
|
tag={
|
|
64
62
|
<>
|
|
65
63
|
<Tag>
|
|
66
|
-
<SiOpenai size={'11px'} style={{ marginTop:
|
|
64
|
+
<SiOpenai size={'11px'} style={{ marginTop: 2 }} />
|
|
67
65
|
{model}
|
|
68
66
|
</Tag>
|
|
69
67
|
{plugins?.length > 0 && <PluginTag plugins={plugins} />}
|
|
70
68
|
</>
|
|
71
69
|
}
|
|
72
|
-
title={
|
|
70
|
+
title={displayTitle}
|
|
73
71
|
/>
|
|
74
72
|
</Flexbox>
|
|
75
73
|
)
|
|
76
74
|
}
|
|
77
75
|
right={
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
<>
|
|
77
|
+
{/*<ActionIcon*/}
|
|
78
|
+
{/* icon={Share2}*/}
|
|
79
|
+
{/* onClick={() => {*/}
|
|
80
|
+
{/* // genShareUrl();*/}
|
|
81
|
+
{/* }}*/}
|
|
82
|
+
{/* size={{ fontSize: 24 }}*/}
|
|
83
|
+
{/* title={t('share')}*/}
|
|
84
|
+
{/*/>*/}
|
|
85
|
+
<ActionIcon
|
|
86
|
+
icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
|
|
87
|
+
onClick={() => toggleConfig()}
|
|
88
|
+
size={{ fontSize: 24 }}
|
|
89
|
+
title={t('roleAndArchive')}
|
|
90
|
+
/>
|
|
91
|
+
{settings && (
|
|
94
92
|
<ActionIcon
|
|
95
93
|
icon={Settings}
|
|
96
94
|
onClick={() => {
|
|
@@ -99,8 +97,8 @@ const Header = memo(() => {
|
|
|
99
97
|
size={{ fontSize: 24 }}
|
|
100
98
|
title={t('header.session', { ns: 'setting' })}
|
|
101
99
|
/>
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
)}
|
|
101
|
+
</>
|
|
104
102
|
}
|
|
105
103
|
/>
|
|
106
104
|
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DraggablePanelBody, SearchBar } from '@lobehub/ui';
|
|
2
|
+
import { Skeleton } from 'antd';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
import { useSessionHydrated } from '@/store/session';
|
|
8
|
+
|
|
9
|
+
import SystemRole from './SystemRole';
|
|
10
|
+
import { Topic } from './Topic';
|
|
11
|
+
|
|
12
|
+
const Inner = memo<{ systemRole: boolean }>(({ systemRole }) => {
|
|
13
|
+
const hydrated = useSessionHydrated();
|
|
14
|
+
const { t } = useTranslation('common');
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<DraggablePanelBody style={{ padding: 0 }}>
|
|
18
|
+
{systemRole && <SystemRole />}
|
|
19
|
+
<Flexbox gap={16} padding={16}>
|
|
20
|
+
<SearchBar placeholder={t('topic.searchPlaceholder')} spotlight type={'ghost'} />
|
|
21
|
+
{!hydrated ? (
|
|
22
|
+
<Flexbox gap={8} style={{ marginTop: 8 }}>
|
|
23
|
+
{Array.from({ length: 8 }).map((_, i) => (
|
|
24
|
+
<Skeleton
|
|
25
|
+
active
|
|
26
|
+
avatar={false}
|
|
27
|
+
key={i}
|
|
28
|
+
paragraph={{ rows: 1, width: '100%' }}
|
|
29
|
+
round
|
|
30
|
+
title={false}
|
|
31
|
+
/>
|
|
32
|
+
))}
|
|
33
|
+
</Flexbox>
|
|
34
|
+
) : (
|
|
35
|
+
<Topic />
|
|
36
|
+
)}
|
|
37
|
+
</Flexbox>
|
|
38
|
+
</DraggablePanelBody>
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export default Inner;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionIcon,
|
|
1
|
+
import { ActionIcon, EditableMessage } from '@lobehub/ui';
|
|
2
2
|
import { Skeleton } from 'antd';
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
4
|
import { Maximize2Icon } from 'lucide-react';
|
|
@@ -6,18 +6,10 @@ import { memo, useState } from 'react';
|
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
|
+
import Header from '@/pages/chat/features/Sidebar/Header';
|
|
9
10
|
import { agentSelectors, useSessionHydrated, useSessionStore } from '@/store/session';
|
|
10
11
|
|
|
11
|
-
import Header from './Header';
|
|
12
|
-
import { Topic } from './Topic';
|
|
13
|
-
|
|
14
12
|
const useStyles = createStyles(({ css, token }) => ({
|
|
15
|
-
desc: css`
|
|
16
|
-
color: ${token.colorText};
|
|
17
|
-
`,
|
|
18
|
-
model: css`
|
|
19
|
-
color: ${token.colorTextTertiary};
|
|
20
|
-
`,
|
|
21
13
|
prompt: css`
|
|
22
14
|
overflow-x: hidden;
|
|
23
15
|
overflow-y: auto;
|
|
@@ -46,14 +38,11 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
46
38
|
|
|
47
39
|
background: linear-gradient(to bottom, transparent, ${token.colorBgLayout});
|
|
48
40
|
`,
|
|
49
|
-
title: css`
|
|
50
|
-
font-size: ${token.fontSizeHeading4}px;
|
|
51
|
-
font-weight: bold;
|
|
52
|
-
`,
|
|
53
41
|
}));
|
|
54
42
|
|
|
55
|
-
const
|
|
43
|
+
const SystemRole = memo(() => {
|
|
56
44
|
const [openModal, setOpenModal] = useState(false);
|
|
45
|
+
|
|
57
46
|
const { styles } = useStyles();
|
|
58
47
|
const [systemRole, updateAgentConfig] = useSessionStore((s) => [
|
|
59
48
|
agentSelectors.currentAgentSystemRole(s),
|
|
@@ -63,7 +52,7 @@ const Inner = memo(() => {
|
|
|
63
52
|
const hydrated = useSessionHydrated();
|
|
64
53
|
const { t } = useTranslation('common');
|
|
65
54
|
return (
|
|
66
|
-
|
|
55
|
+
<>
|
|
67
56
|
<Header
|
|
68
57
|
actions={
|
|
69
58
|
<ActionIcon
|
|
@@ -101,27 +90,8 @@ const Inner = memo(() => {
|
|
|
101
90
|
<Skeleton active avatar={false} style={{ marginTop: 12 }} title={false} />
|
|
102
91
|
)}
|
|
103
92
|
</Flexbox>
|
|
104
|
-
|
|
105
|
-
<SearchBar placeholder={t('topic.searchPlaceholder')} spotlight type={'ghost'} />
|
|
106
|
-
{!hydrated ? (
|
|
107
|
-
<Flexbox gap={8} style={{ marginTop: 8 }}>
|
|
108
|
-
{Array.from({ length: 8 }).map((_, i) => (
|
|
109
|
-
<Skeleton
|
|
110
|
-
active
|
|
111
|
-
avatar={false}
|
|
112
|
-
key={i}
|
|
113
|
-
paragraph={{ rows: 1, width: '100%' }}
|
|
114
|
-
round
|
|
115
|
-
title={false}
|
|
116
|
-
/>
|
|
117
|
-
))}
|
|
118
|
-
</Flexbox>
|
|
119
|
-
) : (
|
|
120
|
-
<Topic />
|
|
121
|
-
)}
|
|
122
|
-
</Flexbox>
|
|
123
|
-
</DraggablePanelBody>
|
|
93
|
+
</>
|
|
124
94
|
);
|
|
125
95
|
});
|
|
126
96
|
|
|
127
|
-
export default
|
|
97
|
+
export default SystemRole;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DraggablePanel, DraggablePanelContainer } from '@lobehub/ui';
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
3
|
import { rgba } from 'polished';
|
|
4
|
+
import { memo } from 'react';
|
|
4
5
|
|
|
5
6
|
import HeaderSpacing from '@/components/HeaderSpacing';
|
|
6
7
|
import { CHAT_SIDEBAR_WIDTH } from '@/const/layoutTokens';
|
|
@@ -20,7 +21,10 @@ const useStyles = createStyles(({ cx, css, token, stylish }) => ({
|
|
|
20
21
|
`,
|
|
21
22
|
}));
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
interface SideBarProps {
|
|
25
|
+
systemRole?: boolean;
|
|
26
|
+
}
|
|
27
|
+
const SideBar = memo<SideBarProps>(({ systemRole = true }) => {
|
|
24
28
|
const { styles } = useStyles();
|
|
25
29
|
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
26
30
|
s.preference.showChatSideBar,
|
|
@@ -37,10 +41,10 @@ const Config = () => {
|
|
|
37
41
|
>
|
|
38
42
|
<HeaderSpacing />
|
|
39
43
|
<DraggablePanelContainer style={{ flex: 'none', minWidth: CHAT_SIDEBAR_WIDTH }}>
|
|
40
|
-
<Inner />
|
|
44
|
+
<Inner systemRole={systemRole} />
|
|
41
45
|
</DraggablePanelContainer>
|
|
42
46
|
</DraggablePanel>
|
|
43
47
|
);
|
|
44
|
-
};
|
|
48
|
+
});
|
|
45
49
|
|
|
46
|
-
export default
|
|
50
|
+
export default SideBar;
|
|
@@ -1 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
import Head from 'next/head';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
5
|
+
|
|
6
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
|
7
|
+
import { useOnFinishHydrationSession, useSessionStore } from '@/store/session';
|
|
8
|
+
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
9
|
+
|
|
10
|
+
import Conversation from './features/Conversation';
|
|
11
|
+
import Header from './features/Header';
|
|
12
|
+
import SideBar from './features/Sidebar';
|
|
13
|
+
import Layout from './layout';
|
|
14
|
+
|
|
15
|
+
const Chat = memo(() => {
|
|
16
|
+
const { t } = useTranslation('common');
|
|
17
|
+
|
|
18
|
+
const pageTitle = genSiteHeadTitle(t('inbox.title'));
|
|
19
|
+
|
|
20
|
+
useOnFinishHydrationSession(() => {
|
|
21
|
+
useSessionStore.getState().activeSession(INBOX_SESSION_ID);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<Head>
|
|
27
|
+
<title>{pageTitle}</title>
|
|
28
|
+
</Head>
|
|
29
|
+
<Layout>
|
|
30
|
+
<Header settings={false} />
|
|
31
|
+
<Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
|
|
32
|
+
<Conversation />
|
|
33
|
+
<SideBar systemRole={false} />
|
|
34
|
+
</Flexbox>
|
|
35
|
+
</Layout>
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
export default Chat;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PropsWithChildren, memo } from 'react';
|
|
2
|
+
import { Flexbox } from 'react-layout-kit';
|
|
3
|
+
|
|
4
|
+
import AppLayout from '@/layout/AppLayout';
|
|
5
|
+
import { useSwitchSideBarOnInit } from '@/store/global';
|
|
6
|
+
|
|
7
|
+
import { Sessions } from './SessionList';
|
|
8
|
+
|
|
9
|
+
const ChatLayout = memo<PropsWithChildren>(({ children }) => {
|
|
10
|
+
useSwitchSideBarOnInit('chat');
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<AppLayout>
|
|
14
|
+
<Sessions />
|
|
15
|
+
<Flexbox
|
|
16
|
+
flex={1}
|
|
17
|
+
height={'100vh'}
|
|
18
|
+
id={'lobe-conversion-container'}
|
|
19
|
+
style={{ position: 'relative' }}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</Flexbox>
|
|
23
|
+
</AppLayout>
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export default ChatLayout;
|
|
@@ -9,6 +9,7 @@ import { CHANGELOG, DISCORD, GITHUB } from '@/const/url';
|
|
|
9
9
|
|
|
10
10
|
const Footer = memo(() => {
|
|
11
11
|
const theme = useTheme();
|
|
12
|
+
|
|
12
13
|
return (
|
|
13
14
|
<Flexbox align={'center'} horizontal justify={'space-between'} style={{ padding: 16 }}>
|
|
14
15
|
<span style={{ color: theme.colorTextDescription }}>©{new Date().getFullYear()} LobeHub</span>
|
|
@@ -2,7 +2,7 @@ import { merge } from 'lodash-es';
|
|
|
2
2
|
|
|
3
3
|
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY, OPENAI_END_POINT } from '@/const/fetch';
|
|
4
4
|
import { useGlobalStore } from '@/store/global';
|
|
5
|
-
import { initialLobeAgentConfig } from '@/store/session';
|
|
5
|
+
import { initialLobeAgentConfig } from '@/store/session/initialState';
|
|
6
6
|
import type { OpenAIStreamPayload } from '@/types/openai';
|
|
7
7
|
|
|
8
8
|
import { URLS } from './url';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useGlobalStore } from '../store';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 当 Session 水合完毕后才会执行的 useEffect
|
|
7
|
+
* @param fn
|
|
8
|
+
* @param deps
|
|
9
|
+
*/
|
|
10
|
+
export const useOnFinishHydrationGlobal = (fn: () => void, deps: any[] = []) => {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const hasRehydrated = useGlobalStore.persist.hasHydrated();
|
|
13
|
+
// 只有当水合完毕后再开始做操作
|
|
14
|
+
if (!hasRehydrated) return;
|
|
15
|
+
|
|
16
|
+
fn();
|
|
17
|
+
}, deps);
|
|
18
|
+
};
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
|
|
3
1
|
import { SidebarTabKey } from '../initialState';
|
|
4
2
|
import { useGlobalStore } from '../store';
|
|
3
|
+
import { useOnFinishHydrationGlobal } from './useOnFinishHydrationGlobal';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* 切换侧边栏选项
|
|
8
7
|
* @desc 只会在应用初始化时(且水合后)执行一次
|
|
9
8
|
*/
|
|
10
9
|
export const useSwitchSideBarOnInit = (key: SidebarTabKey) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
useGlobalStore.getState().switchSideBar(key);
|
|
15
|
-
}
|
|
16
|
-
}, []);
|
|
10
|
+
useOnFinishHydrationGlobal(() => {
|
|
11
|
+
useGlobalStore.getState().switchSideBar(key);
|
|
12
|
+
});
|
|
17
13
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useSessionStore } from '../store';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 当 Session 水合完毕后才会执行的 useEffect
|
|
7
|
+
* @param fn
|
|
8
|
+
* @param deps
|
|
9
|
+
*/
|
|
10
|
+
export const useOnFinishHydrationSession = (fn: () => void, deps: any[] = []) => {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const hasRehydrated = useSessionStore.persist.hasHydrated();
|
|
13
|
+
// 只有当水合完毕后再开始做操作
|
|
14
|
+
if (!hasRehydrated) return;
|
|
15
|
+
|
|
16
|
+
fn();
|
|
17
|
+
}, deps);
|
|
18
|
+
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export * from './hooks
|
|
1
|
+
export * from './hooks';
|
|
2
2
|
export * from './selectors';
|
|
3
|
-
export { initialLobeAgentConfig } from './slices/agentConfig';
|
|
4
|
-
export { initLobeSession } from './slices/session';
|
|
5
3
|
export type { SessionStore } from './store';
|
|
6
4
|
export { useSessionStore } from './store';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AgentConfigState, initialAgentConfigState } from './slices/agentConfig';
|
|
2
|
-
import { ChatState, initialChatState } from './slices/chat';
|
|
3
|
-
import { SessionState, initialSessionState } from './slices/session';
|
|
1
|
+
import { AgentConfigState, initialAgentConfigState } from './slices/agentConfig/initialState';
|
|
2
|
+
import { ChatState, initialChatState } from './slices/chat/initialState';
|
|
3
|
+
import { SessionState, initialSessionState } from './slices/session/initialState';
|
|
4
4
|
|
|
5
5
|
export type SessionStoreState = SessionState & ChatState & AgentConfigState;
|
|
6
6
|
|
|
@@ -9,3 +9,6 @@ export const initialState: SessionStoreState = {
|
|
|
9
9
|
...initialChatState,
|
|
10
10
|
...initialAgentConfigState,
|
|
11
11
|
};
|
|
12
|
+
|
|
13
|
+
export { initialLobeAgentConfig } from './slices/agentConfig';
|
|
14
|
+
export { initLobeSession } from './slices/session/initialState';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { agentSelectors } from './slices/agentConfig';
|
|
2
|
-
export { chatSelectors, topicSelectors } from './slices/chat';
|
|
3
|
-
export { sessionSelectors } from './slices/session';
|
|
1
|
+
export { agentSelectors } from './slices/agentConfig/selectors';
|
|
2
|
+
export { chatSelectors, topicSelectors } from './slices/chat/selectors';
|
|
3
|
+
export { sessionSelectors } from './slices/session/selectors';
|
|
@@ -2,12 +2,13 @@ import { produce } from 'immer';
|
|
|
2
2
|
import { StateCreator } from 'zustand/vanilla';
|
|
3
3
|
|
|
4
4
|
import { promptPickEmoji, promptSummaryAgentName, promptSummaryDescription } from '@/prompts/agent';
|
|
5
|
-
import { SessionStore, sessionSelectors } from '@/store/session';
|
|
6
5
|
import { MetaData } from '@/types/meta';
|
|
7
6
|
import { LobeAgentConfig } from '@/types/session';
|
|
8
7
|
import { fetchPresetTaskResult } from '@/utils/fetch';
|
|
9
8
|
import { setNamespace } from '@/utils/storeDebug';
|
|
10
9
|
|
|
10
|
+
import { SessionStore } from '../../store';
|
|
11
|
+
import { sessionSelectors } from '../session/selectors';
|
|
11
12
|
import { SessionLoadingState } from './initialState';
|
|
12
13
|
|
|
13
14
|
const t = setNamespace('agentConfig');
|
|
@@ -7,7 +7,7 @@ import { SessionStore } from '@/store/session';
|
|
|
7
7
|
import { LanguageModel } from '@/types/llm';
|
|
8
8
|
import { MetaData } from '@/types/meta';
|
|
9
9
|
|
|
10
|
-
import { sessionSelectors } from '../session';
|
|
10
|
+
import { sessionSelectors } from '../session/selectors';
|
|
11
11
|
import { initialLobeAgentConfig } from './initialState';
|
|
12
12
|
|
|
13
13
|
const currentAgentMeta = (s: SessionStore): MetaData => {
|
|
@@ -25,8 +25,17 @@ const currentAutocomplete = (s: SessionStore): Autocomplete => ({
|
|
|
25
25
|
|
|
26
26
|
const currentAgentTitle = (s: SessionStore) => currentAgentMeta(s)?.title || t('defaultSession');
|
|
27
27
|
|
|
28
|
+
const currentAgentConfig = (s: SessionStore) => {
|
|
29
|
+
const session = sessionSelectors.currentSession(s);
|
|
30
|
+
return merge({}, initialLobeAgentConfig, session?.config);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const currentAgentSystemRole = (s: SessionStore) => {
|
|
34
|
+
return currentAgentConfig(s).systemRole;
|
|
35
|
+
};
|
|
36
|
+
|
|
28
37
|
const currentAgentDescription = (s: SessionStore) =>
|
|
29
|
-
currentAgentMeta(s)?.description || t('noDescription');
|
|
38
|
+
currentAgentMeta(s)?.description || currentAgentSystemRole(s) || t('noDescription');
|
|
30
39
|
|
|
31
40
|
const currentAgentBackgroundColor = (s: SessionStore) => {
|
|
32
41
|
const session = sessionSelectors.currentSession(s);
|
|
@@ -41,15 +50,6 @@ const currentAgentAvatar = (s: SessionStore) => {
|
|
|
41
50
|
return session.meta.avatar || DEFAULT_AVATAR;
|
|
42
51
|
};
|
|
43
52
|
|
|
44
|
-
const currentAgentConfig = (s: SessionStore) => {
|
|
45
|
-
const session = sessionSelectors.currentSession(s);
|
|
46
|
-
return merge({}, initialLobeAgentConfig, session?.config);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const currentAgentSystemRole = (s: SessionStore) => {
|
|
50
|
-
return currentAgentConfig(s).systemRole;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
53
|
const currentAgentModel = (s: SessionStore): LanguageModel => {
|
|
54
54
|
const config = currentAgentConfig(s);
|
|
55
55
|
|
|
@@ -4,15 +4,18 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
4
4
|
import { LOADING_FLAT } from '@/const/message';
|
|
5
5
|
import { fetchChatModel } from '@/services/chatModel';
|
|
6
6
|
import { fetchPlugin } from '@/services/plugin';
|
|
7
|
-
import { SessionStore
|
|
8
|
-
import { getSlicedMessagesWithConfig } from '@/store/session/slices/chat/utils';
|
|
7
|
+
import { SessionStore } from '@/store/session';
|
|
9
8
|
import { ChatMessage, OpenAIFunctionCall } from '@/types/chatMessage';
|
|
10
9
|
import { fetchSSE } from '@/utils/fetch';
|
|
11
10
|
import { isFunctionMessage } from '@/utils/message';
|
|
12
11
|
import { setNamespace } from '@/utils/storeDebug';
|
|
13
12
|
import { nanoid } from '@/utils/uuid';
|
|
14
13
|
|
|
14
|
+
import { agentSelectors } from '../../agentConfig/selectors';
|
|
15
|
+
import { sessionSelectors } from '../../session/selectors';
|
|
15
16
|
import { MessageDispatch, messagesReducer } from '../reducers/message';
|
|
17
|
+
import { chatSelectors } from '../selectors';
|
|
18
|
+
import { getSlicedMessagesWithConfig } from '../utils';
|
|
16
19
|
|
|
17
20
|
const t = setNamespace('chat/message');
|
|
18
21
|
|
|
@@ -24,11 +27,6 @@ export interface ChatMessageAction {
|
|
|
24
27
|
* 清除消息
|
|
25
28
|
*/
|
|
26
29
|
clearMessage: () => void;
|
|
27
|
-
/**
|
|
28
|
-
* 创建或发送消息
|
|
29
|
-
* @param text - 消息文本
|
|
30
|
-
*/
|
|
31
|
-
createOrSendMsg: (text: string) => Promise<void>;
|
|
32
30
|
/**
|
|
33
31
|
* 删除消息
|
|
34
32
|
* @param id - 消息 ID
|
|
@@ -86,19 +84,6 @@ export const chatMessage: StateCreator<
|
|
|
86
84
|
}
|
|
87
85
|
},
|
|
88
86
|
|
|
89
|
-
createOrSendMsg: async (message) => {
|
|
90
|
-
if (!message) return;
|
|
91
|
-
|
|
92
|
-
const { sendMessage, createSession } = get();
|
|
93
|
-
const session = sessionSelectors.currentSession(get());
|
|
94
|
-
|
|
95
|
-
if (!session) {
|
|
96
|
-
await createSession();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
sendMessage(message);
|
|
100
|
-
},
|
|
101
|
-
|
|
102
87
|
deleteMessage: (id) => {
|
|
103
88
|
get().dispatchMessage({ id, type: 'deleteMessage' });
|
|
104
89
|
},
|
|
@@ -325,4 +310,12 @@ export const chatMessage: StateCreator<
|
|
|
325
310
|
|
|
326
311
|
await realFetchAIResponse(chats, message.id);
|
|
327
312
|
},
|
|
313
|
+
|
|
314
|
+
// genShareUrl: () => {
|
|
315
|
+
// const session = sessionSelectors.currentSession(get());
|
|
316
|
+
// if (!session) return '';
|
|
317
|
+
//
|
|
318
|
+
// const agent = session.config;
|
|
319
|
+
// return genShareMessagesUrl(session.chats, agent.systemRole);
|
|
320
|
+
// },
|
|
328
321
|
});
|
|
@@ -2,12 +2,14 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
2
2
|
|
|
3
3
|
import { LOADING_FLAT } from '@/const/message';
|
|
4
4
|
import { promptSummaryTitle } from '@/prompts/chat';
|
|
5
|
-
import { SessionStore
|
|
5
|
+
import { SessionStore } from '@/store/session';
|
|
6
6
|
import { fetchPresetTaskResult } from '@/utils/fetch';
|
|
7
7
|
import { setNamespace } from '@/utils/storeDebug';
|
|
8
8
|
import { nanoid } from '@/utils/uuid';
|
|
9
9
|
|
|
10
|
+
import { sessionSelectors } from '../../session/selectors';
|
|
10
11
|
import { ChatTopicDispatch, topicReducer } from '../reducers/topic';
|
|
12
|
+
import { chatSelectors, topicSelectors } from '../selectors';
|
|
11
13
|
|
|
12
14
|
const t = setNamespace('chat/topic');
|
|
13
15
|
export interface ChatTopicAction {
|
|
@@ -4,7 +4,7 @@ import { ChatMessage } from '@/types/chatMessage';
|
|
|
4
4
|
|
|
5
5
|
import type { SessionStore } from '../../../store';
|
|
6
6
|
import { agentSelectors } from '../../agentConfig';
|
|
7
|
-
import { sessionSelectors } from '../../session';
|
|
7
|
+
import { sessionSelectors } from '../../session/selectors';
|
|
8
8
|
import { getSlicedMessagesWithConfig } from '../utils';
|
|
9
9
|
import { organizeChats } from './utils';
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encode } from 'gpt-tokenizer';
|
|
2
2
|
|
|
3
|
-
import { agentSelectors } from '@/store/session';
|
|
3
|
+
import { agentSelectors } from '@/store/session/slices/agentConfig';
|
|
4
4
|
|
|
5
5
|
import type { SessionStore } from '../../../store';
|
|
6
6
|
import { currentChatsWithHistoryConfig } from './chat';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// 展示在聊天框中的消息
|
|
2
|
-
import { SessionStore, sessionSelectors } from '@/store/session';
|
|
3
|
-
import { organizeChats } from '@/store/session/slices/chat/selectors/utils';
|
|
4
2
|
import { ChatTopic } from '@/types/topic';
|
|
5
3
|
|
|
4
|
+
import { SessionStore } from '../../../store';
|
|
5
|
+
import { sessionSelectors } from '../../session/selectors';
|
|
6
|
+
import { organizeChats } from './utils';
|
|
7
|
+
|
|
6
8
|
export const currentTopics = (s: SessionStore): ChatTopic[] => {
|
|
7
9
|
const session = sessionSelectors.currentSession(s);
|
|
8
10
|
if (!session) return [];
|