@lobehub/chat 0.13.1 → 0.15.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 +51 -0
  2. package/README.md +3 -3
  3. package/locales/en_US/common.json +19 -27
  4. package/locales/en_US/plugin.json +10 -0
  5. package/locales/en_US/setting.json +42 -6
  6. package/locales/zh_CN/common.json +8 -17
  7. package/locales/zh_CN/plugin.json +10 -0
  8. package/locales/zh_CN/setting.json +36 -0
  9. package/package.json +1 -1
  10. package/src/components/HeaderSpacing/index.tsx +3 -1
  11. package/src/components/HeaderTitle/index.tsx +42 -0
  12. package/src/const/layoutTokens.ts +6 -1
  13. package/src/const/meta.ts +3 -0
  14. package/src/locales/default/common.ts +31 -49
  15. package/src/locales/default/plugin.ts +10 -0
  16. package/src/locales/default/setting.ts +46 -1
  17. package/src/locales/resources/en_US.ts +2 -0
  18. package/src/locales/resources/zh_CN.ts +2 -0
  19. package/src/pages/chat/SessionList/List/SessionItem.tsx +1 -2
  20. package/src/pages/chat/[id]/Config/Header.tsx +26 -0
  21. package/src/pages/chat/[id]/Config/SideBar.tsx +86 -0
  22. package/src/pages/chat/[id]/Config/index.tsx +5 -45
  23. package/src/pages/chat/[id]/Conversation/FunctionMessage.tsx +1 -1
  24. package/src/pages/chat/[id]/Conversation/Input/Action.tsx +13 -5
  25. package/src/pages/chat/[id]/Conversation/Input/index.tsx +11 -3
  26. package/src/pages/chat/[id]/Conversation/MessageExtra.tsx +1 -1
  27. package/src/pages/chat/[id]/Header.tsx +34 -43
  28. package/src/pages/chat/[id]/edit/AgentConfig/index.tsx +154 -95
  29. package/src/pages/chat/[id]/edit/AgentMeta/AutoGenerateInput.tsx +39 -0
  30. package/src/pages/chat/[id]/edit/AgentMeta/BackgroundSwatches.tsx +31 -0
  31. package/src/pages/chat/[id]/edit/AgentMeta/EmojiPicker.tsx +7 -3
  32. package/src/pages/chat/[id]/edit/AgentMeta/index.tsx +68 -75
  33. package/src/pages/chat/[id]/edit/AgentPlugin/index.tsx +44 -0
  34. package/src/pages/chat/[id]/edit/AgentPrompt/index.tsx +48 -0
  35. package/src/pages/chat/[id]/edit/Header.tsx +31 -0
  36. package/src/pages/chat/[id]/edit/index.page.tsx +12 -40
  37. package/src/pages/chat/[id]/index.page.tsx +2 -1
  38. package/src/pages/setting/Header.tsx +4 -11
  39. package/src/pages/setting/SettingForm.tsx +9 -9
  40. package/src/pages/setting/index.page.tsx +2 -1
  41. package/src/plugins/index.ts +2 -1
  42. package/src/plugins/webCrawler/index.ts +20 -0
  43. package/src/plugins/webCrawler/runner.ts +75 -0
  44. package/src/store/session/slices/agentConfig/initialState.ts +1 -5
  45. package/src/store/session/slices/agentConfig/selectors.ts +15 -5
  46. package/src/store/session/slices/chat/selectors/chat.ts +2 -2
  47. package/src/store/session/slices/session/selectors/chat.ts +1 -1
  48. package/src/utils/genSiteHeadTitle.ts +1 -0
  49. package/src/pages/chat/[id]/Config/ReadMode.tsx +0 -64
  50. package/src/pages/chat/[id]/edit/AgentConfig/Plugin.tsx +0 -46
  51. package/src/pages/chat/[id]/edit/AgentConfig/Prompt.tsx +0 -69
@@ -7,7 +7,6 @@ import { Flexbox } from 'react-layout-kit';
7
7
  import { shallow } from 'zustand/shallow';
8
8
 
9
9
  import { chatSelectors, sessionSelectors, useSessionStore } from '@/store/session';
