@lobehub/chat 0.14.0 → 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 (46) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/locales/en_US/common.json +19 -27
  3. package/locales/en_US/plugin.json +10 -0
  4. package/locales/en_US/setting.json +42 -6
  5. package/locales/zh_CN/common.json +8 -17
  6. package/locales/zh_CN/plugin.json +10 -0
  7. package/locales/zh_CN/setting.json +36 -0
  8. package/package.json +1 -1
  9. package/src/components/HeaderSpacing/index.tsx +3 -1
  10. package/src/components/HeaderTitle/index.tsx +42 -0
  11. package/src/const/layoutTokens.ts +6 -1
  12. package/src/const/meta.ts +3 -0
  13. package/src/locales/default/common.ts +31 -51
  14. package/src/locales/default/plugin.ts +10 -0
  15. package/src/locales/default/setting.ts +46 -1
  16. package/src/locales/resources/en_US.ts +2 -0
  17. package/src/locales/resources/zh_CN.ts +2 -0
  18. package/src/pages/chat/SessionList/List/SessionItem.tsx +1 -2
  19. package/src/pages/chat/[id]/Config/Header.tsx +26 -0
  20. package/src/pages/chat/[id]/Config/SideBar.tsx +86 -0
  21. package/src/pages/chat/[id]/Config/index.tsx +5 -45
  22. package/src/pages/chat/[id]/Conversation/FunctionMessage.tsx +1 -1
  23. package/src/pages/chat/[id]/Conversation/Input/Action.tsx +13 -5
  24. package/src/pages/chat/[id]/Conversation/Input/index.tsx +11 -3
  25. package/src/pages/chat/[id]/Header.tsx +34 -43
  26. package/src/pages/chat/[id]/edit/AgentConfig/index.tsx +154 -95
  27. package/src/pages/chat/[id]/edit/AgentMeta/AutoGenerateInput.tsx +39 -0
  28. package/src/pages/chat/[id]/edit/AgentMeta/BackgroundSwatches.tsx +31 -0
  29. package/src/pages/chat/[id]/edit/AgentMeta/EmojiPicker.tsx +7 -3
  30. package/src/pages/chat/[id]/edit/AgentMeta/index.tsx +68 -75
  31. package/src/pages/chat/[id]/edit/AgentPlugin/index.tsx +44 -0
  32. package/src/pages/chat/[id]/edit/AgentPrompt/index.tsx +48 -0
  33. package/src/pages/chat/[id]/edit/Header.tsx +31 -0
  34. package/src/pages/chat/[id]/edit/index.page.tsx +12 -40
  35. package/src/pages/chat/[id]/index.page.tsx +2 -1
  36. package/src/pages/setting/Header.tsx +4 -11
  37. package/src/pages/setting/SettingForm.tsx +9 -9
  38. package/src/pages/setting/index.page.tsx +2 -1
  39. package/src/store/session/slices/agentConfig/initialState.ts +1 -5
  40. package/src/store/session/slices/agentConfig/selectors.ts +15 -5
  41. package/src/store/session/slices/chat/selectors/chat.ts +2 -2
  42. package/src/store/session/slices/session/selectors/chat.ts +1 -1
  43. package/src/utils/genSiteHeadTitle.ts +1 -0
  44. package/src/pages/chat/[id]/Config/ReadMode.tsx +0 -64
  45. package/src/pages/chat/[id]/edit/AgentConfig/Plugin.tsx +0 -46
  46. package/src/pages/chat/[id]/edit/AgentConfig/Prompt.tsx +0 -69
