@lobehub/chat 0.42.3 → 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 +74 -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/settings/Settings/Common.tsx +11 -2
- 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/global/slices/settings.ts +2 -2
- 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
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,80 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 0.44.0](https://github.com/lobehub/lobe-chat/compare/v0.43.0...v0.44.0)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-08-12**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: 优化 Inbox 会话的实现逻辑, 将 chat 中的功能模型拆分到 features 中, 重构 session 相关实现,移除循环依赖.
|
|
12
|
+
|
|
13
|
+
#### ✨ Features
|
|
14
|
+
|
|
15
|
+
- **misc**: 支持 inbox 消息导出, 支持 inbox 的会话功能, 新增 inbox 数据模型, 新增 inbox 模块入口.
|
|
16
|
+
|
|
17
|
+
#### 💄 Styles
|
|
18
|
+
|
|
19
|
+
- **misc**: Fix Inbox defaultMessage avatar, 优化 header 的 setting 展示, 优化门禁下默认的解锁方式, 补充 ChatList 的 Loading 态.
|
|
20
|
+
|
|
21
|
+
<br/>
|
|
22
|
+
|
|
23
|
+
<details>
|
|
24
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
25
|
+
|
|
26
|
+
#### Code refactoring
|
|
27
|
+
|
|
28
|
+
- **misc**: 优化 Inbox 会话的实现逻辑 ([22cc4cf](https://github.com/lobehub/lobe-chat/commit/22cc4cf))
|
|
29
|
+
- **misc**: 将 chat 中的功能模型拆分到 features 中 ([e25a856](https://github.com/lobehub/lobe-chat/commit/e25a856))
|
|
30
|
+
- **misc**: 重构 session 相关实现,移除循环依赖 ([9acf65c](https://github.com/lobehub/lobe-chat/commit/9acf65c))
|
|
31
|
+
|
|
32
|
+
#### What's improved
|
|
33
|
+
|
|
34
|
+
- **misc**: 支持 inbox 消息导出 ([498e075](https://github.com/lobehub/lobe-chat/commit/498e075))
|
|
35
|
+
- **misc**: 支持 inbox 的会话功能 ([9b713b8](https://github.com/lobehub/lobe-chat/commit/9b713b8))
|
|
36
|
+
- **misc**: 新增 inbox 数据模型 ([91a8158](https://github.com/lobehub/lobe-chat/commit/91a8158))
|
|
37
|
+
- **misc**: 新增 inbox 模块入口 ([6fc8907](https://github.com/lobehub/lobe-chat/commit/6fc8907))
|
|
38
|
+
|
|
39
|
+
#### Styles
|
|
40
|
+
|
|
41
|
+
- **misc**: Fix Inbox defaultMessage avatar ([dbc18a4](https://github.com/lobehub/lobe-chat/commit/dbc18a4))
|
|
42
|
+
- **misc**: 优化 header 的 setting 展示 ([201d380](https://github.com/lobehub/lobe-chat/commit/201d380))
|
|
43
|
+
- **misc**: 优化门禁下默认的解锁方式 ([df9bb45](https://github.com/lobehub/lobe-chat/commit/df9bb45))
|
|
44
|
+
- **misc**: 补充 ChatList 的 Loading 态 ([eb3eb5d](https://github.com/lobehub/lobe-chat/commit/eb3eb5d))
|
|
45
|
+
|
|
46
|
+
</details>
|
|
47
|
+
|
|
48
|
+
<div align="right">
|
|
49
|
+
|
|
50
|
+
[](#readme-top)
|
|
51
|
+
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
## [Version 0.43.0](https://github.com/lobehub/lobe-chat/compare/v0.42.3...v0.43.0)
|
|
55
|
+
|
|
56
|
+
<sup>Released on **2023-08-12**</sup>
|
|
57
|
+
|
|
58
|
+
#### ✨ Features
|
|
59
|
+
|
|
60
|
+
- **misc**: 支持切换语言.
|
|
61
|
+
|
|
62
|
+
<br/>
|
|
63
|
+
|
|
64
|
+
<details>
|
|
65
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
66
|
+
|
|
67
|
+
#### What's improved
|
|
68
|
+
|
|
69
|
+
- **misc**: 支持切换语言, closes [#67](https://github.com/lobehub/lobe-chat/issues/67) ([63ed8ec](https://github.com/lobehub/lobe-chat/commit/63ed8ec))
|
|
70
|
+
|
|
71
|
+
</details>
|
|
72
|
+
|
|
73
|
+
<div align="right">
|
|
74
|
+
|
|
75
|
+
[](#readme-top)
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
|
|
5
79
|
### [Version 0.42.3](https://github.com/lobehub/lobe-chat/compare/v0.42.2...v0.42.3)
|
|
6
80
|
|
|
7
81
|
<sup>Released on **2023-08-12**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"description": "Lobe Chat is an open-source chatbot client using LangChain, Typescript and Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatbot",
|
|
@@ -25,9 +25,11 @@
|
|
|
25
25
|
"dev": "next dev -p 3010",
|
|
26
26
|
"i18n": "npm run i18n:toc && lobe-i18n",
|
|
27
27
|
"i18n:toc": "ts-node --project ./tsconfig.json scripts/toc.ts",
|
|
28
|
-
"lint": "
|
|
28
|
+
"lint": "npm run lint:ts && npm run lint:style && npm run type-check && npm run lint:circular",
|
|
29
|
+
"lint:circular": "dpdm src/**/*.ts --warning false --tree false --exit-code circular:1 -T true",
|
|
29
30
|
"lint:md": "remark . --quiet --frail --output",
|
|
30
31
|
"lint:style": "stylelint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
|
|
32
|
+
"lint:ts": "eslint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
|
|
31
33
|
"prepare": "husky install",
|
|
32
34
|
"prettier": "prettier -c --write \"**/**\"",
|
|
33
35
|
"pull": "git pull",
|
|
@@ -116,6 +118,7 @@
|
|
|
116
118
|
"@vitest/coverage-v8": "latest",
|
|
117
119
|
"commitlint": "^17",
|
|
118
120
|
"consola": "^3",
|
|
121
|
+
"dpdm": "^3",
|
|
119
122
|
"eslint": "^8",
|
|
120
123
|
"husky": "^8",
|
|
121
124
|
"i18next-browser-languagedetector": "^7",
|
package/src/const/meta.ts
CHANGED
|
@@ -4,3 +4,6 @@ export const DEFAULT_AVATAR = '🤖';
|
|
|
4
4
|
export const DEFAULT_USER_AVATAR = '😀';
|
|
5
5
|
export const DEFAULT_BACKGROUND_COLOR = 'rgba(0,0,0,0)';
|
|
6
6
|
export const DEFAULT_AGENT_META: MetaData = {};
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_INBOX_AVATAR =
|
|
9
|
+
'https://npm.elemecdn.com/@lobehub/assets-logo/assets/logo-3d.webp';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const INBOX_SESSION_ID = 'inbox';
|
package/src/helpers/export.ts
CHANGED
|
@@ -2,22 +2,25 @@ import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
|
2
2
|
import { sessionSelectors, useSessionStore } from '@/store/session';
|
|
3
3
|
import { createConfigFile, exportConfigFile } from '@/utils/config';
|
|
4
4
|
|
|
5
|
-
const getAgents = () => sessionSelectors.exportAgents(useSessionStore.getState());
|
|
6
|
-
const getAgent = (id: string) => sessionSelectors.getExportAgent(id)(useSessionStore.getState());
|
|
7
|
-
|
|
8
5
|
const getSessions = () => sessionSelectors.exportSessions(useSessionStore.getState());
|
|
9
6
|
const getSession = (id: string) => sessionSelectors.getSessionById(id)(useSessionStore.getState());
|
|
10
7
|
|
|
11
8
|
const getSettings = () => settingsSelectors.exportSettings(useGlobalStore.getState());
|
|
12
9
|
|
|
10
|
+
// ============= 导出所有角色 ============= //
|
|
11
|
+
|
|
13
12
|
export const exportAgents = () => {
|
|
14
|
-
const
|
|
13
|
+
const agents = sessionSelectors.exportAgents(useSessionStore.getState());
|
|
15
14
|
|
|
16
|
-
const config = createConfigFile('agents',
|
|
15
|
+
const config = createConfigFile('agents', agents);
|
|
17
16
|
|
|
18
17
|
exportConfigFile(config, 'agents');
|
|
19
18
|
};
|
|
20
19
|
|
|
20
|
+
// ============= 导出单个角色 ============= //
|
|
21
|
+
|
|
22
|
+
const getAgent = (id: string) => sessionSelectors.getExportAgent(id)(useSessionStore.getState());
|
|
23
|
+
|
|
21
24
|
export const exportSingleAgent = (id: string) => {
|
|
22
25
|
const agent = getAgent(id);
|
|
23
26
|
if (!agent) return;
|
|
@@ -27,23 +30,26 @@ export const exportSingleAgent = (id: string) => {
|
|
|
27
30
|
exportConfigFile(config, agent.meta?.title || 'agent');
|
|
28
31
|
};
|
|
29
32
|
|
|
33
|
+
// ============= 导出所有会话 ============= //
|
|
34
|
+
|
|
30
35
|
export const exportSessions = () => {
|
|
31
|
-
const
|
|
32
|
-
const config = createConfigFile('sessions', { sessions });
|
|
36
|
+
const config = createConfigFile('sessions', getSessions());
|
|
33
37
|
|
|
34
38
|
exportConfigFile(config, 'sessions');
|
|
35
39
|
};
|
|
36
40
|
|
|
41
|
+
// ============= 导出单个会话 ============= //
|
|
37
42
|
export const exportSingleSession = (id: string) => {
|
|
38
43
|
const session = getSession(id);
|
|
39
44
|
if (!session) return;
|
|
40
45
|
const sessions = { [id]: session };
|
|
41
46
|
|
|
42
|
-
const config = createConfigFile('
|
|
47
|
+
const config = createConfigFile('singleSession', { sessions });
|
|
43
48
|
|
|
44
49
|
exportConfigFile(config, `${session.meta?.title}-session`);
|
|
45
50
|
};
|
|
46
51
|
|
|
52
|
+
// ============= 导出设置会话 ============= //
|
|
47
53
|
export const exportSettings = () => {
|
|
48
54
|
const settings = getSettings();
|
|
49
55
|
|
|
@@ -56,7 +62,7 @@ export const exportAll = () => {
|
|
|
56
62
|
const sessions = getSessions();
|
|
57
63
|
const settings = getSettings();
|
|
58
64
|
|
|
59
|
-
const config = createConfigFile('all', { sessions, settings });
|
|
65
|
+
const config = createConfigFile('all', { ...sessions, settings });
|
|
60
66
|
|
|
61
67
|
exportConfigFile(config, 'config');
|
|
62
68
|
};
|
|
@@ -17,7 +17,7 @@ export default {
|
|
|
17
17
|
copy: '复制',
|
|
18
18
|
copySuccess: '复制成功',
|
|
19
19
|
defaultAgent: '默认助手',
|
|
20
|
-
defaultSession: '
|
|
20
|
+
defaultSession: '默认助手',
|
|
21
21
|
delete: '删除',
|
|
22
22
|
edit: '编辑',
|
|
23
23
|
export: '导出配置',
|
|
@@ -31,6 +31,12 @@ export default {
|
|
|
31
31
|
},
|
|
32
32
|
feedback: '反馈与建议',
|
|
33
33
|
import: '导入配置',
|
|
34
|
+
inbox: {
|
|
35
|
+
defaultMessage:
|
|
36
|
+
'你好,我是你的智能助手,你可以问我任何问题,我会尽力回答你。如果需要获得更加专业或定制的助手,可以点击「+」创建自定义助手',
|
|
37
|
+
desc: '开启大脑集群,激发思维火花。你的智能助理,就在这里与你交流一切',
|
|
38
|
+
title: '随便聊聊',
|
|
39
|
+
},
|
|
34
40
|
message: {
|
|
35
41
|
function_loading: '插件请求中...',
|
|
36
42
|
},
|
|
@@ -47,6 +53,7 @@ export default {
|
|
|
47
53
|
searchAgentPlaceholder: '搜索助手和对话...',
|
|
48
54
|
send: '发送',
|
|
49
55
|
sendPlaceholder: '输入聊天内容...',
|
|
56
|
+
sessionList: '助手列表',
|
|
50
57
|
setting: '设置',
|
|
51
58
|
share: '分享',
|
|
52
59
|
tab: {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Avatar, List } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
import { DEFAULT_INBOX_AVATAR } from '@/const/meta';
|
|
6
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
|
7
|
+
import { useSessionStore } from '@/store/session';
|
|
8
|
+
|
|
9
|
+
const Inbox = memo(() => {
|
|
10
|
+
const { t } = useTranslation('common');
|
|
11
|
+
const [activeId, switchInbox] = useSessionStore((s) => [s.activeId, s.switchInbox]);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<List.Item
|
|
15
|
+
active={activeId === INBOX_SESSION_ID}
|
|
16
|
+
avatar={<Avatar avatar={DEFAULT_INBOX_AVATAR} size={46} style={{ padding: 3 }} />}
|
|
17
|
+
onClick={switchInbox}
|
|
18
|
+
title={t('inbox.title')}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default Inbox;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ActionIcon, Avatar, Icon, List } from '@lobehub/ui';
|
|
2
2
|
import { useHover } from 'ahooks';
|
|
3
3
|
import { App, Dropdown, type MenuProps, Tag } from 'antd';
|
|
4
|
+
import { createStyles } from 'antd-style';
|
|
4
5
|
import { FolderOutput, MoreVertical, Pin, PinOff, Trash } from 'lucide-react';
|
|
5
|
-
import {
|
|
6
|
+
import { memo, useMemo, useRef, useState } from 'react';
|
|
6
7
|
import { useTranslation } from 'react-i18next';
|
|
7
8
|
import { Flexbox } from 'react-layout-kit';
|
|
8
9
|
import { shallow } from 'zustand/shallow';
|
|
@@ -11,17 +12,27 @@ import { exportSingleAgent, exportSingleSession } from '@/helpers/export';
|
|
|
11
12
|
import { useGlobalStore } from '@/store/global';
|
|
12
13
|
import { agentSelectors, chatSelectors, sessionSelectors, useSessionStore } from '@/store/session';
|
|
13
14
|
|
|
14
|
-
import { useStyles } from './style';
|
|
15
|
-
|
|
16
15
|
const { Item } = List;
|
|
17
16
|
|
|
17
|
+
const useStyles = createStyles(({ css }) => {
|
|
18
|
+
return {
|
|
19
|
+
container: css`
|
|
20
|
+
position: relative;
|
|
21
|
+
`,
|
|
22
|
+
|
|
23
|
+
modalRoot: css`
|
|
24
|
+
z-index: 2000;
|
|
25
|
+
`,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
18
29
|
interface SessionItemProps {
|
|
19
30
|
active?: boolean;
|
|
20
31
|
id: string;
|
|
21
32
|
loading?: boolean;
|
|
22
33
|
}
|
|
23
34
|
|
|
24
|
-
const SessionItem
|
|
35
|
+
const SessionItem = memo<SessionItemProps>(({ id, active = true, loading }) => {
|
|
25
36
|
const [open, setOpen] = useState(false);
|
|
26
37
|
const ref = useRef(null);
|
|
27
38
|
const isHovering = useHover(ref);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import isEqual from 'fast-deep-equal';
|
|
2
2
|
import Link from 'next/link';
|
|
3
3
|
import { memo } from 'react';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
4
5
|
|
|
5
6
|
import { sessionSelectors, useSessionHydrated, useSessionStore } from '@/store/session';
|
|
6
7
|
|
|
@@ -16,13 +17,13 @@ const SessionList = memo(() => {
|
|
|
16
17
|
return !isInit ? (
|
|
17
18
|
<SkeletonItem />
|
|
18
19
|
) : (
|
|
19
|
-
|
|
20
|
+
<Flexbox>
|
|
20
21
|
{list.map(({ id }) => (
|
|
21
22
|
<Link href={`/chat/${id}`} key={id}>
|
|
22
23
|
<SessionItem active={activeId === id} id={id} loading={loading && id === activeId} />
|
|
23
24
|
</Link>
|
|
24
25
|
))}
|
|
25
|
-
|
|
26
|
+
</Flexbox>
|
|
26
27
|
);
|
|
27
28
|
});
|
|
28
29
|
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import { DraggablePanelBody } from '@lobehub/ui';
|
|
2
2
|
import { memo } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
3
5
|
|
|
4
6
|
import FolderPanel from '@/features/FolderPanel';
|
|
5
7
|
|
|
6
8
|
import Header from './Header';
|
|
9
|
+
import Inbox from './Inbox';
|
|
7
10
|
import SessionList from './List';
|
|
8
11
|
|
|
9
12
|
export const Sessions = memo(() => {
|
|
13
|
+
const { t } = useTranslation('common');
|
|
14
|
+
|
|
10
15
|
return (
|
|
11
16
|
<FolderPanel>
|
|
12
17
|
<Header />
|
|
13
18
|
<DraggablePanelBody style={{ padding: 0 }}>
|
|
14
|
-
<
|
|
19
|
+
<Flexbox gap={8}>
|
|
20
|
+
<Inbox />
|
|
21
|
+
|
|
22
|
+
<Flexbox paddingInline={20} style={{ fontSize: 12, marginTop: 8 }}>
|
|
23
|
+
{t('sessionList')}
|
|
24
|
+
</Flexbox>
|
|
25
|
+
<SessionList />
|
|
26
|
+
</Flexbox>
|
|
15
27
|
</DraggablePanelBody>
|
|
16
28
|
</FolderPanel>
|
|
17
29
|
);
|
|
@@ -5,9 +5,9 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
5
5
|
import { agentSelectors, useSessionStore } from '@/store/session';
|
|
6
6
|
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
7
7
|
|
|
8
|
-
import Conversation from '
|
|
9
|
-
import Header from '
|
|
10
|
-
import
|
|
8
|
+
import Conversation from '../features/Conversation';
|
|
9
|
+
import Header from '../features/Header';
|
|
10
|
+
import SideBar from '../features/Sidebar';
|
|
11
11
|
import Layout from './layout';
|
|
12
12
|
|
|
13
13
|
const Chat = memo(() => {
|
|
@@ -24,12 +24,10 @@ const Chat = memo(() => {
|
|
|
24
24
|
<title>{pageTitle}</title>
|
|
25
25
|
</Head>
|
|
26
26
|
<Layout>
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
<Config />
|
|
32
|
-
</Flexbox>
|
|
27
|
+
<Header />
|
|
28
|
+
<Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
|
|
29
|
+
<Conversation />
|
|
30
|
+
<SideBar />
|
|
33
31
|
</Flexbox>
|
|
34
32
|
</Layout>
|
|
35
33
|
</>
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { useRouter } from 'next/router';
|
|
2
|
-
import { PropsWithChildren, memo
|
|
3
|
-
import { Flexbox } from 'react-layout-kit';
|
|
2
|
+
import { PropsWithChildren, memo } from 'react';
|
|
4
3
|
import { shallow } from 'zustand/shallow';
|
|
5
4
|
|
|
6
|
-
import
|
|
7
|
-
import { useSwitchSideBarOnInit } from '@/store/global';
|
|
8
|
-
import { useSessionStore } from '@/store/session';
|
|
5
|
+
import { useOnFinishHydrationSession, useSessionStore } from '@/store/session';
|
|
9
6
|
|
|
10
|
-
import
|
|
7
|
+
import ChatLayout from '../layout';
|
|
11
8
|
|
|
12
|
-
const
|
|
9
|
+
const Layout = memo<PropsWithChildren>(({ children }) => {
|
|
13
10
|
const [activeSession, toggleTopic] = useSessionStore((s) => {
|
|
14
11
|
return [s.activeSession, s.toggleTopic];
|
|
15
12
|
}, shallow);
|
|
@@ -17,11 +14,7 @@ const ChatLayout = memo<PropsWithChildren>(({ children }) => {
|
|
|
17
14
|
const router = useRouter();
|
|
18
15
|
const { id } = router.query;
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
const hasRehydrated = useSessionStore.persist.hasHydrated();
|
|
22
|
-
// 只有当水合完毕后再开始做操作
|
|
23
|
-
if (!hasRehydrated) return;
|
|
24
|
-
|
|
17
|
+
useOnFinishHydrationSession(() => {
|
|
25
18
|
// 1. 正常激活会话
|
|
26
19
|
if (typeof id === 'string') {
|
|
27
20
|
activeSession(id);
|
|
@@ -31,16 +24,7 @@ const ChatLayout = memo<PropsWithChildren>(({ children }) => {
|
|
|
31
24
|
toggleTopic();
|
|
32
25
|
}, [id]);
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<AppLayout>
|
|
38
|
-
<Sessions />
|
|
39
|
-
<Flexbox flex={1} height={'100vh'} style={{ position: 'relative' }}>
|
|
40
|
-
{children}
|
|
41
|
-
</Flexbox>
|
|
42
|
-
</AppLayout>
|
|
43
|
-
);
|
|
27
|
+
return <ChatLayout>{children}</ChatLayout>;
|
|
44
28
|
});
|
|
45
29
|
|
|
46
|
-
export default
|
|
30
|
+
export default Layout;
|
|
@@ -7,10 +7,10 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
7
7
|
import HeaderSpacing from '@/components/HeaderSpacing';
|
|
8
8
|
import { HEADER_HEIGHT } from '@/const/layoutTokens';
|
|
9
9
|
import { AgentConfig, AgentMeta, AgentPlugin, AgentPrompt } from '@/features/AgentSetting';
|
|
10
|
-
import AppLayout from '@/layout/AppLayout';
|
|
11
10
|
import { agentSelectors, useSessionStore } from '@/store/session';
|
|
12
11
|
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
13
12
|
|
|
13
|
+
import ChatLayout from '../layout';
|
|
14
14
|
import Header from './Header';
|
|
15
15
|
|
|
16
16
|
const EditPage = memo(() => {
|
|
@@ -32,7 +32,7 @@ const EditPage = memo(() => {
|
|
|
32
32
|
<Head>
|
|
33
33
|
<title>{pageTitle}</title>
|
|
34
34
|
</Head>
|
|
35
|
-
<
|
|
35
|
+
<ChatLayout>
|
|
36
36
|
<Header />
|
|
37
37
|
<Flexbox align={'center'} flex={1} gap={16} padding={24} style={{ overflow: 'auto' }}>
|
|
38
38
|
<HeaderSpacing height={HEADER_HEIGHT - 16} />
|
|
@@ -46,7 +46,7 @@ const EditPage = memo(() => {
|
|
|
46
46
|
<AgentConfig config={config} updateConfig={updateAgentConfig} />
|
|
47
47
|
<AgentPlugin config={config} updateConfig={toggleAgentPlugin} />
|
|
48
48
|
</Flexbox>
|
|
49
|
-
</
|
|
49
|
+
</ChatLayout>
|
|
50
50
|
</>
|
|
51
51
|
);
|
|
52
52
|
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Skeleton } from 'antd';
|
|
2
|
+
import { createStyles } from 'antd-style';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
5
|
+
|
|
6
|
+
const useStyles = createStyles(({ css, prefixCls }) => ({
|
|
7
|
+
user: css`
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: row-reverse;
|
|
10
|
+
gap: 16px;
|
|
11
|
+
|
|
12
|
+
.${prefixCls}-skeleton-paragraph {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
align-items: flex-end;
|
|
16
|
+
}
|
|
17
|
+
`,
|
|
18
|
+
}));
|
|
19
|
+
const SkeletonList = memo(() => {
|
|
20
|
+
const { styles } = useStyles();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Flexbox gap={24} padding={12} style={{ marginTop: 24 }}>
|
|
24
|
+
<Skeleton
|
|
25
|
+
active
|
|
26
|
+
avatar={{ size: 40 }}
|
|
27
|
+
paragraph={{ width: ['50%', '30%'] }}
|
|
28
|
+
round
|
|
29
|
+
title={false}
|
|
30
|
+
/>
|
|
31
|
+
<Skeleton
|
|
32
|
+
active
|
|
33
|
+
avatar={{ size: 40 }}
|
|
34
|
+
className={styles.user}
|
|
35
|
+
paragraph={{ width: ['50%', '30%'] }}
|
|
36
|
+
round
|
|
37
|
+
// style={{ display: 'flex', flexDirection: 'row-reverse' }}
|
|
38
|
+
title={false}
|
|
39
|
+
/>
|
|
40
|
+
</Flexbox>
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
export default SkeletonList;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { ChatList, RenderErrorMessage, RenderMessage } from '@lobehub/ui';
|
|
2
2
|
import isEqual from 'fast-deep-equal';
|
|
3
|
-
import { memo, useCallback } from 'react';
|
|
3
|
+
import { memo, useCallback, useMemo } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { Flexbox } from 'react-layout-kit';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { DEFAULT_INBOX_AVATAR } from '@/const/meta';
|
|
8
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
|
9
|
+
import {
|
|
10
|
+
agentSelectors,
|
|
11
|
+
chatSelectors,
|
|
12
|
+
useSessionHydrated,
|
|
13
|
+
useSessionStore,
|
|
14
|
+
} from '@/store/session';
|
|
8
15
|
import { ChatMessage } from '@/types/chatMessage';
|
|
9
16
|
import { ErrorType } from '@/types/fetch';
|
|
10
17
|
import { isFunctionMessage } from '@/utils/message';
|
|
@@ -14,6 +21,7 @@ import OpenAiBizError from './Error/OpenAiBizError';
|
|
|
14
21
|
import MessageExtra from './MessageExtra';
|
|
15
22
|
import FunctionCall from './Plugins/FunctionCall';
|
|
16
23
|
import PluginMessage from './Plugins/PluginMessage';
|
|
24
|
+
import SkeletonList from './SkeletonList';
|
|
17
25
|
|
|
18
26
|
const renderErrorMessage: RenderErrorMessage = (error, message) => {
|
|
19
27
|
switch (error.type as ErrorType) {
|
|
@@ -27,11 +35,14 @@ const renderErrorMessage: RenderErrorMessage = (error, message) => {
|
|
|
27
35
|
};
|
|
28
36
|
|
|
29
37
|
const List = () => {
|
|
38
|
+
const init = useSessionHydrated();
|
|
30
39
|
const { t } = useTranslation('common');
|
|
31
40
|
|
|
32
41
|
const data = useSessionStore(chatSelectors.currentChats, isEqual);
|
|
33
|
-
|
|
42
|
+
|
|
43
|
+
const [isInbox, displayMode, chatLoadingId, deleteMessage, resendMessage, dispatchMessage] =
|
|
34
44
|
useSessionStore((s) => [
|
|
45
|
+
s.activeId === INBOX_SESSION_ID,
|
|
35
46
|
agentSelectors.currentAgentConfig(s).displayMode,
|
|
36
47
|
s.chatLoadingId,
|
|
37
48
|
s.deleteMessage,
|
|
@@ -70,9 +81,28 @@ const List = () => {
|
|
|
70
81
|
[chatLoadingId],
|
|
71
82
|
);
|
|
72
83
|
|
|
73
|
-
|
|
84
|
+
// 针对 inbox 添加初始化时的自定义消息
|
|
85
|
+
const displayDataSource = useMemo(() => {
|
|
86
|
+
const emptyGuideMessage = {
|
|
87
|
+
content: t('inbox.defaultMessage'),
|
|
88
|
+
createAt: Date.now(),
|
|
89
|
+
extra: {},
|
|
90
|
+
id: 'default',
|
|
91
|
+
meta: {
|
|
92
|
+
avatar: DEFAULT_INBOX_AVATAR,
|
|
93
|
+
},
|
|
94
|
+
role: 'assistant',
|
|
95
|
+
updateAt: Date.now(),
|
|
96
|
+
} as ChatMessage;
|
|
97
|
+
|
|
98
|
+
return isInbox && data.length === 0 ? [emptyGuideMessage] : data;
|
|
99
|
+
}, [data]);
|
|
100
|
+
|
|
101
|
+
return !init ? (
|
|
102
|
+
<SkeletonList />
|
|
103
|
+
) : (
|
|
74
104
|
<ChatList
|
|
75
|
-
data={
|
|
105
|
+
data={displayDataSource}
|
|
76
106
|
loadingId={chatLoadingId}
|
|
77
107
|
onActionClick={(key, id) => {
|
|
78
108
|
switch (key) {
|