10
- import { DEFAULT_TITLE } from '@/store/session/slices/agentConfig';
11
10
  import { useSettings } from '@/store/settings';
12
11
 
13
12
  import { useStyles } from './style';
@@ -96,7 +95,7 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
96
95
  }
97
96
  loading={loading}
98
97
  style={{ color: theme.colorText }}
99
- title={title || t(DEFAULT_TITLE)}
98
+ title={title || t('defaultSession')}
100
99
  />
101
100
  <Popconfirm
102
101
  arrow={false}
@@ -0,0 +1,26 @@
1
+ import { type ReactNode, memo } from 'react';
2
+ import { Flexbox } from 'react-layout-kit';
3
+
4
+ interface HeaderProps {
5
+ actions?: ReactNode;
6
+ title: string;
7
+ }
8
+
9
+ const Header = memo<HeaderProps>(({ title, actions }) => {
10
+ return (
11
+ <Flexbox
12
+ align={'center'}
13
+ distribution={'space-between'}
14
+ horizontal
15
+ padding={12}
16
+ paddingInline={16}
17
+ >
18
+ <Flexbox>{title}</Flexbox>
19
+ <Flexbox gap={4} horizontal>
20
+ {actions}
21
+ </Flexbox>
22
+ </Flexbox>
23
+ );
24
+ });
25
+
26
+ export default Header;
@@ -0,0 +1,86 @@
1
+ import { ActionIcon, DraggablePanelBody, EditableMessage, SearchBar } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { ChevronRight } from 'lucide-react';
4
+ import { memo, useState } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { Flexbox } from 'react-layout-kit';
7
+ import { shallow } from 'zustand/shallow';
8
+
9
+ import { agentSelectors, useSessionStore } from '@/store/session';
10
+
11
+ import Header from './Header';
12
+
13
+ const useStyles = createStyles(({ css, token }) => ({
14
+ desc: css`
15
+ color: ${token.colorText};
16
+ `,
17
+ model: css`
18
+ color: ${token.colorTextTertiary};
19
+ `,
20
+ prompt: css`
21
+ overflow-x: hidden;
22
+ overflow-y: auto;
23
+
24
+ height: 200px;
25
+ padding: 0 16px 16px;
26
+
27
+ opacity: 0.75;
28
+ border-bottom: 1px solid ${token.colorBorder};
29
+
30
+ transition: 200ms ${token.motionEaseOut};
31
+
32
+ &:hover {
33
+ opacity: 1;
34
+ }
35
+ `,
36
+ title: css`
37
+ font-size: ${token.fontSizeHeading4}px;
38
+ font-weight: bold;
39
+ `,
40
+ }));
41
+
42
+ const SideBar = memo(() => {
43
+ const [openModal, setOpenModal] = useState(false);
44
+ const { styles } = useStyles();
45
+ const [updateAgentConfig] = useSessionStore((s) => [s.updateAgentConfig], shallow);
46
+ const systemRole = useSessionStore(agentSelectors.currentAgentSystemRole, shallow);
47
+
48
+ const { t } = useTranslation('common');
49
+ return (
50
+ <DraggablePanelBody style={{ padding: 0 }}>
51
+ <Header
52
+ actions={
53
+ <ActionIcon
54
+ icon={ChevronRight}
55
+ onClick={() => setOpenModal(true)}
56
+ size="small"
57
+ title={t('edit')}
58
+ />
59
+ }
60
+ title={t('settingAgent.prompt.title', { ns: 'setting' })}
61
+ />
62
+ <EditableMessage
63
+ classNames={{ markdown: styles.prompt }}
64
+ onChange={(e) => {
65
+ updateAgentConfig({ systemRole: e });
66
+ }}
67
+ onOpenChange={setOpenModal}
68
+ openModal={openModal}
69
+ placeholder={`${t('settingAgent.prompt.placeholder', { ns: 'setting' })}...`}
70
+ styles={{ markdown: systemRole ? {} : { opacity: 0.5 } }}
71
+ text={{
72
+ cancel: t('cancel'),
73
+ confirm: t('ok'),
74
+ edit: t('edit'),
75
+ title: t('settingAgent.prompt.title', { ns: 'setting' }),
76
+ }}
77
+ value={systemRole}
78
+ />
79
+ <Flexbox style={{ padding: 16 }}>
80
+ <SearchBar placeholder={t('archiveSearchPlaceholder')} />
81
+ </Flexbox>
82
+ </DraggablePanelBody>
83
+ );
84
+ });
85
+
86
+ export default SideBar;
@@ -1,22 +1,13 @@
1
- import {
2
- ActionIcon,
3
- DraggablePanel,
4
- DraggablePanelBody,
5
- DraggablePanelContainer,
6
- } from '@lobehub/ui';
1
+ import { DraggablePanel, DraggablePanelContainer } from '@lobehub/ui';
7
2
  import { createStyles } from 'antd-style';
