@lobehub/chat 0.63.1 → 0.63.3
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/const/url.ts +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/pages/chat/SessionList/List/Item/index.tsx +1 -1
- package/src/pages/chat/[id]/setting/index.page.tsx +8 -15
- package/src/pages/settings/Settings/Agent.tsx +13 -12
- package/src/store/global/slices/agent.ts +6 -57
- 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.3](https://github.com/lobehub/lobe-chat/compare/v0.63.2...v0.63.3)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-08-28**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor with new market url.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor with new market url, closes [#123](https://github.com/lobehub/lobe-chat/issues/123) ([34a88f8](https://github.com/lobehub/lobe-chat/commit/34a88f8))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.63.2](https://github.com/lobehub/lobe-chat/compare/v0.63.1...v0.63.2)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-08-27**</sup>
|
|
33
|
+
|
|
34
|
+
#### ♻ Code Refactoring
|
|
35
|
+
|
|
36
|
+
- **misc**: Refactor AgentSettings.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### Code refactoring
|
|
44
|
+
|
|
45
|
+
- **misc**: Refactor AgentSettings, closes [#121](https://github.com/lobehub/lobe-chat/issues/121) ([1f29199](https://github.com/lobehub/lobe-chat/commit/1f29199))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 0.63.1](https://github.com/lobehub/lobe-chat/compare/v0.63.0...v0.63.1)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2023-08-27**</sup>
|
package/package.json
CHANGED
package/src/const/url.ts
CHANGED
|
@@ -7,4 +7,4 @@ export const FEEDBACK = pkg.bugs.url;
|
|
|
7
7
|
export const DISCORD = 'https://discord.gg/AYFPHvv2jT';
|
|
8
8
|
|
|
9
9
|
export const PLUGINS_INDEX_URL =
|
|
10
|
-
process.env.PLUGINS_INDEX_URL ?? 'https://chat-plugins
|
|
10
|
+
process.env.PLUGINS_INDEX_URL ?? 'https://chat-plugins.lobehub.com';
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
import { merge } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_AGENT_META } from '@/const/meta';
|
|
5
|
+
import { MetaData } from '@/types/meta';
|
|
6
|
+
|
|
7
|
+
export type MetaDataDispatch = { type: 'update'; value: Partial<MetaData> } | { type: 'reset' };
|
|
8
|
+
|
|
9
|
+
export const metaDataReducer = (state: MetaData, payload: MetaDataDispatch): MetaData => {
|
|
10
|
+
switch (payload.type) {
|
|
11
|
+
case 'update': {
|
|
12
|
+
return produce(state, (draftState) => {
|
|
13
|
+
return merge({}, draftState, payload.value);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
case 'reset': {
|
|
18
|
+
return DEFAULT_AGENT_META;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -56,7 +56,7 @@ const SessionItem = memo<SessionItemProps>(({ id }) => {
|
|
|
56
56
|
|
|
57
57
|
return [
|
|
58
58
|
s.activeId === id,
|
|
59
|
-
s.
|
|
59
|
+
!!s.chatLoadingId && id === s.activeId,
|
|
60
60
|
session.pinned,
|
|
61
61
|
agentSelectors.getTitle(meta),
|
|
62
62
|
agentSelectors.getDescription(meta),
|
|
@@ -7,7 +7,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
7
7
|
|
|
8
8
|
import SafeSpacing from '@/components/SafeSpacing';
|
|
9
9
|
import { HEADER_HEIGHT } from '@/const/layoutTokens';
|
|
10
|
-
import
|
|
10
|
+
import AgentSetting from '@/features/AgentSetting';
|
|
11
11
|
import { useSessionStore } from '@/store/session';
|
|
12
12
|
import { agentSelectors } from '@/store/session/selectors';
|
|
13
13
|
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
@@ -21,10 +21,8 @@ const EditPage = memo(() => {
|
|
|
21
21
|
const { t } = useTranslation('setting');
|
|
22
22
|
const config = useSessionStore(agentSelectors.currentAgentConfig, isEqual);
|
|
23
23
|
const meta = useSessionStore(agentSelectors.currentAgentMeta, isEqual);
|
|
24
|
-
const
|
|
25
|
-
const [updateAgentConfig, toggleAgentPlugin, updateAgentMeta, title] = useSessionStore((s) => [
|
|
24
|
+
const [updateAgentConfig, updateAgentMeta, title] = useSessionStore((s) => [
|
|
26
25
|
s.updateAgentConfig,
|
|
27
|
-
s.toggleAgentPlugin,
|
|
28
26
|
s.updateAgentMeta,
|
|
29
27
|
agentSelectors.currentAgentTitle(s),
|
|
30
28
|
]);
|
|
@@ -32,17 +30,12 @@ const EditPage = memo(() => {
|
|
|
32
30
|
const pageTitle = genSiteHeadTitle(t('header.sessionWithName', { name: title }));
|
|
33
31
|
|
|
34
32
|
const settings = (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
updateMeta={updateAgentMeta}
|
|
42
|
-
/>
|
|
43
|
-
<AgentConfig config={config} updateConfig={updateAgentConfig} />
|
|
44
|
-
<AgentPlugin config={config} updateConfig={toggleAgentPlugin} />
|
|
45
|
-
</>
|
|
33
|
+
<AgentSetting
|
|
34
|
+
config={config}
|
|
35
|
+
meta={meta}
|
|
36
|
+
onConfigChange={updateAgentConfig}
|
|
37
|
+
onMetaChange={updateAgentMeta}
|
|
38
|
+
/>
|
|
46
39
|
);
|
|
47
40
|
|
|
48
41
|
return (
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import isEqual from 'fast-deep-equal';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import AgentSetting from '@/features/AgentSetting';
|
|
5
5
|
import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
6
6
|
|
|
7
7
|
const Agent = memo(() => {
|
|
8
8
|
const config = useGlobalStore(settingsSelectors.currentAgentConfig, isEqual);
|
|
9
9
|
const meta = useGlobalStore(settingsSelectors.currentAgentMeta, isEqual);
|
|
10
|
-
const [
|
|
11
|
-
|
|
12
|
-
s.setAgentMeta,
|
|
13
|
-
s.toggleAgentPlugin,
|
|
14
|
-
]);
|
|
10
|
+
const [updateAgent] = useGlobalStore((s) => [s.updateDefaultAgent]);
|
|
11
|
+
|
|
15
12
|
return (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
<AgentSetting
|
|
14
|
+
config={config}
|
|
15
|
+
meta={meta}
|
|
16
|
+
onConfigChange={(config) => {
|
|
17
|
+
updateAgent({ config });
|
|
18
|
+
}}
|
|
19
|
+
onMetaChange={(meta) => {
|
|
20
|
+
updateAgent({ meta });
|
|
21
|
+
}}
|
|
22
|
+
/>
|
|
22
23
|
);
|
|
23
24
|
});
|
|
24
25
|
|
|
@@ -2,10 +2,7 @@ import { produce } from 'immer';
|
|
|
2
2
|
import { merge } from 'lodash-es';
|
|
3
3
|
import type { StateCreator } from 'zustand/vanilla';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { MetaData } from '@/types/meta';
|
|
7
|
-
import type { LobeAgentSession } from '@/types/session';
|
|
8
|
-
import { LobeAgentConfig } from '@/types/session';
|
|
5
|
+
import { LobeAgentSettings } from '@/types/session';
|
|
9
6
|
import type { GlobalSettings } from '@/types/settings';
|
|
10
7
|
import { setNamespace } from '@/utils/storeDebug';
|
|
11
8
|
|
|
@@ -17,12 +14,7 @@ const t = setNamespace('settings');
|
|
|
17
14
|
* 设置操作
|
|
18
15
|
*/
|
|
19
16
|
export interface AgentAction {
|
|
20
|
-
|
|
21
|
-
resetAgentMeta: () => void;
|
|
22
|
-
resetDefaultAgent: () => void;
|
|
23
|
-
setAgentConfig: (config: Partial<LobeAgentSession['config']>) => void;
|
|
24
|
-
setAgentMeta: (meta: Partial<LobeAgentSession['meta']>) => void;
|
|
25
|
-
toggleAgentPlugin: (pluginId: string) => void;
|
|
17
|
+
updateDefaultAgent: (agent: Partial<LobeAgentSettings>) => void;
|
|
26
18
|
}
|
|
27
19
|
|
|
28
20
|
export const createAgentSlice: StateCreator<
|
|
@@ -31,55 +23,12 @@ export const createAgentSlice: StateCreator<
|
|
|
31
23
|
[],
|
|
32
24
|
AgentAction
|
|
33
25
|
> = (set, get) => ({
|
|
34
|
-
|
|
26
|
+
updateDefaultAgent: (agent) => {
|
|
35
27
|
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
36
|
-
draft.defaultAgent
|
|
37
|
-
|
|
38
|
-
set({ settings }, false, t('resetAgentConfig'));
|
|
39
|
-
},
|
|
40
|
-
resetAgentMeta: () => {
|
|
41
|
-
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
42
|
-
draft.defaultAgent.meta = DEFAULT_AGENT.meta;
|
|
43
|
-
});
|
|
44
|
-
set({ settings }, false, t('resetAgentMeta'));
|
|
45
|
-
},
|
|
46
|
-
resetDefaultAgent: () => {
|
|
47
|
-
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
48
|
-
draft.defaultAgent = DEFAULT_AGENT;
|
|
49
|
-
});
|
|
50
|
-
set({ settings }, false, t('resetDefaultAgent'));
|
|
51
|
-
},
|
|
52
|
-
setAgentConfig: (config) => {
|
|
53
|
-
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
54
|
-
const oldConfig = draft.defaultAgent.config as LobeAgentConfig;
|
|
55
|
-
draft.defaultAgent.config = merge({}, oldConfig, config);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
set({ settings }, false, t('setAgentConfig', config));
|
|
59
|
-
},
|
|
60
|
-
setAgentMeta: (meta) => {
|
|
61
|
-
const settings = produce(get().settings, (draft) => {
|
|
62
|
-
const oldMeta = draft.defaultAgent.meta as MetaData;
|
|
63
|
-
draft.defaultAgent.meta = merge({}, oldMeta, meta);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
set({ settings }, false, t('setAgentMeta', meta));
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
toggleAgentPlugin: (id: string) => {
|
|
70
|
-
const settings = produce(get().settings, (draft: GlobalSettings) => {
|
|
71
|
-
const oldConfig = draft.defaultAgent.config as LobeAgentConfig;
|
|
72
|
-
if (oldConfig.plugins === undefined) {
|
|
73
|
-
oldConfig.plugins = [id];
|
|
74
|
-
} else {
|
|
75
|
-
if (oldConfig.plugins.includes(id)) {
|
|
76
|
-
oldConfig.plugins.splice(oldConfig.plugins.indexOf(id), 1);
|
|
77
|
-
} else {
|
|
78
|
-
oldConfig.plugins.push(id);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
28
|
+
const oldAgent = draft.defaultAgent as LobeAgentSettings;
|
|
29
|
+
draft.defaultAgent = merge({}, oldAgent, agent);
|
|
81
30
|
});
|
|
82
31
|
|
|
83
|
-
set({ settings }, false, t('
|
|
32
|
+
set({ settings }, false, t('updateDefaultAgent', agent));
|
|
84
33
|
},
|
|
85
34
|
});
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { AgentConfigState, initialAgentConfigState } from './slices/agentConfig/initialState';
|
|
2
1
|
import { ChatState, initialChatState } from './slices/chat/initialState';
|
|
3
2
|
import { SessionState, initialSessionState } from './slices/session/initialState';
|
|
4
3
|
|
|
5
|
-
export type SessionStoreState = SessionState & ChatState
|
|
4
|
+
export type SessionStoreState = SessionState & ChatState;
|
|
6
5
|
|
|
7
6
|
export const initialState: SessionStoreState = {
|
|
8
7
|
...initialSessionState,
|
|
9
8
|
...initialChatState,
|
|
10
|
-
...initialAgentConfigState,
|
|
11
9
|
};
|
|
12
10
|
|
|
13
11
|
export { initialLobeAgentConfig } from './slices/agentConfig';
|
|
@@ -1,66 +1,21 @@
|
|
|
1
|
-
import { produce } from 'immer';
|
|
2
1
|
import { StateCreator } from 'zustand/vanilla';
|
|
3
2
|
|
|
4
|
-
import { promptPickEmoji, promptSummaryAgentName, promptSummaryDescription } from '@/prompts/agent';
|
|
5
3
|
import { MetaData } from '@/types/meta';
|
|
6
4
|
import { LobeAgentConfig } from '@/types/session';
|
|
7
|
-
import { fetchPresetTaskResult } from '@/utils/fetch';
|
|
8
|
-
import { setNamespace } from '@/utils/storeDebug';
|
|
9
5
|
|
|
10
6
|
import { SessionStore } from '../../store';
|
|
11
7
|
import { sessionSelectors } from '../session/selectors';
|
|
12
|
-
import { SessionLoadingState } from './initialState';
|
|
13
|
-
|
|
14
|
-
const t = setNamespace('agentConfig');
|
|
15
8
|
|
|
16
9
|
/**
|
|
17
10
|
* 代理行为接口
|
|
18
11
|
*/
|
|
19
12
|
export interface AgentAction {
|
|
20
|
-
/**
|
|
21
|
-
* 自动选择表情
|
|
22
|
-
* @param id - 表情的 ID
|
|
23
|
-
*/
|
|
24
|
-
autoPickEmoji: (id: string) => void;
|
|
25
|
-
/**
|
|
26
|
-
* 自动完成代理描述
|
|
27
|
-
* @param id - 代理的 ID
|
|
28
|
-
* @returns 一个 Promise,用于异步操作完成后的处理
|
|
29
|
-
*/
|
|
30
|
-
autocompleteAgentDescription: (id: string) => Promise<void>;
|
|
31
|
-
/**
|
|
32
|
-
* 自动完成代理标题
|
|
33
|
-
* @param id - 代理的 ID
|
|
34
|
-
* @returns 一个 Promise,用于异步操作完成后的处理
|
|
35
|
-
*/
|
|
36
|
-
autocompleteAgentTitle: (id: string) => Promise<void>;
|
|
37
|
-
autocompleteMeta: (key: keyof MetaData) => void;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* 自动完成会话代理元数据
|
|
41
|
-
* @param id - 代理的 ID
|
|
42
|
-
*/
|
|
43
|
-
autocompleteSessionAgentMeta: (id: string, replace?: boolean) => void;
|
|
44
|
-
/**
|
|
45
|
-
* 内部更新代理元数据
|
|
46
|
-
* @param id - 代理的 ID
|
|
47
|
-
* @returns 任意类型的返回值
|
|
48
|
-
*/
|
|
49
|
-
internalUpdateAgentMeta: (id: string) => any;
|
|
50
|
-
|
|
51
|
-
toggleAgentPlugin: (pluginId: string, checked: boolean) => void;
|
|
52
13
|
/**
|
|
53
14
|
* 更新代理配置
|
|
54
15
|
* @param config - 部分 LobeAgentConfig 的配置
|
|
55
16
|
*/
|
|
56
17
|
updateAgentConfig: (config: Partial<LobeAgentConfig>) => void;
|
|
57
18
|
updateAgentMeta: (meta: Partial<MetaData>) => void;
|
|
58
|
-
/**
|
|
59
|
-
* 更新加载状态
|
|
60
|
-
* @param key - SessionLoadingState 的键
|
|
61
|
-
* @param value - 加载状态的值
|
|
62
|
-
*/
|
|
63
|
-
updateLoadingState: (key: keyof SessionLoadingState, value: boolean) => void;
|
|
64
19
|
}
|
|
65
20
|
|
|
66
21
|
export const createAgentSlice: StateCreator<
|
|
@@ -69,147 +24,6 @@ export const createAgentSlice: StateCreator<
|
|
|
69
24
|
[],
|
|
70
25
|
AgentAction
|
|
71
26
|
> = (set, get) => ({
|
|
72
|
-
autoPickEmoji: async (id) => {
|
|
73
|
-
const { dispatchSession } = get();
|
|
74
|
-
const session = sessionSelectors.getSessionById(id)(get());
|
|
75
|
-
if (!session) return;
|
|
76
|
-
|
|
77
|
-
const systemRole = session.config.systemRole;
|
|
78
|
-
|
|
79
|
-
const emoji = await fetchPresetTaskResult({
|
|
80
|
-
onLoadingChange: (loading) => {
|
|
81
|
-
get().updateLoadingState('avatar', loading);
|
|
82
|
-
},
|
|
83
|
-
params: promptPickEmoji(systemRole),
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (emoji) {
|
|
87
|
-
dispatchSession({ id, key: 'avatar', type: 'updateSessionMeta', value: emoji });
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
autocompleteAgentDescription: async (id) => {
|
|
92
|
-
const { dispatchSession, updateLoadingState, internalUpdateAgentMeta } = get();
|
|
93
|
-
const session = sessionSelectors.getSessionById(id)(get());
|
|
94
|
-
if (!session) return;
|
|
95
|
-
|
|
96
|
-
const systemRole = session.config.systemRole;
|
|
97
|
-
|
|
98
|
-
if (!systemRole) return;
|
|
99
|
-
|
|
100
|
-
const preValue = session.meta.description;
|
|
101
|
-
|
|
102
|
-
// 替换为 ...
|
|
103
|
-
dispatchSession({ id, key: 'description', type: 'updateSessionMeta', value: '...' });
|
|
104
|
-
|
|
105
|
-
fetchPresetTaskResult({
|
|
106
|
-
onError: () => {
|
|
107
|
-
dispatchSession({
|
|
108
|
-
id,
|
|
109
|
-
key: 'description',
|
|
110
|
-
type: 'updateSessionMeta',
|
|
111
|
-
value: preValue,
|
|
112
|
-
});
|
|
113
|
-
},
|
|
114
|
-
onLoadingChange: (loading) => {
|
|
115
|
-
updateLoadingState('description', loading);
|
|
116
|
-
},
|
|
117
|
-
onMessageHandle: internalUpdateAgentMeta(id)('description'),
|
|
118
|
-
params: promptSummaryDescription(systemRole),
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
autocompleteAgentTitle: async (id) => {
|
|
123
|
-
const { dispatchSession, updateLoadingState, internalUpdateAgentMeta } = get();
|
|
124
|
-
const session = sessionSelectors.getSessionById(id)(get());
|
|
125
|
-
if (!session) return;
|
|
126
|
-
|
|
127
|
-
const systemRole = session.config.systemRole;
|
|
128
|
-
|
|
129
|
-
if (!systemRole) return;
|
|
130
|
-
|
|
131
|
-
const previousTitle = session.meta.title;
|
|
132
|
-
|
|
133
|
-
// 替换为 ...
|
|
134
|
-
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: '...' });
|
|
135
|
-
|
|
136
|
-
fetchPresetTaskResult({
|
|
137
|
-
onError: () => {
|
|
138
|
-
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: previousTitle });
|
|
139
|
-
},
|
|
140
|
-
onLoadingChange: (loading) => {
|
|
141
|
-
updateLoadingState('title', loading);
|
|
142
|
-
},
|
|
143
|
-
onMessageHandle: internalUpdateAgentMeta(id)('title'),
|
|
144
|
-
params: promptSummaryAgentName(systemRole),
|
|
145
|
-
});
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
autocompleteMeta: (key) => {
|
|
149
|
-
const { activeId, autoPickEmoji, autocompleteAgentTitle, autocompleteAgentDescription } = get();
|
|
150
|
-
if (!activeId) return;
|
|
151
|
-
|
|
152
|
-
switch (key) {
|
|
153
|
-
case 'avatar': {
|
|
154
|
-
autoPickEmoji(activeId);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
case 'description': {
|
|
159
|
-
autocompleteAgentDescription(activeId);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
case 'title': {
|
|
164
|
-
autocompleteAgentTitle(activeId);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
autocompleteSessionAgentMeta: (id, replace) => {
|
|
170
|
-
const session = sessionSelectors.getSessionById(id)(get());
|
|
171
|
-
|
|
172
|
-
if (!session) return;
|
|
173
|
-
|
|
174
|
-
if (!session.meta.title || replace) {
|
|
175
|
-
get().autocompleteAgentTitle(id);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (!session.meta.description || replace) {
|
|
179
|
-
get().autocompleteAgentDescription(id);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (!session.meta.avatar || replace) {
|
|
183
|
-
get().autoPickEmoji(id);
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
internalUpdateAgentMeta: (id: string) => (key: keyof MetaData) => {
|
|
187
|
-
let value = '';
|
|
188
|
-
return (text: string) => {
|
|
189
|
-
value += text;
|
|
190
|
-
get().dispatchSession({ id, key, type: 'updateSessionMeta', value });
|
|
191
|
-
};
|
|
192
|
-
},
|
|
193
|
-
toggleAgentPlugin: (id: string) => {
|
|
194
|
-
const { activeId } = get();
|
|
195
|
-
const session = sessionSelectors.currentSession(get());
|
|
196
|
-
if (!activeId || !session) return;
|
|
197
|
-
|
|
198
|
-
const config = produce(session.config, (draft) => {
|
|
199
|
-
if (draft.plugins === undefined) {
|
|
200
|
-
draft.plugins = [id];
|
|
201
|
-
} else {
|
|
202
|
-
const plugins = draft.plugins;
|
|
203
|
-
if (plugins.includes(id)) {
|
|
204
|
-
plugins.splice(plugins.indexOf(id), 1);
|
|
205
|
-
} else {
|
|
206
|
-
plugins.push(id);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
get().dispatchSession({ config, id: activeId, type: 'updateSessionConfig' });
|
|
212
|
-
},
|
|
213
27
|
updateAgentConfig: (config) => {
|
|
214
28
|
const { activeId } = get();
|
|
215
29
|
const session = sessionSelectors.currentSession(get());
|
|
@@ -233,11 +47,4 @@ export const createAgentSlice: StateCreator<
|
|
|
233
47
|
}
|
|
234
48
|
}
|
|
235
49
|
},
|
|
236
|
-
updateLoadingState: (key, value) => {
|
|
237
|
-
set(
|
|
238
|
-
{ autocompleteLoading: { ...get().autocompleteLoading, [key]: value } },
|
|
239
|
-
false,
|
|
240
|
-
t('updateLoadingState', { key, value }),
|
|
241
|
-
);
|
|
242
|
-
},
|
|
243
50
|
});
|
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
2
|
-
import { MetaData } from '@/types/meta';
|
|
3
2
|
import { LobeAgentConfig } from '@/types/session';
|
|
4
3
|
|
|
5
|
-
export type SessionLoadingState = Record<Partial<keyof MetaData>, boolean>;
|
|
6
|
-
|
|
7
|
-
export interface AgentConfigState {
|
|
8
|
-
autocompleteLoading: SessionLoadingState;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
4
|
export const initialLobeAgentConfig: LobeAgentConfig = DEFAULT_AGENT_CONFIG;
|
|
12
|
-
|
|
13
|
-
export const initialAgentConfigState: AgentConfigState = {
|
|
14
|
-
// // loading 中间态
|
|
15
|
-
autocompleteLoading: {
|
|
16
|
-
avatar: false,
|
|
17
|
-
backgroundColor: false,
|
|
18
|
-
description: false,
|
|
19
|
-
tag: false,
|
|
20
|
-
title: false,
|
|
21
|
-
},
|
|
22
|
-
};
|
|
@@ -2,7 +2,6 @@ import { t } from 'i18next';
|
|
|
2
2
|
import { merge } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import { DEFAULT_AVATAR, DEFAULT_BACKGROUND_COLOR } from '@/const/meta';
|
|
5
|
-
import { Autocomplete } from '@/features/AgentSetting/AgentMeta';
|
|
6
5
|
import { SessionStore } from '@/store/session';
|
|
7
6
|
import { LanguageModel } from '@/types/llm';
|
|
8
7
|
import { MetaData } from '@/types/meta';
|
|
@@ -16,13 +15,6 @@ const currentAgentMeta = (s: SessionStore): MetaData => {
|
|
|
16
15
|
return { avatar: DEFAULT_AVATAR, backgroundColor: DEFAULT_BACKGROUND_COLOR, ...session?.meta };
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
const currentAutocomplete = (s: SessionStore): Autocomplete => ({
|
|
20
|
-
autocompleteMeta: s.autocompleteMeta,
|
|
21
|
-
autocompleteSessionAgentMeta: s.autocompleteSessionAgentMeta,
|
|
22
|
-
id: s.activeId,
|
|
23
|
-
loading: s.autocompleteLoading,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
18
|
const currentAgentTitle = (s: SessionStore) => currentAgentMeta(s)?.title || t('defaultSession');
|
|
27
19
|
|
|
28
20
|
const currentAgentConfig = (s: SessionStore) => {
|
|
@@ -84,7 +76,6 @@ export const agentSelectors = {
|
|
|
84
76
|
currentAgentPlugins,
|
|
85
77
|
currentAgentSystemRole,
|
|
86
78
|
currentAgentTitle,
|
|
87
|
-
currentAutocomplete,
|
|
88
79
|
getAvatar,
|
|
89
80
|
getDescription,
|
|
90
81
|
getTitle,
|
|
@@ -263,8 +263,7 @@ export const chatMessage: StateCreator<
|
|
|
263
263
|
},
|
|
264
264
|
|
|
265
265
|
sendMessage: async (message) => {
|
|
266
|
-
const { dispatchMessage, realFetchAIResponse,
|
|
267
|
-
get();
|
|
266
|
+
const { dispatchMessage, realFetchAIResponse, activeTopicId } = get();
|
|
268
267
|
const session = sessionSelectors.currentSession(get());
|
|
269
268
|
if (!session || !message) return;
|
|
270
269
|
|
|
@@ -281,10 +280,11 @@ export const chatMessage: StateCreator<
|
|
|
281
280
|
|
|
282
281
|
await realFetchAIResponse(messages, userId);
|
|
283
282
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
// TODO: AgentSettings 提供一个外部调用的 hooks
|
|
284
|
+
// const chats = chatSelectors.currentChats(get());
|
|
285
|
+
// if (chats.length >= 4) {
|
|
286
|
+
// autocompleteSessionAgentMeta(session.id);
|
|
287
|
+
// }
|
|
288
288
|
},
|
|
289
289
|
|
|
290
290
|
stopGenerateMessage: () => {
|
package/src/types/session.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChatMessageMap } from './chatMessage';
|
|
2
2
|
import { LLMExample, LLMParams, LanguageModel } from './llm';
|
|
3
|
-
import { BaseDataModel } from './meta';
|
|
3
|
+
import { BaseDataModel, MetaData } from './meta';
|
|
4
4
|
import { ChatTopicMap } from './topic';
|
|
5
5
|
|
|
6
6
|
export enum LobeSessionType {
|
|
@@ -84,6 +84,13 @@ export interface LobeAgentSession extends LobeSessionBase {
|
|
|
84
84
|
type: LobeSessionType.Agent;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
export interface LobeAgentSettings {
|
|
88
|
+
/**
|
|
89
|
+
* 语言模型角色设定
|
|
90
|
+
*/
|
|
91
|
+
config: LobeAgentConfig;
|
|
92
|
+
meta: MetaData;
|
|
93
|
+
}
|
|
87
94
|
export type LobeSessions = Record<string, LobeAgentSession>;
|
|
88
95
|
|
|
89
96
|
export type LobeAgentConfigKeys =
|