@lobehub/chat 0.63.0 → 0.63.2
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/CHANGELOG.md +50 -0
- package/package.json +1 -1
- package/src/features/AgentSetting/AgentConfig/index.tsx +6 -8
- package/src/features/AgentSetting/AgentMeta/index.tsx +35 -50
- package/src/features/AgentSetting/AgentPlugin/index.tsx +9 -15
- package/src/features/AgentSetting/AgentPrompt/index.tsx +10 -11
- package/src/features/AgentSetting/StoreUpdater.tsx +22 -0
- package/src/features/AgentSetting/index.tsx +25 -0
- package/src/features/AgentSetting/store/action.ts +212 -0
- package/src/features/AgentSetting/store/index.ts +12 -0
- package/src/features/AgentSetting/store/initialState.ts +28 -0
- package/src/features/AgentSetting/store/reducers/config.ts +43 -0
- package/src/features/AgentSetting/store/reducers/meta.ts +21 -0
- package/src/helpers/export.ts +2 -1
- package/src/pages/chat/SessionList/List/Item/Actions.tsx +2 -1
- package/src/pages/chat/SessionList/List/Item/index.tsx +3 -2
- package/src/pages/chat/SessionList/List/index.tsx +2 -1
- package/src/pages/chat/[id]/index.page.tsx +2 -1
- package/src/pages/chat/[id]/setting/index.page.tsx +10 -16
- package/src/pages/chat/features/Conversation/ChatList/MessageExtra.tsx +2 -1
- package/src/pages/chat/features/Conversation/ChatList/index.tsx +2 -6
- package/src/pages/chat/features/Conversation/Input/Action.tsx +2 -1
- package/src/pages/chat/features/Conversation/Input/Token.tsx +2 -1
- package/src/pages/chat/features/Header/Mobile.tsx +2 -1
- package/src/pages/chat/features/Header/PC.tsx +2 -1
- package/src/pages/chat/features/Sidebar/SystemRole.tsx +2 -1
- package/src/pages/chat/features/Sidebar/Topic/index.tsx +2 -1
- package/src/pages/index.page.tsx +2 -1
- package/src/pages/settings/Settings/Agent.tsx +13 -12
- package/src/store/global/slices/agent.ts +6 -57
- package/src/store/session/index.ts +0 -1
- package/src/store/session/initialState.ts +1 -3
- package/src/store/session/slices/agentConfig/action.ts +0 -193
- package/src/store/session/slices/agentConfig/initialState.ts +0 -18
- package/src/store/session/slices/agentConfig/selectors.ts +0 -9
- package/src/store/session/slices/chat/actions/message.ts +6 -6
- package/src/types/session.ts +8 -1
- package/src/features/AgentSetting/index.ts +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.63.2](https://github.com/lobehub/lobe-chat/compare/v0.63.1...v0.63.2)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-08-27**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor AgentSettings.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor AgentSettings, closes [#121](https://github.com/lobehub/lobe-chat/issues/121) ([1f29199](https://github.com/lobehub/lobe-chat/commit/1f29199))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.63.1](https://github.com/lobehub/lobe-chat/compare/v0.63.0...v0.63.1)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-08-27**</sup>
|
|
33
|
+
|
|
34
|
+
#### ♻ Code Refactoring
|
|
35
|
+
|
|
36
|
+
- **misc**: Refactor the selectors import.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### Code refactoring
|
|
44
|
+
|
|
45
|
+
- **misc**: Refactor the selectors import, closes [#120](https://github.com/lobehub/lobe-chat/issues/120) ([6646502](https://github.com/lobehub/lobe-chat/commit/6646502))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
## [Version 0.63.0](https://github.com/lobehub/lobe-chat/compare/v0.62.1...v0.63.0)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2023-08-27**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Form, ItemGroup, SliderWithInput } from '@lobehub/ui';
|
|
2
2
|
import { ConfigProvider, Input, Select, Switch } from 'antd';
|
|
3
3
|
import { useTheme, useThemeMode } from 'antd-style';
|
|
4
|
+
import isEqual from 'fast-deep-equal';
|
|
4
5
|
import { debounce } from 'lodash-es';
|
|
5
6
|
import { BrainCog, LayoutList, MessageSquare, MessagesSquare } from 'lucide-react';
|
|
6
7
|
import { memo, useMemo } from 'react';
|
|
@@ -8,24 +9,21 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
9
|
|
|
9
10
|
import SelectWithImg from '@/components/SelectWithImg';
|
|
10
11
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
11
|
-
import { AgentAction } from '@/store/session/slices/agentConfig';
|
|
12
12
|
import { LanguageModel } from '@/types/llm';
|
|
13
|
-
import type { LobeAgentConfig } from '@/types/session';
|
|
14
13
|
import { LobeAgentConfigKeys } from '@/types/session';
|
|
15
14
|
|
|
15
|
+
import { useStore } from '../store';
|
|
16
|
+
|
|
16
17
|
type SettingItemGroup = ItemGroup & {
|
|
17
18
|
children: {
|
|
18
19
|
name?: LobeAgentConfigKeys | string | string[];
|
|
19
20
|
}[];
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
config: LobeAgentConfig;
|
|
24
|
-
updateConfig: AgentAction['updateAgentConfig'];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const AgentConfig = memo<AgentConfigProps>(({ config, updateConfig }) => {
|
|
23
|
+
const AgentConfig = memo(() => {
|
|
28
24
|
const { t } = useTranslation('setting');
|
|
25
|
+
const updateConfig = useStore((s) => s.setAgentConfig);
|
|
26
|
+
const config = useStore((s) => s.config, isEqual);
|
|
29
27
|
const theme = useTheme();
|
|
30
28
|
const { isDarkMode } = useThemeMode();
|
|
31
29
|
|
|
@@ -1,38 +1,28 @@
|
|
|
1
1
|
import { Form, type FormItemProps, Icon, type ItemGroup, Tooltip } from '@lobehub/ui';
|
|
2
2
|
import { Button } from 'antd';
|
|
3
|
+
import isEqual from 'fast-deep-equal';
|
|
3
4
|
import { UserCircle, Wand2 } from 'lucide-react';
|
|
4
|
-
import {
|
|
5
|
+
import { memo, useMemo } from 'react';
|
|
5
6
|
import { useTranslation } from 'react-i18next';
|
|
6
7
|
|
|
7
8
|
import EmojiPicker from '@/components/EmojiPicker';
|
|
8
9
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
9
|
-
import { AgentAction, SessionLoadingState } from '@/store/session/slices/agentConfig';
|
|
10
|
-
import { MetaData } from '@/types/meta';
|
|
11
|
-
import { LobeAgentConfig } from '@/types/session';
|
|
12
10
|
|
|
11
|
+
import { useStore } from '../store';
|
|
12
|
+
import { SessionLoadingState } from '../store/initialState';
|
|
13
13
|
import AutoGenerateInput from './AutoGenerateInput';
|
|
14
14
|
import BackgroundSwatches from './BackgroundSwatches';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
autocompleteMeta: AgentAction['autocompleteMeta'];
|
|
18
|
-
autocompleteSessionAgentMeta: AgentAction['autocompleteSessionAgentMeta'];
|
|
19
|
-
id: string | null;
|
|
20
|
-
loading: SessionLoadingState;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface AgentMetaProps {
|
|
24
|
-
autocomplete?: Autocomplete;
|
|
25
|
-
config: LobeAgentConfig;
|
|
26
|
-
meta: MetaData;
|
|
27
|
-
updateMeta: AgentAction['updateAgentMeta'];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const AgentMeta = memo<AgentMetaProps>(({ config, meta, updateMeta, autocomplete }) => {
|
|
16
|
+
const AgentMeta = memo(() => {
|
|
31
17
|
const { t } = useTranslation('setting');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
const [hasSystemRole, updateMeta, autocompleteMeta, autocompleteAllMeta] = useStore((s) => [
|
|
19
|
+
!!s.config.systemRole,
|
|
20
|
+
s.setAgentMeta,
|
|
21
|
+
s.autocompleteMeta,
|
|
22
|
+
s.autocompleteAllMeta,
|
|
23
|
+
]);
|
|
24
|
+
const loading = useStore((s) => s.autocompleteLoading);
|
|
25
|
+
const meta = useStore((s) => s.meta, isEqual);
|
|
36
26
|
|
|
37
27
|
const basic = [
|
|
38
28
|
{
|
|
@@ -49,15 +39,16 @@ const AgentMeta = memo<AgentMetaProps>(({ config, meta, updateMeta, autocomplete
|
|
|
49
39
|
];
|
|
50
40
|
|
|
51
41
|
const autocompleteItems: FormItemProps[] = basic.map((item) => {
|
|
52
|
-
const handleGenerate = () => autocomplete?.autocompleteMeta(item.key as keyof typeof meta);
|
|
53
42
|
return {
|
|
54
43
|
children: (
|
|
55
44
|
<AutoGenerateInput
|
|
56
|
-
loading={
|
|
45
|
+
loading={loading[item.key as keyof SessionLoadingState]}
|
|
57
46
|
onChange={(e) => {
|
|
58
47
|
updateMeta({ [item.key]: e.target.value });
|
|
59
48
|
}}
|
|
60
|
-
onGenerate={
|
|
49
|
+
onGenerate={() => {
|
|
50
|
+
autocompleteMeta(item.key as keyof typeof meta);
|
|
51
|
+
}}
|
|
61
52
|
placeholder={item.placeholder}
|
|
62
53
|
value={meta[item.key as keyof typeof meta]}
|
|
63
54
|
/>
|
|
@@ -66,28 +57,6 @@ const AgentMeta = memo<AgentMetaProps>(({ config, meta, updateMeta, autocomplete
|
|
|
66
57
|
};
|
|
67
58
|
});
|
|
68
59
|
|
|
69
|
-
if (autocomplete) {
|
|
70
|
-
const { autocompleteSessionAgentMeta, loading, id } = autocomplete;
|
|
71
|
-
|
|
72
|
-
extra = (
|
|
73
|
-
<Tooltip title={t('autoGenerateTooltip', { ns: 'common' })}>
|
|
74
|
-
<Button
|
|
75
|
-
disabled={!hasSystemRole}
|
|
76
|
-
icon={<Icon icon={Wand2} />}
|
|
77
|
-
loading={Object.values(loading).some((i) => !!i)}
|
|
78
|
-
onClick={(e: any) => {
|
|
79
|
-
e.stopPropagation();
|
|
80
|
-
if (!id) return;
|
|
81
|
-
autocompleteSessionAgentMeta(id, true);
|
|
82
|
-
}}
|
|
83
|
-
size={'small'}
|
|
84
|
-
>
|
|
85
|
-
{t('autoGenerate', { ns: 'common' })}
|
|
86
|
-
</Button>
|
|
87
|
-
</Tooltip>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
60
|
const metaData: ItemGroup = useMemo(
|
|
92
61
|
() => ({
|
|
93
62
|
children: [
|
|
@@ -115,11 +84,27 @@ const AgentMeta = memo<AgentMetaProps>(({ config, meta, updateMeta, autocomplete
|
|
|
115
84
|
},
|
|
116
85
|
...autocompleteItems,
|
|
117
86
|
],
|
|
118
|
-
extra:
|
|
87
|
+
extra: (
|
|
88
|
+
<Tooltip title={t('autoGenerateTooltip', { ns: 'common' })}>
|
|
89
|
+
<Button
|
|
90
|
+
disabled={!hasSystemRole}
|
|
91
|
+
icon={<Icon icon={Wand2} />}
|
|
92
|
+
loading={Object.values(loading).some((i) => !!i)}
|
|
93
|
+
onClick={(e: any) => {
|
|
94
|
+
e.stopPropagation();
|
|
95
|
+
|
|
96
|
+
autocompleteAllMeta(true);
|
|
97
|
+
}}
|
|
98
|
+
size={'small'}
|
|
99
|
+
>
|
|
100
|
+
{t('autoGenerate', { ns: 'common' })}
|
|
101
|
+
</Button>
|
|
102
|
+
</Tooltip>
|
|
103
|
+
),
|
|
119
104
|
icon: UserCircle,
|
|
120
105
|
title: t('settingAgent.title'),
|
|
121
106
|
}),
|
|
122
|
-
[autocompleteItems,
|
|
107
|
+
[autocompleteItems, meta],
|
|
123
108
|
);
|
|
124
109
|
|
|
125
110
|
return <Form items={[metaData]} {...FORM_STYLE} />;
|
|
@@ -10,9 +10,8 @@ import { FORM_STYLE } from '@/const/layoutTokens';
|
|
|
10
10
|
import { transformPluginSettings } from '@/features/PluginSettings';
|
|
11
11
|
import PluginSettingRender from '@/features/PluginSettings/PluginSettingRender';
|
|
12
12
|
import { pluginHelpers, usePluginStore } from '@/store/plugin';
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
import { LobeAgentConfig } from '@/types/session';
|
|
13
|
+
|
|
14
|
+
import { useStore } from '../store';
|
|
16
15
|
|
|
17
16
|
const useStyles = createStyles(({ css, token }) => ({
|
|
18
17
|
avatar: css`
|
|
@@ -36,14 +35,13 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
36
35
|
`,
|
|
37
36
|
}));
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
config: LobeAgentConfig;
|
|
41
|
-
updateConfig: AgentAction['toggleAgentPlugin'];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const AgentPlugin = memo<AgentPluginProps>(({ config, updateConfig }) => {
|
|
38
|
+
const AgentPlugin = memo(() => {
|
|
45
39
|
const { t } = useTranslation('setting');
|
|
46
40
|
const { styles } = useStyles();
|
|
41
|
+
|
|
42
|
+
const updateConfig = useStore((s) => s.toggleAgentPlugin);
|
|
43
|
+
const [plugins, hasPlugin] = useStore((s) => [s.config.plugins || [], !!s.config.plugins]);
|
|
44
|
+
|
|
47
45
|
const [useFetchPluginList, fetchPluginManifest, updatePluginSettings] = usePluginStore((s) => [
|
|
48
46
|
s.useFetchPluginList,
|
|
49
47
|
s.fetchPluginManifest,
|
|
@@ -54,8 +52,6 @@ const AgentPlugin = memo<AgentPluginProps>(({ config, updateConfig }) => {
|
|
|
54
52
|
const pluginsSettings = usePluginStore((s) => s.pluginsSettings, isEqual);
|
|
55
53
|
const { data } = useFetchPluginList();
|
|
56
54
|
|
|
57
|
-
const plugins = useSessionStore(agentSelectors.currentAgentPlugins);
|
|
58
|
-
|
|
59
55
|
const loadingItem = {
|
|
60
56
|
avatar: (
|
|
61
57
|
<Skeleton
|
|
@@ -85,13 +81,11 @@ const AgentPlugin = memo<AgentPluginProps>(({ config, updateConfig }) => {
|
|
|
85
81
|
<Switch
|
|
86
82
|
checked={
|
|
87
83
|
// 如果在加载中,说明激活了
|
|
88
|
-
pluginManifestLoading[identifier] || !
|
|
89
|
-
? false
|
|
90
|
-
: config.plugins.includes(identifier)
|
|
84
|
+
pluginManifestLoading[identifier] || !hasPlugin ? false : plugins.includes(identifier)
|
|
91
85
|
}
|
|
92
86
|
loading={pluginManifestLoading[identifier]}
|
|
93
87
|
onChange={(checked) => {
|
|
94
|
-
updateConfig(identifier
|
|
88
|
+
updateConfig(identifier);
|
|
95
89
|
if (checked) {
|
|
96
90
|
fetchPluginManifest(identifier);
|
|
97
91
|
}
|
|
@@ -3,14 +3,14 @@ import { Button } from 'antd';
|
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
4
|
import { encode } from 'gpt-tokenizer';
|
|
5
5
|
import { Bot } from 'lucide-react';
|
|
6
|
-
import { memo,
|
|
6
|
+
import { memo, useState } from 'react';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import { Flexbox } from 'react-layout-kit';
|
|
9
9
|
|
|
10
10
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
11
11
|
import { ModelTokens } from '@/const/modelTokens';
|
|
12
|
-
|
|
13
|
-
import {
|
|
12
|
+
|
|
13
|
+
import { useStore } from '../store';
|
|
14
14
|
|
|
15
15
|
export const useStyles = createStyles(({ css, token }) => ({
|
|
16
16
|
markdown: css`
|
|
@@ -21,17 +21,16 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|
|
21
21
|
`,
|
|
22
22
|
}));
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
config: LobeAgentConfig;
|
|
26
|
-
updateConfig: AgentAction['updateAgentConfig'];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const AgentPrompt = memo<AgentPromptProps>(({ config, updateConfig }) => {
|
|
24
|
+
const AgentPrompt = memo(() => {
|
|
30
25
|
const { t } = useTranslation('setting');
|
|
31
26
|
const { styles } = useStyles();
|
|
32
27
|
const [editing, setEditing] = useState(false);
|
|
33
|
-
const
|
|
34
|
-
const systemTokenCount =
|
|
28
|
+
const updateConfig = useStore((s) => s.setAgentConfig);
|
|
29
|
+
const [systemRole, model, systemTokenCount] = useStore((s) => [
|
|
30
|
+
s.config.systemRole,
|
|
31
|
+
s.config.model,
|
|
32
|
+
encode(s.config.systemRole || '').length,
|
|
33
|
+
]);
|
|
35
34
|
|
|
36
35
|
return (
|
|
37
36
|
<FormGroup
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { memo } from 'react';
|
|
2
|
+
import { createStoreUpdater } from 'zustand-utils';
|
|
3
|
+
|
|
4
|
+
import { State, useStoreApi } from './store';
|
|
5
|
+
|
|
6
|
+
export type StoreUpdaterProps = Partial<
|
|
7
|
+
Pick<State, 'onMetaChange' | 'onConfigChange' | 'meta' | 'config'>
|
|
8
|
+
>;
|
|
9
|
+
|
|
10
|
+
const StoreUpdater = memo<StoreUpdaterProps>(({ onConfigChange, onMetaChange, meta, config }) => {
|
|
11
|
+
const storeApi = useStoreApi();
|
|
12
|
+
const useStoreUpdater = createStoreUpdater(storeApi);
|
|
13
|
+
|
|
14
|
+
useStoreUpdater('meta', meta);
|
|
15
|
+
useStoreUpdater('config', config);
|
|
16
|
+
useStoreUpdater('onConfigChange', onConfigChange);
|
|
17
|
+
useStoreUpdater('onMetaChange', onMetaChange);
|
|
18
|
+
|
|
19
|
+
return null;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export default StoreUpdater;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { memo } from 'react';
|
|
2
|
+
|
|
3
|
+
import AgentConfig from './AgentConfig';
|
|
4
|
+
import AgentMeta from './AgentMeta';
|
|
5
|
+
import AgentPlugin from './AgentPlugin';
|
|
6
|
+
import AgentPrompt from './AgentPrompt';
|
|
7
|
+
import StoreUpdater, { StoreUpdaterProps } from './StoreUpdater';
|
|
8
|
+
import { Provider, createStore } from './store';
|
|
9
|
+
|
|
10
|
+
type AgentSettingsProps = StoreUpdaterProps;
|
|
11
|
+
|
|
12
|
+
const AgentSettings = memo<AgentSettingsProps>((props) => {
|
|
13
|
+
return (
|
|
14
|
+
<Provider createStore={createStore}>
|
|
15
|
+
<StoreUpdater {...props} />
|
|
16
|
+
|
|
17
|
+
<AgentPrompt />
|
|
18
|
+
<AgentMeta />
|
|
19
|
+
<AgentConfig />
|
|
20
|
+
<AgentPlugin />
|
|
21
|
+
</Provider>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default AgentSettings;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { StateCreator } from 'zustand/vanilla';
|
|
2
|
+
|
|
3
|
+
import { promptPickEmoji, promptSummaryAgentName, promptSummaryDescription } from '@/prompts/agent';
|
|
4
|
+
import { MetaData } from '@/types/meta';
|
|
5
|
+
import { LobeAgentConfig } from '@/types/session';
|
|
6
|
+
import { fetchPresetTaskResult } from '@/utils/fetch';
|
|
7
|
+
import { setNamespace } from '@/utils/storeDebug';
|
|
8
|
+
|
|
9
|
+
import { SessionLoadingState } from '../store/initialState';
|
|
10
|
+
import { State, initialState } from './initialState';
|
|
11
|
+
import { ConfigDispatch, configReducer } from './reducers/config';
|
|
12
|
+
import { MetaDataDispatch, metaDataReducer } from './reducers/meta';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 设置操作
|
|
16
|
+
*/
|
|
17
|
+
export interface Action {
|
|
18
|
+
/**
|
|
19
|
+
* 自动选择表情
|
|
20
|
+
* @param id - 表情的 ID
|
|
21
|
+
*/
|
|
22
|
+
autoPickEmoji: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* 自动完成代理描述
|
|
25
|
+
* @param id - 代理的 ID
|
|
26
|
+
* @returns 一个 Promise,用于异步操作完成后的处理
|
|
27
|
+
*/
|
|
28
|
+
autocompleteAgentDescription: () => Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* 自动完成代理标题
|
|
31
|
+
* @param id - 代理的 ID
|
|
32
|
+
* @returns 一个 Promise,用于异步操作完成后的处理
|
|
33
|
+
*/
|
|
34
|
+
autocompleteAgentTitle: () => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* 自动完成助理元数据
|
|
37
|
+
*/
|
|
38
|
+
autocompleteAllMeta: (replace?: boolean) => void;
|
|
39
|
+
autocompleteMeta: (key: keyof MetaData) => void;
|
|
40
|
+
dispatchConfig: (payload: ConfigDispatch) => void;
|
|
41
|
+
dispatchMeta: (payload: MetaDataDispatch) => void;
|
|
42
|
+
|
|
43
|
+
resetAgentConfig: () => void;
|
|
44
|
+
|
|
45
|
+
resetAgentMeta: () => void;
|
|
46
|
+
|
|
47
|
+
setAgentConfig: (config: Partial<LobeAgentConfig>) => void;
|
|
48
|
+
|
|
49
|
+
setAgentMeta: (meta: Partial<MetaData>) => void;
|
|
50
|
+
streamUpdateMeta: (key: keyof MetaData) => any;
|
|
51
|
+
toggleAgentPlugin: (pluginId: string) => void;
|
|
52
|
+
/**
|
|
53
|
+
* 更新加载状态
|
|
54
|
+
* @param key - SessionLoadingState 的键
|
|
55
|
+
* @param value - 加载状态的值
|
|
56
|
+
*/
|
|
57
|
+
updateLoadingState: (key: keyof SessionLoadingState, value: boolean) => void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type Store = Action & State;
|
|
61
|
+
|
|
62
|
+
const t = setNamespace('AgentSettings');
|
|
63
|
+
|
|
64
|
+
export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, get) => ({
|
|
65
|
+
...initialState,
|
|
66
|
+
|
|
67
|
+
autoPickEmoji: async () => {
|
|
68
|
+
const { config, dispatchMeta } = get();
|
|
69
|
+
|
|
70
|
+
const systemRole = config.systemRole;
|
|
71
|
+
|
|
72
|
+
const emoji = await fetchPresetTaskResult({
|
|
73
|
+
onLoadingChange: (loading) => {
|
|
74
|
+
get().updateLoadingState('avatar', loading);
|
|
75
|
+
},
|
|
76
|
+
params: promptPickEmoji(systemRole),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (emoji) {
|
|
80
|
+
dispatchMeta({ type: 'update', value: { avatar: emoji } });
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
autocompleteAgentDescription: async () => {
|
|
84
|
+
const { dispatchMeta, config, meta, updateLoadingState, streamUpdateMeta } = get();
|
|
85
|
+
|
|
86
|
+
const systemRole = config.systemRole;
|
|
87
|
+
|
|
88
|
+
if (!systemRole) return;
|
|
89
|
+
|
|
90
|
+
const preValue = meta.description;
|
|
91
|
+
|
|
92
|
+
// 替换为 ...
|
|
93
|
+
dispatchMeta({ type: 'update', value: { description: '...' } });
|
|
94
|
+
|
|
95
|
+
fetchPresetTaskResult({
|
|
96
|
+
onError: () => {
|
|
97
|
+
dispatchMeta({ type: 'update', value: { description: preValue } });
|
|
98
|
+
},
|
|
99
|
+
onLoadingChange: (loading) => {
|
|
100
|
+
updateLoadingState('description', loading);
|
|
101
|
+
},
|
|
102
|
+
onMessageHandle: streamUpdateMeta('description'),
|
|
103
|
+
params: promptSummaryDescription(systemRole),
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
autocompleteAgentTitle: async () => {
|
|
107
|
+
const { dispatchMeta, config, meta, updateLoadingState, streamUpdateMeta } = get();
|
|
108
|
+
|
|
109
|
+
const systemRole = config.systemRole;
|
|
110
|
+
|
|
111
|
+
if (!systemRole) return;
|
|
112
|
+
|
|
113
|
+
const previousTitle = meta.title;
|
|
114
|
+
|
|
115
|
+
// 替换为 ...
|
|
116
|
+
dispatchMeta({ type: 'update', value: { title: '...' } });
|
|
117
|
+
|
|
118
|
+
fetchPresetTaskResult({
|
|
119
|
+
onError: () => {
|
|
120
|
+
dispatchMeta({ type: 'update', value: { title: previousTitle } });
|
|
121
|
+
},
|
|
122
|
+
onLoadingChange: (loading) => {
|
|
123
|
+
updateLoadingState('title', loading);
|
|
124
|
+
},
|
|
125
|
+
onMessageHandle: streamUpdateMeta('title'),
|
|
126
|
+
params: promptSummaryAgentName(systemRole),
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
autocompleteAllMeta: (replace) => {
|
|
130
|
+
const { meta } = get();
|
|
131
|
+
|
|
132
|
+
if (!meta.title || replace) {
|
|
133
|
+
get().autocompleteAgentTitle();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!meta.description || replace) {
|
|
137
|
+
get().autocompleteAgentDescription();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!meta.avatar || replace) {
|
|
141
|
+
get().autoPickEmoji();
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
autocompleteMeta: (key) => {
|
|
145
|
+
const { autoPickEmoji, autocompleteAgentTitle, autocompleteAgentDescription } = get();
|
|
146
|
+
|
|
147
|
+
switch (key) {
|
|
148
|
+
case 'avatar': {
|
|
149
|
+
autoPickEmoji();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
case 'description': {
|
|
154
|
+
autocompleteAgentDescription();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case 'title': {
|
|
159
|
+
autocompleteAgentTitle();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
dispatchConfig: (payload) => {
|
|
165
|
+
const nextConfig = configReducer(get().config, payload);
|
|
166
|
+
|
|
167
|
+
set({ config: nextConfig }, false, payload);
|
|
168
|
+
|
|
169
|
+
get().onConfigChange?.(nextConfig);
|
|
170
|
+
},
|
|
171
|
+
dispatchMeta: (payload) => {
|
|
172
|
+
const nextValue = metaDataReducer(get().meta, payload);
|
|
173
|
+
|
|
174
|
+
set({ meta: nextValue }, false, payload);
|
|
175
|
+
|
|
176
|
+
get().onMetaChange?.(nextValue);
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
resetAgentConfig: () => {
|
|
180
|
+
get().dispatchConfig({ type: 'reset' });
|
|
181
|
+
},
|
|
182
|
+
resetAgentMeta: () => {
|
|
183
|
+
get().dispatchMeta({ type: 'reset' });
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
setAgentConfig: (config) => {
|
|
187
|
+
get().dispatchConfig({ config, type: 'update' });
|
|
188
|
+
},
|
|
189
|
+
setAgentMeta: (meta) => {
|
|
190
|
+
get().dispatchMeta({ type: 'update', value: meta });
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
streamUpdateMeta: (key: keyof MetaData) => {
|
|
194
|
+
let value = '';
|
|
195
|
+
return (text: string) => {
|
|
196
|
+
value += text;
|
|
197
|
+
get().dispatchMeta({ type: 'update', value: { [key]: value } });
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
toggleAgentPlugin: (id) => {
|
|
202
|
+
get().dispatchConfig({ pluginId: id, type: 'togglePlugin' });
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
updateLoadingState: (key, value) => {
|
|
206
|
+
set(
|
|
207
|
+
{ autocompleteLoading: { ...get().autocompleteLoading, [key]: value } },
|
|
208
|
+
false,
|
|
209
|
+
t('updateLoadingState', { key, value }),
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StoreApi } from 'zustand';
|
|
2
|
+
import { createContext } from 'zustand-utils';
|
|
3
|
+
import { shallow } from 'zustand/shallow';
|
|
4
|
+
import { createWithEqualityFn } from 'zustand/traditional';
|
|
5
|
+
|
|
6
|
+
import { Store, store } from './action';
|
|
7
|
+
|
|
8
|
+
export type { State } from './initialState';
|
|
9
|
+
|
|
10
|
+
export const createStore = () => createWithEqualityFn(store, shallow);
|
|
11
|
+
|
|
12
|
+
export const { useStore, useStoreApi, Provider } = createContext<StoreApi<Store>>();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DEFAULT_AGENT_META } from '@/const/meta';
|
|
2
|
+
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
3
|
+
import { MetaData } from '@/types/meta';
|
|
4
|
+
import { LobeAgentConfig } from '@/types/session';
|
|
5
|
+
|
|
6
|
+
export interface State {
|
|
7
|
+
autocompleteLoading: SessionLoadingState;
|
|
8
|
+
config: LobeAgentConfig;
|
|
9
|
+
meta: MetaData;
|
|
10
|
+
|
|
11
|
+
onConfigChange?: (config: LobeAgentConfig) => void;
|
|
12
|
+
onMetaChange?: (meta: MetaData) => void;
|
|
13
|
+
}
|
|
14
|
+
export type SessionLoadingState = Record<Partial<keyof MetaData>, boolean>;
|
|
15
|
+
|
|
16
|
+
export const initialState: State = {
|
|
17
|
+
// loading 中间态
|
|
18
|
+
autocompleteLoading: {
|
|
19
|
+
avatar: false,
|
|
20
|
+
backgroundColor: false,
|
|
21
|
+
description: false,
|
|
22
|
+
tag: false,
|
|
23
|
+
title: false,
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
config: DEFAULT_AGENT_CONFIG,
|
|
27
|
+
meta: DEFAULT_AGENT_META,
|
|
28
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
import { merge } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
5
|
+
import { LobeAgentConfig } from '@/types/session';
|
|
6
|
+
|
|
7
|
+
export type ConfigDispatch =
|
|
8
|
+
| { config: Partial<any>; type: 'update' }
|
|
9
|
+
| { pluginId: string; type: 'togglePlugin' }
|
|
10
|
+
| { type: 'reset' };
|
|
11
|
+
|
|
12
|
+
export const configReducer = (state: LobeAgentConfig, payload: ConfigDispatch): LobeAgentConfig => {
|
|
13
|
+
switch (payload.type) {
|
|
14
|
+
case 'update': {
|
|
15
|
+
return produce(state, (draftState) => {
|
|
16
|
+
return merge({}, draftState, payload.config);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
case 'togglePlugin': {
|
|
21
|
+
return produce(state, (config) => {
|
|
22
|
+
const { pluginId: id } = payload;
|
|
23
|
+
if (config.plugins === undefined) {
|
|
24
|
+
config.plugins = [id];
|
|
25
|
+
} else {
|
|
26
|
+
if (config.plugins.includes(id)) {
|
|
27
|
+
config.plugins.splice(config.plugins.indexOf(id), 1);
|
|
28
|
+
} else {
|
|
29
|
+
config.plugins.push(id);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
case 'reset': {
|
|
36
|
+
return DEFAULT_AGENT_CONFIG;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
default: {
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|