@@ -0,0 +1,31 @@
1
+ import { Swatches, primaryColorsSwatches } from '@lobehub/ui';
2
+ import { memo } from 'react';
3
+ import { shallow } from 'zustand/shallow';
4
+
5
+ import { DEFAULT_BACKGROUND_COLOR } from '@/const/meta';
6
+ import { agentSelectors, useSessionStore } from '@/store/session';
7
+
8
+ const BackgroundSwatches = memo(() => {
9
+ const [backgroundColor, updateAgentMeta] = useSessionStore(
10
+ (s) => [agentSelectors.currentAgentBackgroundColor(s), s.updateAgentMeta],
11
+ shallow,
12
+ );
13
+
14
+ const handleSelect = (v: any) => {
15
+ if (v) {
16
+ updateAgentMeta({ backgroundColor: v });
17
+ } else {
18
+ updateAgentMeta({ backgroundColor: DEFAULT_BACKGROUND_COLOR });
19
+ }
20
+ };
21
+
22
+ return (
23
+ <Swatches
24
+ activeColor={backgroundColor}
25
+ colors={primaryColorsSwatches}
26
+ onSelect={handleSelect}
27
+ />
28
+ );
29
+ });
30
+
31
+ export default BackgroundSwatches;
@@ -39,8 +39,12 @@ const useStyles = createStyles(({ css, token, prefixCls }) => ({
39
39
 
40
40
  const EmojiPicker = () => {
41
41
  const { styles } = useStyles();
42
- const [avatar, updateAgentMeta] = useSessionStore(
43
- (s) => [agentSelectors.currentAgentAvatar(s), s.updateAgentMeta],
42
+ const [avatar, backgroundColor, updateAgentMeta] = useSessionStore(
43
+ (s) => [
44
+ agentSelectors.currentAgentAvatar(s),
45
+ agentSelectors.currentAgentBackgroundColor(s),
46
+ s.updateAgentMeta,
47
+ ],
44
48
  shallow,
45
49
  );
46
50
 
@@ -65,7 +69,7 @@ const EmojiPicker = () => {
65
69
  trigger={'click'}
66
70
  >
67
71
  <div className={styles.avatar} style={{ width: 'fit-content' }}>
68
- <Avatar avatar={avatar} size={200} />
72
+ <Avatar avatar={avatar} background={backgroundColor} size={44} />
69
73
  </div>
70
74
  </Popover>
71
75
  );
@@ -1,21 +1,20 @@
1
- import { ActionIcon, Input, Tooltip } from '@lobehub/ui';
2
- import { Button, Collapse } from 'antd';
1
+ import { Form, Icon, type ItemGroup, Tooltip } from '@lobehub/ui';
2
+ import { Button } from 'antd';
3
3
  import isEqual from 'fast-deep-equal';
4
- import { LucideSparkles } from 'lucide-react';
4
+ import { UserCircle, Wand2 } from 'lucide-react';
5
+ import { memo, useMemo } from 'react';
5
6
  import { useTranslation } from 'react-i18next';
6
- import { Flexbox } from 'react-layout-kit';
7
7
  import { shallow } from 'zustand/shallow';
8
8
 
9
+ import { FORM_STYLE } from '@/const/layoutTokens';
9
10
  import { agentSelectors, useSessionStore } from '@/store/session';
10
11
 
11
- import { FormItem } from '../FormItem';
12
- import { useStyles } from '../style';
12
+ import AutoGenerateInput from './AutoGenerateInput';
13
+ import BackgroundSwatches from './BackgroundSwatches';
13
14
  import EmojiPicker from './EmojiPicker';
14
15
 
15
- const AgentMeta = () => {
16
- const { t } = useTranslation('common');
17
-
18
- const { styles, theme } = useStyles();
16
+ const AgentMeta = memo(() => {
17
+ const { t } = useTranslation('setting');
19
18
 
20
19
  const metaData = useSessionStore(agentSelectors.currentAgentMeta, isEqual);
21
20
 
@@ -39,80 +38,74 @@ const AgentMeta = () => {
39
38
  );
40
39
 
41
40
  const basic = [
42
- { key: 'title', label: t('agentName'), placeholder: t('agentNamePlaceholder') },
41
+ {
42
+ key: 'title',
43
+ label: t('settingAgent.name.title'),
44
+ placeholder: t('settingAgent.name.placeholder'),
45
+ },
43
46
  {
44
47
  key: 'description',
45
- label: t('agentDescription'),
46
- placeholder: t('agentDescriptionPlaceholder'),
48
+ label: t('settingAgent.description.title'),
49
+ placeholder: t('settingAgent.description.placeholder'),
47
50
  },
48
51
  // { key: 'tag', label: t('agentTag'), placeholder: t('agentTagPlaceholder') },
49
52
  ];
50
53
 
51
- return (
52
- <Collapse
53
- defaultActiveKey={hasSystemRole ? ['meta'] : []}
54
- items={[
54
+ const meta: ItemGroup = useMemo(
55
+ () => ({
56
+ children: [
57
+ {
58
+ children: <EmojiPicker />,
59
+ label: t('settingAgent.avatar.title'),
60
+ minWidth: undefined,
61
+ },
55
62
  {
63
+ children: <BackgroundSwatches />,
64
+ label: t('settingAgent.backgroundColor.title'),
65
+ minWidth: undefined,
66
+ },
67
+ ...basic.map((item) => ({
56
68
  children: (
57
- <Flexbox gap={80} horizontal style={{ marginTop: 16 }}>
58
- <Flexbox flex={1} gap={24}>
59
- {basic.map((item) => (
60
- <FormItem key={item.key} label={item.label}>
61
- <Input
62
- onChange={(e) => {
63
- updateAgentMeta({ [item.key]: e.target.value });
64
- }}
65
- placeholder={item.placeholder}
66
- suffix={
67
- <ActionIcon
68
- icon={LucideSparkles}
69
- loading={loading[item.key as keyof typeof loading]}
70
- onClick={() => {
71
- autocompleteMeta(item.key as keyof typeof metaData);
72
- }}
73
- size={'small'}
74
- style={{
75
- color: theme.purple,
76
- }}
77
- title={t('autoGenerate')}
78
- />
79
- }
80
- type={'block'}
81
- value={metaData[item.key as keyof typeof metaData]}
82
- />
83
- </FormItem>
84
- ))}
85
- </Flexbox>
86
- <FormItem label={t('agentAvatar')}>
87
- <EmojiPicker />
88
- </FormItem>
89
- </Flexbox>
90
- ),
91
- className: styles.collapseHeader,
92
- extra: (
93
- <Tooltip title={t('autoGenerateTooltip')}>
94
- <Button
95
- disabled={!hasSystemRole}
96
- loading={Object.values(loading).some((i) => !!i)}
97
- onClick={(e: any) => {
98
- e.stopPropagation();
99
- console.log(id);
100
- if (!id) return;
101
-
102
- autocompleteSessionAgentMeta(id, true);
103
- }}
104
- size={'large'}
105
- >
106
- {t('autoGenerate')}
107
- </Button>
108
- </Tooltip>
69
+ <AutoGenerateInput
70
+ loading={loading[item.key as keyof typeof loading]}
71
+ onChange={(e) => {
72
+ updateAgentMeta({ [item.key]: e.target.value });
73
+ }}
74
+ onGenerate={() => {
75
+ autocompleteMeta(item.key as keyof typeof metaData);
76
+ }}
77
+ placeholder={item.placeholder}
78
+ value={metaData[item.key as keyof typeof metaData]}
79
+ />
109
80
  ),
110
- key: 'meta',
111
- label: <Flexbox className={styles.profile}>{t('profile')}</Flexbox>,
112
- },
113
- ]}
114
- />
81
+ label: item.label,
82
+ })),
83
+ ],
84
+ extra: (
85
+ <Tooltip title={t('autoGenerateTooltip', { ns: 'common' })}>
86
+ <Button
87
+ disabled={!hasSystemRole}
88
+ icon={<Icon icon={Wand2} />}
89
+ loading={Object.values(loading).some((i) => !!i)}
90
+ onClick={(e: any) => {
91
+ e.stopPropagation();
92
+ console.log(id);
93
+ if (!id) return;
94
+ autocompleteSessionAgentMeta(id, true);
95
+ }}
96
+ size={'small'}
97
+ >
98
+ {t('autoGenerate', { ns: 'common' })}
99
+ </Button>
100
+ </Tooltip>
101
+ ),
102
+ icon: UserCircle,
103
+ title: t('settingAgent.title'),
104
+ }),
105
+ [basic, metaData],
115
106
  );
116
- };
107
+
108
+ return <Form items={[meta]} {...FORM_STYLE} />;
109
+ });
117
110
 
118
111
  export default AgentMeta;
@@ -0,0 +1,44 @@
1
+ import { Avatar, Form, ItemGroup } from '@lobehub/ui';
2
+ import { Switch } from 'antd';
3
+ import isEqual from 'fast-deep-equal';
4
+ import { ToyBrick } from 'lucide-react';
5
+ import { useMemo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { shallow } from 'zustand/shallow';
8
+
9
+ import { FORM_STYLE } from '@/const/layoutTokens';
10
+ import pluginList from '@/plugins';
11
+ import { agentSelectors, useSessionStore } from '@/store/session';
12
+
13
+ const PluginList = () => {
14
+ const { t } = useTranslation('setting');
15
+
16
+ const config = useSessionStore(agentSelectors.currentAgentConfigSafe, isEqual);
17
+
18
+ const toggleAgentPlugin = useSessionStore((s) => s.toggleAgentPlugin, shallow);
19
+
20
+ const plugin: ItemGroup = useMemo(
21
+ () => ({
22
+ children: pluginList.map((item) => ({
23
+ avatar: <Avatar avatar={item.avatar} />,
24
+ children: (
25
+ <Switch
26
+ checked={!config.plugins ? false : config.plugins.includes(item.name)}
27
+ onChange={() => toggleAgentPlugin(item.name)}
28
+ />
29
+ ),
30
+ desc: item.schema.description,
31
+ label: t(`plugins.${item.name}` as any, { ns: 'plugin' }),
32
+ minWidth: undefined,
33
+ tag: item.name,
34
+ })),
35
+ icon: ToyBrick,
36
+ title: t('settingPlugin.title'),
37
+ }),
38
+ [config],
39
+ );
40
+
41
+ return <Form items={[plugin]} {...FORM_STYLE} />;
42
+ };
43
+
44
+ export default PluginList;
@@ -0,0 +1,48 @@
1
+ import { CodeEditor, FormGroup } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { Bot } from 'lucide-react';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { shallow } from 'zustand/shallow';
7
+
8
+ import { FORM_STYLE } from '@/const/layoutTokens';
9
+ import { agentSelectors, useSessionStore } from '@/store/session';
10
+
11
+ export const useStyles = createStyles(({ css, token }) => ({
12
+ input: css`
13
+ padding: 12px;
14
+ background: ${token.colorFillTertiary};
15
+ border: 1px solid ${token.colorPrimaryBorder};
16
+ border-radius: 8px;
17
+ `,
18
+ markdown: css`
19
+ padding: 12px;
20
+ background: ${token.colorFillTertiary};
21
+ `,
22
+ }));
23
+
24
+ const AgentPrompt = memo(() => {
25
+ const { t } = useTranslation('setting');
26
+
27
+ const systemRole = useSessionStore(agentSelectors.currentAgentSystemRole, shallow);
28
+
29
+ const [updateAgentConfig] = useSessionStore((s) => [s.updateAgentConfig], shallow);
30
+
31
+ return (
32
+ <FormGroup icon={Bot} style={FORM_STYLE.style} title={t('settingAgent.prompt.title')}>
33
+ <CodeEditor
34
+ language={'md'}
35
+ onValueChange={(e) => {
36
+ updateAgentConfig({ systemRole: e });
37
+ }}
38
+ placeholder={t('settingAgent.name.placeholder')}
39
+ resize={false}
40
+ style={{ marginBottom: 16, marginTop: 16 }}
41
+ type={'pure'}
42
+ value={systemRole}
43
+ />
44
+ </FormGroup>
45
+ );
46
+ });
47
+
48
+ export default AgentPrompt;
@@ -0,0 +1,31 @@
1
+ import { ActionIcon, ChatHeader } from '@lobehub/ui';
2
+ import { Download, Share2 } from 'lucide-react';
3
+ import Router from 'next/router';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import HeaderTitle from '@/components/HeaderTitle';
8
+
9
+ const Header = memo(() => {
10
+ const { t } = useTranslation('setting');
11
+
12
+ return (
13
+ <ChatHeader
14
+ left={<HeaderTitle title={t('header.session')} />}
15
+ onBackClick={() => Router.back()}
16
+ right={
17
+ <>
18
+ <ActionIcon icon={Share2} size={{ fontSize: 24 }} title={t('share', { ns: 'common' })} />
19
+ <ActionIcon
20
+ icon={Download}
21
+ size={{ fontSize: 24 }}
22
+ title={t('export', { ns: 'common' })}
23
+ />
24
+ </>
25
+ }
26
+ showBackButton
27
+ />
28
+ );
29
+ });
30
+
31
+ export default Header;
@@ -1,43 +1,23 @@
1
- import { ActionIcon, ChatHeader } from '@lobehub/ui';
2
- import { createStyles } from 'antd-style';
3
- import { Download, Share2 } from 'lucide-react';
4
1
  import Head from 'next/head';
5
- import Router from 'next/router';
6
2
  import { memo } from 'react';
7
3
  import { useTranslation } from 'react-i18next';
8
4
  import { Flexbox } from 'react-layout-kit';
9
5
 
10
6
  import HeaderSpacing from '@/components/HeaderSpacing';
7
+ import { HEADER_HEIGHT } from '@/const/layoutTokens';
8
+ import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
11
9
 
12
10
  import ChatLayout from '../../layout';
13
11
  import AgentConfig from './AgentConfig';
14
12
  import AgentMeta from './AgentMeta';
15
-
16
- const useStyles = createStyles(({ css, token }) => ({
17
- footer: css`
18
- position: sticky;
19
- bottom: 0;
20
- border-top: 1px solid ${token.colorBorder};
21
- `,
22
- form: css`
23
- overflow-y: auto;
24
- `,
25
- header: css`
26
- background: ${token.colorBgContainer};
27
- border-bottom: 1px solid ${token.colorSplit};
28
- `,
29
- title: css`
30
- font-size: 16px;
31
- font-weight: 500;
32
- `,
33
- }));
13
+ import AgentPlugin from './AgentPlugin';
14
+ import AgentPrompt from './AgentPrompt';
15
+ import Header from './Header';
34
16
 
35
17
  const EditPage = memo(() => {
36
- const { t } = useTranslation('common');
37
-
38
- const { styles } = useStyles();
18
+ const { t } = useTranslation('setting');
39
19
 
40
- const pageTitle = t('editAgentProfile');
20
+ const pageTitle = genSiteHeadTitle(t('header.session'));
41
21
 
42
22
  return (
43
23
  <>
@@ -45,21 +25,13 @@ const EditPage = memo(() => {
45
25
  <title>{pageTitle}</title>
46
26
  </Head>
47
27
  <ChatLayout>
48
- <ChatHeader
49
- left={<div className={styles.title}>{t('editAgentProfile')}</div>}
50
- onBackClick={() => Router.back()}
51
- right={
52
- <>
53
- <ActionIcon icon={Share2} size={{ fontSize: 24 }} title={t('share')} />
54
- <ActionIcon icon={Download} size={{ fontSize: 24 }} title={t('export')} />
55
- </>
56
- }
57
- showBackButton
58
- />
59
- <Flexbox className={styles.form} flex={1} gap={10} padding={24}>
60
- <HeaderSpacing />
28
+ <Header />
29
+ <Flexbox align={'center'} flex={1} gap={16} padding={24} style={{ overflow: 'auto' }}>
30
+ <HeaderSpacing height={HEADER_HEIGHT - 16} />
31
+ <AgentPrompt />
61
32
  <AgentMeta />
62
33
  <AgentConfig />
34
+ <AgentPlugin />
63
35
  </Flexbox>
64
36
  </ChatLayout>
65
37
  </>
@@ -4,6 +4,7 @@ import { memo } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
6
  import { sessionSelectors, useSessionStore } from '@/store/session';
7
+ import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
7
8
 
8
9
  import Layout from '../layout';
9
10
  import Config from './Config';
@@ -16,7 +17,7 @@ const Chat = memo(() => {
16
17
  return [context?.meta.title];
17
18
  }, isEqual);
18
19
 
19
- const pageTitle = title ? `${title} - LobeChat` : 'LobeChat';
20
+ const pageTitle = genSiteHeadTitle(title);
20
21
 
21
22
  return (
22
23
  <>
@@ -1,23 +1,16 @@
1
1
  import { ChatHeader } from '@lobehub/ui';
2
- import { createStyles } from 'antd-style';
3
- import { useTranslation } from 'react-i18next';
4
2
  import Router from 'next/router';
5
3
  import { memo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import HeaderTitle from '@/components/HeaderTitle';
6
7
 
7
- const useStyles = createStyles(({ css, token }) => ({
8
- title: css`
9
- font-size: 16px;
10
- font-weight: bold;
11
- color: ${token.colorText};
12
- `,
13
- }));
14
8
  const Header = memo(() => {
15
9
  const { t } = useTranslation('setting');
16
10
 
17
- const { styles } = useStyles();
18
11
  return (
19
12
  <ChatHeader
20
- left={<div className={styles.title}>{t('header')}</div>}
13
+ left={<HeaderTitle title={t('header.global')} />}
21
14
  onBackClick={() => Router.back()}
22
15
  showBackButton
23
16
  />
@@ -2,11 +2,12 @@ import { Form, type ItemGroup, ThemeSwitch } from '@lobehub/ui';
2
2
  import { Form as AntForm, Button, Input, Popconfirm, Select, Switch } from 'antd';
3
3
  import isEqual from 'fast-deep-equal';
4
4
  import { debounce } from 'lodash-es';
5
- import { AppWindow, Bot, MessagesSquare, Palette, Webhook } from 'lucide-react';
5
+ import { AppWindow, BrainCog, MessagesSquare, Palette, Webhook } from 'lucide-react';
6
6
  import { memo, useCallback, useMemo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { shallow } from 'zustand/shallow';
9
9
 
10
+ import { FORM_STYLE } from '@/const/layoutTokens';
10
11
  import AvatarWithUpload from '@/features/AvatarWithUpload';
11
12
  import SliderWithInput from '@/features/SliderWithInput';
12
13
  import { options } from '@/locales/options';
@@ -99,7 +100,7 @@ const SettingForm = memo(() => {
99
100
  [settings],
100
101
  );
101
102
 
102
- const OpenAI: SettingItemGroup = useMemo(
103
+ const openAI: SettingItemGroup = useMemo(
103
104
  () => ({
104
105
  children: [
105
106
  {
@@ -123,7 +124,7 @@ const SettingForm = memo(() => {
123
124
  [settings],
124
125
  );
125
126
 
126
- const Chat: SettingItemGroup = useMemo(
127
+ const chat: SettingItemGroup = useMemo(
127
128
  () => ({
128
129
  children: [
129
130
  {
@@ -161,7 +162,7 @@ const SettingForm = memo(() => {
161
162
  [settings],
162
163
  );
163
164
 
164
- const Model: SettingItemGroup = useMemo(
165
+ const model: SettingItemGroup = useMemo(
165
166
  () => ({
166
167
  children: [
167
168
  {
@@ -222,13 +223,13 @@ const SettingForm = memo(() => {
222
223
  tag: 'max_tokens',
223
224
  },
224
225
  ],
225
- icon: Bot,
226
+ icon: BrainCog,
226
227
  title: t('settingModel.title'),
227
228
  }),
228
229
  [settings],
229
230
  );
230
231
 
231
- const System: SettingItemGroup = useMemo(
232
+ const system: SettingItemGroup = useMemo(
232
233
  () => ({
233
234
  children: [
234
235
  {
@@ -282,16 +283,15 @@ const SettingForm = memo(() => {
282
283
  [settings],
283
284
  );
284
285
 
285
- const items = useMemo(() => [theme, OpenAI, Chat, Model, System], [settings]);
286
+ const items = useMemo(() => [theme, openAI, chat, model, system], [settings]);
286
287
 
287
288
  return (
288
289
  <Form
289
290
  form={form}
290
291
  initialValues={settings}
291
- itemMinWidth="max(30%,240px)"
292
292
  items={items}
293
293
  onValuesChange={debounce(setSettings, 100)}
294
- style={{ maxWidth: 1024, width: '100%' }}
294
+ {...FORM_STYLE}
295
295
  />
296
296
  );
297
297
  });
@@ -6,6 +6,7 @@ import { Flexbox } from 'react-layout-kit';
6
6
  import HeaderSpacing from '@/components/HeaderSpacing';
7
7
  import { createI18nNext } from '@/locales/create';
8
8
  import ChatLayout from '@/pages/chat/layout';
9
+ import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
9
10
 
10
11
  import Header from './Header';
11
12
  import SettingForm from './SettingForm';
@@ -14,7 +15,7 @@ const initI18n = createI18nNext('setting');
14
15
 
15
16
  const SettingLayout = memo(() => {
16
17
  const { t } = useTranslation('setting');
17
- const pageTitle = `${t('header')} - LobeChat`;
18
+ const pageTitle = genSiteHeadTitle(t('header.global'));
18
19
 
19
20
  useEffect(() => {
20
21
  initI18n.finally();
@@ -16,10 +16,6 @@ export const initialLobeAgentConfig: LobeAgentConfig = {
16
16
  systemRole: '',
17
17
  };
18
18
 
19
- export const DEFAULT_AVATAR = 'https://npm.elemecdn.com/@lobehub/assets-logo/assets/logo-3d.webp';
20
-
21
- export const DEFAULT_TITLE = 'DefaultSession';
22
-
23
19
  export const initialAgentConfigState: AgentConfigState = {
24
20
  // // loading 中间态
25
21
  autocompleteLoading: {
@@ -30,5 +26,5 @@ export const initialAgentConfigState: AgentConfigState = {
30
26
  title: false,
31
27
  },
32
28
 
33
- showAgentSettings: false,
29
+ showAgentSettings: true,
34
30
  };
@@ -1,30 +1,34 @@
1
+ import { DEFAULT_AVATAR, DEFAULT_BACKGROUND_COLOR } from '@/const/meta';
1
2
  import { SessionStore } from '@/store/session';
2
3
  import { LanguageModel } from '@/types/llm';
3
4
  import { MetaData } from '@/types/meta';
4
5
  import { LobeAgentConfig } from '@/types/session';
5
6
 
6
7
  import { sessionSelectors } from '../session';
7
- import { DEFAULT_AVATAR, initialLobeAgentConfig } from './initialState';
8
+ import { initialLobeAgentConfig } from './initialState';
8
9
 
9
10
  const currentAgentMeta = (s: SessionStore): MetaData => {
10
11
  const session = sessionSelectors.currentSession(s);
11
12
 
12
- return session?.meta || {};
13
+ return { avatar: DEFAULT_AVATAR, backgroundColor: DEFAULT_BACKGROUND_COLOR, ...session?.meta };
13
14
  };
14
15
 
15
16
  const currentAgentTitle = (s: SessionStore) => currentAgentMeta(s)?.title;
16
17
 
17
- const currentAgentAvatar = (s: SessionStore) => {
18
+ const currentAgentBackgroundColor = (s: SessionStore) => {
18
19
  const session = sessionSelectors.currentSession(s);
20
+ if (!session) return DEFAULT_BACKGROUND_COLOR;
21
+ return session.meta.backgroundColor || DEFAULT_BACKGROUND_COLOR;
22
+ };
19
23
 
24
+ const currentAgentAvatar = (s: SessionStore) => {
25
+ const session = sessionSelectors.currentSession(s);
20
26
  if (!session) return DEFAULT_AVATAR;
21
-
22
27
  return session.meta.avatar || DEFAULT_AVATAR;
23
28
  };
24
29
 
25
30
  const currentAgentConfig = (s: SessionStore) => {
26
31
  const session = sessionSelectors.currentSession(s);
27
-
28
32
  return session?.config;
29
33
  };
30
34
 
@@ -32,6 +36,10 @@ const currentAgentConfigSafe = (s: SessionStore): LobeAgentConfig => {
32
36
  return currentAgentConfig(s) || initialLobeAgentConfig;
33
37
  };
34
38
 
39
+ const currentAgentSystemRole = (s: SessionStore) => {
40
+ return currentAgentConfigSafe(s).systemRole;
41
+ };
42
+
35
43
  const currentAgentModel = (s: SessionStore): LanguageModel => {
36
44
  const config = currentAgentConfig(s);
37
45
 
@@ -45,10 +53,12 @@ const hasSystemRole = (s: SessionStore) => {
45
53
  };
46
54
  export const agentSelectors = {
47
55
  currentAgentAvatar,
56
+ currentAgentBackgroundColor,
48
57
  currentAgentConfig,
49
58
  currentAgentConfigSafe,
50
59
  currentAgentMeta,
51
60
  currentAgentModel,
61
+ currentAgentSystemRole,
52
62
  currentAgentTitle,
53
63
  hasSystemRole,
54
64
  };
@@ -1,9 +1,9 @@
1
+ import { DEFAULT_USER_AVATAR } from '@/const/meta';
1
2
  import { agentSelectors } from '@/store/session';
2
3
  import { useSettings } from '@/store/settings';
3
4
  import { ChatMessage } from '@/types/chatMessage';
4
5
 
5
6
  import type { SessionStore } from '../../../store';
6
- import { DEFAULT_AVATAR } from '../../agentConfig';
7
7
  import { sessionSelectors } from '../../session';
8
8
  import { organizeChats } from './utils';
9
9
 
@@ -14,7 +14,7 @@ export const currentChats = (s: SessionStore): ChatMessage[] => {
14
14
 
15
15
  return organizeChats(session, {
16
16
  assistant: agentSelectors.currentAgentAvatar(s),
17
- user: useSettings.getState().settings.avatar || DEFAULT_AVATAR,
17
+ user: useSettings.getState().settings.avatar || DEFAULT_USER_AVATAR,
18
18
  });
19
19
  };
20
20