8
- import { LucideEdit, LucideX } from 'lucide-react';
9
- import Router from 'next/router';
10
3
  import { rgba } from 'polished';
11
- import { useTranslation } from 'react-i18next';
12
- import { Flexbox } from 'react-layout-kit';
13
4
  import { shallow } from 'zustand/shallow';
14
5
 
15
6
  import HeaderSpacing from '@/components/HeaderSpacing';
16
7
  import { CHAT_SIDEBAR_WIDTH } from '@/const/layoutTokens';
17
8
  import { useSessionStore } from '@/store/session';
18
9
 
19
- import ReadMode from './ReadMode';
10
+ import SideBar from './SideBar';
20
11
 
21
12
  const useStyles = createStyles(({ cx, css, token, stylish }) => ({
22
13
  drawer: cx(
@@ -31,10 +22,9 @@ const useStyles = createStyles(({ cx, css, token, stylish }) => ({
31
22
  }));
32
23
 
33
24
  const Config = () => {
34
- const { t } = useTranslation('common');
35
25
  const { styles } = useStyles();
36
- const [showAgentSettings, toggleConfig, id] = useSessionStore(
37
- (s) => [s.showAgentSettings, s.toggleConfig, s.activeId],
26
+ const [showAgentSettings, toggleConfig] = useSessionStore(
27
+ (s) => [s.showAgentSettings, s.toggleConfig],
38
28
  shallow,
39
29
  );
40
30
 
@@ -50,37 +40,7 @@ const Config = () => {
50
40
  >
51
41
  <HeaderSpacing />
52
42
  <DraggablePanelContainer style={{ flex: 'none', minWidth: CHAT_SIDEBAR_WIDTH }}>
53
- <Flexbox
54
- align={'center'}
55
- className={styles.header}
56
- distribution={'space-between'}
57
- horizontal
58
- padding={12}
59
- paddingInline={16}
60
- >
61
- <Flexbox>{t('agentProfile')}</Flexbox>
62
- <Flexbox gap={4} horizontal>
63
- <ActionIcon
64
- icon={LucideEdit}
65
- onClick={() => {
66
- Router.push(`/chat/${id}/edit`);
67
- }}
68
- size={{ blockSize: 32, fontSize: 20 }}
69
- title={t('edit')}
70
- />
71
- <ActionIcon
72
- icon={LucideX}
73
- onClick={() => {
74
- toggleConfig(false);
75
- }}
76
- size={{ blockSize: 32, fontSize: 20 }}
77
- title={t('close')}
78
- />
79
- </Flexbox>
80
- </Flexbox>
81
- <DraggablePanelBody>
82
- <ReadMode />
83
- </DraggablePanelBody>
43
+ <SideBar />
84
44
  </DraggablePanelContainer>
85
45
  </DraggablePanel>
86
46
  );
@@ -16,7 +16,7 @@ const useStyles = createStyles(({ css, token }) => ({
16
16
  `,
17
17
  }));
18
18
  const FunctionMessage = memo(() => {
19
- const { t } = useTranslation();
19
+ const { t } = useTranslation('plugin');
20
20
  const { styles } = useStyles();
21
21
  return (
22
22
  <Flexbox className={styles.container} gap={8} horizontal>
@@ -1,6 +1,6 @@
1
1
  import { ActionIcon } from '@lobehub/ui';
2
2
  import { Popconfirm } from 'antd';
3
- import { Eraser, Languages } from 'lucide-react';
3
+ import { BrainCog, Eraser, Thermometer, Timer } from 'lucide-react';
4
4
  import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { shallow } from 'zustand/shallow';
@@ -8,14 +8,22 @@ import { shallow } from 'zustand/shallow';
8
8
  import { useSessionStore } from '@/store/session';
9
9
 
10
10
  const InputActions = memo(() => {
11
- const { t } = useTranslation();
11
+ const { t } = useTranslation('setting');
12
12
  const [clearMessage] = useSessionStore((s) => [s.clearMessage], shallow);
13
13
 
14
14
  return (
15
15
  <>
16
- <ActionIcon icon={Languages} />
17
- <Popconfirm onConfirm={() => clearMessage()} title={t('confirmClearCurrentMessages')}>
18
- <ActionIcon icon={Eraser} title={t('clearCurrentMessages')} />
16
+ <ActionIcon icon={BrainCog} title={t('settingModel.model.title')} />
17
+ <ActionIcon icon={Thermometer} title={t('settingModel.temperature.title')} />
18
+ <ActionIcon icon={Timer} title={t('settingChat.historyCount.title')} />
19
+ <Popconfirm
20
+ cancelText={t('cancel', { ns: 'common' })}
21
+ okButtonProps={{ danger: true }}
22
+ okText={t('ok', { ns: 'common' })}
23
+ onConfirm={() => clearMessage()}
24
+ title={t('confirmClearCurrentMessages', { ns: 'common' })}
25
+ >
26
+ <ActionIcon icon={Eraser} title={t('clearCurrentMessages', { ns: 'common' })} />
19
27
  </Popconfirm>
20
28
  </>
21
29
  );
@@ -1,4 +1,4 @@
1
- import { ChatInputArea, DraggablePanel, Icon } from '@lobehub/ui';
1
+ import { ChatInputArea, DraggablePanel, Icon, Tooltip } from '@lobehub/ui';
2
2
  import { Button } from 'antd';
3
3
  import { Archive } from 'lucide-react';
4
4
  import { memo, useMemo, useState } from 'react';
@@ -13,7 +13,7 @@ import InputActions from './Action';
13
13
  import Token from './Token';
14
14
 
15
15
  const ChatInput = () => {
16
- const { t } = useTranslation();
16
+ const { t } = useTranslation('common');
17
17
  const [expand, setExpand] = useState<boolean>(false);
18
18
  const [text, setText] = useState('');
19
19
 
@@ -21,7 +21,11 @@ const ChatInput = () => {
21
21
  const [sendMessage] = useSessionStore((s) => [s.createOrSendMsg], shallow);
22
22
 
23
23
  const footer = useMemo(
24
- () => <Button icon={<Icon icon={Archive} title={t('archiveCurrentMessages')} />} />,
24
+ () => (
25
+ <Tooltip title={t('archiveCurrentMessages')}>
26
+ <Button icon={<Icon icon={Archive} />} />
27
+ </Tooltip>
28
+ ),
25
29
  [],
26
30
  );
27
31
 
@@ -54,6 +58,10 @@ const ChatInput = () => {
54
58
  onExpandChange={setExpand}
55
59
  onInputChange={setText}
56
60
  onSend={sendMessage}
61
+ placeholder={t('sendPlaceholder')}
62
+ text={{
63
+ send: t('send'),
64
+ }}
57
65
  />
58
66
  </DraggablePanel>
59
67
  );
@@ -69,7 +69,7 @@ const MessageExtra = ({ role, extra, function_call }: ChatMessage): ReactNode =>
69
69
  if (!(hasModelTag || hasFuncTag)) return;
70
70
 
71
71
  return (
72
- <Flexbox className={styles.container}>
72
+ <Flexbox className={styles.container} horizontal>
73
73
  {hasFuncTag && funcTag}
74
74
  {hasModelTag && modelTag}
75
75
  </Flexbox>
@@ -1,61 +1,45 @@
1
1
  import { ActionIcon, Avatar, ChatHeader } from '@lobehub/ui';
2
2
  import { Tag } from 'antd';
3
- import { createStyles } from 'antd-style';
4
- import { ArchiveIcon, MoreVerticalIcon, Share2 } from 'lucide-react';
3
+ import { PanelRightClose, PanelRightOpen, Settings, Share2 } from 'lucide-react';
4
+ import Router from 'next/router';
5
5
  import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
- import { Flexbox } from 'react-layout-kit';
8
7
  import { shallow } from 'zustand/shallow';
9
8
 
10
- import { agentSelectors, sessionSelectors, useSessionStore } from '@/store/session';
11
-
12
- const useStyles = createStyles(({ css, token }) => ({
13
- desc: css`
14
- font-size: 12px;
15
- color: ${token.colorTextTertiary};
16
- `,
17
- title: css`
18
- font-weight: bold;
19
- color: ${token.colorText};
20
- `,
21
- }));
9
+ import HeaderTitle from '@/components/HeaderTitle';
10
+ import { agentSelectors, useSessionStore } from '@/store/session';
22
11
 
23
12
  const Header = memo(() => {
24
13
  const { t } = useTranslation('common');
25
- const [avatar, model] = useSessionStore(
26
- (s) => [agentSelectors.currentAgentAvatar(s), agentSelectors.currentAgentModel(s)],
14
+
15
+ const [meta, id, modle] = useSessionStore(
16
+ (s) => [agentSelectors.currentAgentMeta(s), s.activeId, agentSelectors.currentAgentModel(s)],
27
17
  shallow,
28
18
  );
29
- const [meta, id] = useSessionStore((s) => {
30
- const chat = sessionSelectors.currentSession(s);
31
- return [chat?.meta, s.activeId];
32
- }, shallow);
33
-
34
- const [
35
- // genShareUrl,
36
-
37
- toggleConfig,
38
- ] = useSessionStore(
39
- (s) => [
40
- // s.genShareUrl,
41
- s.toggleConfig,
42
- ],
19
+ const [showAgentSettings, toggleConfig] = useSessionStore(
20
+ (s) => [s.showAgentSettings, s.toggleConfig],
43
21
  shallow,
44
22
  );
45
23
 
46
- const { styles } = useStyles();
47
24
  return (
48
25
  <ChatHeader
49
26
  left={
50
27
  <>
51
- <Avatar avatar={avatar} size={40} title={meta?.title} />
52
- <Flexbox>
53
- <Flexbox align={'center'} className={styles.title} gap={8} horizontal>
54
- {meta?.title || t('defaultAgent')}
55
- <Tag bordered={false}>{model}</Tag>
56
- </Flexbox>
57
- <Flexbox className={styles.desc}>{meta?.description || t('noDescription')}</Flexbox>
58
- </Flexbox>
28
+ <Avatar
29
+ avatar={meta?.avatar}
30
+ background={meta?.backgroundColor}
31
+ onClick={() => {
32
+ Router.push(`/chat/${id}/edit`);
33
+ }}
34
+ size={40}
35
+ style={{ cursor: 'pointer' }}
36
+ title={meta?.title}
37
+ />
38
+ <HeaderTitle
39
+ desc={meta?.description || t('noDescription')}
40
+ tag={<Tag>{modle}</Tag>}
41
+ title={meta?.title || t('defaultAgent')}
42
+ />
59
43
  </>
60
44
  }
61
45
  right={
@@ -69,12 +53,19 @@ const Header = memo(() => {
69
53
  size={{ fontSize: 24 }}
70
54
  title={t('share')}
71
55
  />
72
- <ActionIcon icon={ArchiveIcon} size={{ fontSize: 24 }} title={t('archive')} />
73
56
  <ActionIcon
74
- icon={MoreVerticalIcon}
57
+ icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
75
58
  onClick={() => toggleConfig()}
76
59
  size={{ fontSize: 24 }}
77
- title={t('sessionSetting')}
60
+ title={t('roleAndArchive')}
61
+ />
62
+ <ActionIcon
63
+ icon={Settings}
64
+ onClick={() => {
65
+ Router.push(`/chat/${id}/edit`);
66
+ }}
67
+ size={{ fontSize: 24 }}
68
+ title={t('header.session', { ns: 'setting' })}
78
69
  />
79
70
  </>
80
71
  )