@lobehub/chat 0.89.7 β 0.89.9
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 +58 -0
- package/README.md +10 -10
- package/package.json +1 -1
- package/src/app/chat/features/Conversation/ChatList/Error/InvalidAccess.tsx +2 -2
- package/src/app/chat/features/Conversation/ChatList/Error/OpenAPIKey.tsx +2 -1
- package/src/app/chat/features/Conversation/ChatList/Error/OpenAiBizError.tsx +7 -5
- package/src/app/chat/features/Conversation/ChatList/Error/Plugin/PluginError.tsx +5 -4
- package/src/app/chat/features/Conversation/ChatList/Error/Plugin/PluginSettings.tsx +6 -12
- package/src/app/chat/features/Conversation/ChatList/Error/index.tsx +17 -39
- package/src/app/chat/features/Conversation/ChatList/Messages/Assistant.tsx +80 -0
- package/src/app/chat/features/Conversation/ChatList/Messages/Default.tsx +6 -0
- package/src/app/chat/features/Conversation/ChatList/Messages/Function.tsx +42 -0
- package/src/app/chat/features/Conversation/ChatList/Messages/System.tsx +7 -0
- package/src/app/chat/features/Conversation/ChatList/Messages/User.tsx +14 -0
- package/src/app/chat/features/Conversation/ChatList/Messages/index.ts +24 -0
- package/src/app/chat/features/Conversation/ChatList/Plugins/FunctionCall.tsx +2 -0
- package/src/app/chat/features/Conversation/ChatList/index.tsx +11 -52
- package/src/store/session/slices/chat/selectors/chat.ts +21 -0
- package/src/app/chat/features/Conversation/ChatList/MessageExtra.tsx +0 -85
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.89.9](https://github.com/lobehub/lobe-chat/compare/v0.89.8...v0.89.9)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-10-17**</sup>
|
|
8
|
+
|
|
9
|
+
#### π Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix ChatList FC Render.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fix ChatList FC Render ([4b8bdbd](https://github.com/lobehub/lobe-chat/commit/4b8bdbd))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.89.8](https://github.com/lobehub/lobe-chat/compare/v0.89.7...v0.89.8)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-10-16**</sup>
|
|
33
|
+
|
|
34
|
+
#### β» Code Refactoring
|
|
35
|
+
|
|
36
|
+
- **misc**: Refactor ChatList.
|
|
37
|
+
|
|
38
|
+
#### π Bug Fixes
|
|
39
|
+
|
|
40
|
+
- **misc**: Fix type.
|
|
41
|
+
|
|
42
|
+
<br/>
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
46
|
+
|
|
47
|
+
#### Code refactoring
|
|
48
|
+
|
|
49
|
+
- **misc**: Refactor ChatList, closes [#147](https://github.com/lobehub/lobe-chat/issues/147) ([aa4216c](https://github.com/lobehub/lobe-chat/commit/aa4216c))
|
|
50
|
+
|
|
51
|
+
#### What's fixed
|
|
52
|
+
|
|
53
|
+
- **misc**: Fix type ([1e931d5](https://github.com/lobehub/lobe-chat/commit/1e931d5))
|
|
54
|
+
|
|
55
|
+
</details>
|
|
56
|
+
|
|
57
|
+
<div align="right">
|
|
58
|
+
|
|
59
|
+
[](#readme-top)
|
|
60
|
+
|
|
61
|
+
</div>
|
|
62
|
+
|
|
5
63
|
### [Version 0.89.7](https://github.com/lobehub/lobe-chat/compare/v0.89.6...v0.89.7)
|
|
6
64
|
|
|
7
65
|
<sup>Released on **2023-10-16**</sup>
|
package/README.md
CHANGED
|
@@ -86,14 +86,14 @@ Please be aware that LobeChat is currently under active development, and feedbac
|
|
|
86
86
|
|
|
87
87
|
## β¨ Features
|
|
88
88
|
|
|
89
|
-
- [x] π¨ **Quick Deployment**: Using the Vercel platform, you can deploy with just one click and complete the process within 1 minute without any complex configuration
|
|
90
|
-
- [x] π **Exquisite UI Design**: With a carefully designed interface, it offers an elegant appearance and smooth interaction. It supports light and dark themes and is mobile-friendly. PWA support provides a more native-like experience
|
|
91
|
-
- [x] π£οΈ **Smooth Conversation Experience**: Fluid responses ensure a smooth conversation experience. It fully supports Markdown rendering, including code highlighting, LaTex formulas, Mermaid flowcharts, and more
|
|
92
|
-
- [x] π§© **Plugin Support & Custom Plugin Development**: Conversations are extendable with plugins. Users can install and use various plugins, such as search engines, web extraction, etc. It also supports the development of custom plugins to meet custom needs
|
|
89
|
+
- [x] π¨ **Quick Deployment**: Using the Vercel platform, you can deploy with just one click and complete the process within 1 minute without any complex configuration.
|
|
90
|
+
- [x] π **Exquisite UI Design**: With a carefully designed interface, it offers an elegant appearance and smooth interaction. It supports light and dark themes and is mobile-friendly. PWA support provides a more native-like experience.
|
|
91
|
+
- [x] π£οΈ **Smooth Conversation Experience**: Fluid responses ensure a smooth conversation experience. It fully supports Markdown rendering, including code highlighting, LaTex formulas, Mermaid flowcharts, and more.
|
|
92
|
+
- [x] π§© **Plugin Support & Custom Plugin Development**: Conversations are extendable with plugins. Users can install and use various plugins, such as search engines, web extraction, etc. It also supports the development of custom plugins to meet custom needs.
|
|
93
93
|
- [x] π **Privacy Protection**: All data is stored locally in the user's browser, ensuring user privacy;
|
|
94
94
|
- [x] π€ **Customizable Agent Roles**: Users can create, share, and debug personalized dialogue agent roles according to their needs, providing more flexible and customized dialogue functions;
|
|
95
95
|
- [x] π **Custom Domain**: If users have their own domain, they can bind it to the platform for quick access to the dialogue agent from anywhere.
|
|
96
|
-
- [x] π¬ **Role Market**: A Role Market is provided where users can select their preferred dialogue agent roles, enriching the content and style of the dialogue
|
|
96
|
+
- [x] π¬ **Role Market**: A Role Market is provided where users can select their preferred dialogue agent roles, enriching the content and style of the dialogue.
|
|
97
97
|
|
|
98
98
|
> **Note**\
|
|
99
99
|
> You can find our upcoming [Roadmap][github-project-link] plans in the Projects section.
|
|
@@ -183,8 +183,8 @@ LobeChat provides Self-Hosted Version with Vercel and [Docker Image][docker-rele
|
|
|
183
183
|
If you want to deploy this service yourself on Vercel, you can follow these steps:
|
|
184
184
|
|
|
185
185
|
- Prepare your [OpenAI API Key](https://platform.openai.com/account/api-keys).
|
|
186
|
-
- Click the button below to start deployment: Deploy with Vercel. Log in directly with your GitHub account, and remember to fill in the `OPENAI_API_KEY`(required) and `ACCESS_CODE` (recommended) on the environment variable section
|
|
187
|
-
- After deployment, you can start using it
|
|
186
|
+
- Click the button below to start deployment: Deploy with Vercel. Log in directly with your GitHub account, and remember to fill in the `OPENAI_API_KEY`(required) and `ACCESS_CODE` (recommended) on the environment variable section.
|
|
187
|
+
- After deployment, you can start using it.
|
|
188
188
|
- Bind a custom domain (optional): The DNS of the domain assigned by Vercel is polluted in some areas; binding a custom domain can connect directly.
|
|
189
189
|
|
|
190
190
|
<div align="center">
|
|
@@ -279,8 +279,8 @@ Plugins provide a means to extend the [Function Calling][fc-link] capabilities o
|
|
|
279
279
|
> The plugin system is currently undergoing major development. You can learn more in the following issues:
|
|
280
280
|
>
|
|
281
281
|
> - [x] [**Plugin Phase 1**](https://github.com/lobehub/lobe-chat/issues/73): Implement separation of the plugin from the main body, split the plugin into an independent repository for maintenance, and realize dynamic loading of the plugin.
|
|
282
|
-
> - [x] [**Plugin Phase 2**](https://github.com/lobehub/lobe-chat/issues/97): The security and stability of the plugin's use, more accurately presenting abnormal states, the maintainability of the plugin architecture and developer-friendly.
|
|
283
|
-
> - [ ] [**Plugin Phase 3**](https://github.com/lobehub/lobe-chat/issues/149): Higher-level and more comprehensive customization capabilities, support for plugin authentication and examples.
|
|
282
|
+
> - [x] [**Plugin Phase 2**](https://github.com/lobehub/lobe-chat/issues/97): The security and stability of the plugin's use, more accurately presenting abnormal states, the maintainability of the plugin architecture, and developer-friendly.
|
|
283
|
+
> - [ ] [**Plugin Phase 3**](https://github.com/lobehub/lobe-chat/issues/149): Higher-level and more comprehensive customization capabilities, support for plugin authentication, and examples.
|
|
284
284
|
|
|
285
285
|
| Official Plugin | Description |
|
|
286
286
|
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -335,7 +335,7 @@ Contributions of all types are more than welcome; if you are interested in contr
|
|
|
335
335
|
|
|
336
336
|
## π More Products
|
|
337
337
|
|
|
338
|
-
- **[π€― Lobe Theme][lobe-theme]:** The modern theme for stable diffusion
|
|
338
|
+
- **[π€― Lobe Theme][lobe-theme]:** The modern theme for stable diffusion WebUI, exquisite interface design, highly customizable UI, and efficiency-boosting features.
|
|
339
339
|
- **[π Lobe i18n][lobe-i18n] :** Lobe i18n is an automation tool for the i18n (internationalization) translation process, powered by ChatGPT. It supports features such as automatic splitting of large files, incremental updates, and customization options for the OpenAI model, API proxy, and temperature.
|
|
340
340
|
- **[π Lobe Commit][lobe-commit]:** Lobe Commit is a CLI tool that leverages Langchain/ChatGPT to generate Gitmoji-based commit messages.
|
|
341
341
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.89.
|
|
3
|
+
"version": "0.89.9",
|
|
4
4
|
"description": "An open-source, extensible (Function Calling), high-performance chatbot framework. It supports one-click free deployment of your private ChatGPT/LLM web application",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatbot",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Icon } from '@lobehub/ui';
|
|
1
|
+
import { Icon, RenderErrorMessage } from '@lobehub/ui';
|
|
2
2
|
import { Button, Segmented } from 'antd';
|
|
3
3
|
import { KeySquare, SquareAsterisk } from 'lucide-react';
|
|
4
4
|
import { memo, useState } from 'react';
|
|
@@ -17,7 +17,7 @@ enum Tab {
|
|
|
17
17
|
Password = 'password',
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const InvalidAccess = memo
|
|
20
|
+
const InvalidAccess: RenderErrorMessage = memo(({ id }) => {
|
|
21
21
|
const { t } = useTranslation('error');
|
|
22
22
|
const [mode, setMode] = useState<Tab>(Tab.Password);
|
|
23
23
|
const [password, setSettings] = useGlobalStore((s) => [s.settings.password, s.setSettings]);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { RenderErrorMessage } from '@lobehub/ui';
|
|
1
2
|
import { memo } from 'react';
|
|
2
3
|
|
|
3
4
|
import APIKeyForm from './ApiKeyForm';
|
|
4
5
|
import { ErrorActionContainer } from './style';
|
|
5
6
|
|
|
6
|
-
const OpenAPIKey = memo
|
|
7
|
+
const OpenAPIKey: RenderErrorMessage = memo(({ id }) => (
|
|
7
8
|
<ErrorActionContainer>
|
|
8
9
|
<APIKeyForm id={id} />
|
|
9
10
|
</ErrorActionContainer>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Highlighter } from '@lobehub/ui';
|
|
1
|
+
import { Highlighter, RenderErrorMessage } from '@lobehub/ui';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
@@ -16,16 +16,18 @@ interface OpenAIErrorResponse {
|
|
|
16
16
|
error: OpenAIError;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const OpenAiBizError = memo
|
|
19
|
+
const OpenAiBizError: RenderErrorMessage = memo(({ error, id, ...props }) => {
|
|
20
20
|
const { styles } = useStyles();
|
|
21
21
|
|
|
22
|
-
const
|
|
22
|
+
const errorBody: OpenAIErrorResponse = (error as any)?.body;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const errorCode = errorBody.error?.code;
|
|
25
|
+
|
|
26
|
+
if (errorCode === 'invalid_api_key') return <OpenAPIKey error={error} id={id} {...props} />;
|
|
25
27
|
|
|
26
28
|
return (
|
|
27
29
|
<Flexbox className={styles.container} style={{ maxWidth: 600 }}>
|
|
28
|
-
<Highlighter language={'json'}>{JSON.stringify(
|
|
30
|
+
<Highlighter language={'json'}>{JSON.stringify(errorBody, null, 2)}</Highlighter>
|
|
29
31
|
</Flexbox>
|
|
30
32
|
);
|
|
31
33
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Highlighter } from '@lobehub/ui';
|
|
1
|
+
import { Highlighter, RenderErrorMessage } from '@lobehub/ui';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
@@ -15,12 +15,13 @@ interface OpenAIErrorResponse {
|
|
|
15
15
|
error: OpenAIError;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const PluginError = memo
|
|
18
|
+
const PluginError: RenderErrorMessage = memo(({ error, id }) => {
|
|
19
19
|
const { styles } = useStyles();
|
|
20
|
+
const errorBody: OpenAIErrorResponse = (error as any)?.body;
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
|
-
<Flexbox className={styles.container} style={{ maxWidth: 600 }}>
|
|
23
|
-
<Highlighter language={'json'}>{JSON.stringify(
|
|
23
|
+
<Flexbox className={styles.container} id={id} style={{ maxWidth: 600 }}>
|
|
24
|
+
<Highlighter language={'json'}>{JSON.stringify(errorBody, null, 2)}</Highlighter>
|
|
24
25
|
</Flexbox>
|
|
25
26
|
);
|
|
26
27
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Avatar } from '@lobehub/ui';
|
|
1
|
+
import { Avatar, RenderErrorMessage } from '@lobehub/ui';
|
|
2
2
|
import { Button, Divider } from 'antd';
|
|
3
3
|
import { useTheme } from 'antd-style';
|
|
4
4
|
import isEqual from 'fast-deep-equal';
|
|
@@ -12,32 +12,26 @@ import { useSessionStore } from '@/store/session';
|
|
|
12
12
|
|
|
13
13
|
import { ErrorActionContainer, useStyles } from '../style';
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
id: string;
|
|
17
|
-
pluginIdentifier: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const PluginSettings = memo<PluginSettingsProps>(({ id, pluginIdentifier }) => {
|
|
15
|
+
const PluginSettings: RenderErrorMessage = memo(({ id, plugin }) => {
|
|
21
16
|
const { styles } = useStyles();
|
|
22
|
-
|
|
23
17
|
const { t } = useTranslation('error');
|
|
24
18
|
const theme = useTheme();
|
|
25
19
|
const [resend, deleteMessage] = useSessionStore((s) => [s.resendMessage, s.deleteMessage]);
|
|
26
|
-
|
|
27
|
-
const
|
|
20
|
+
const pluginIdentifier = plugin?.identifier as string;
|
|
21
|
+
const pluginMeta = usePluginStore(pluginSelectors.getPluginMetaById(pluginIdentifier), isEqual);
|
|
28
22
|
const manifest = usePluginStore(pluginSelectors.getPluginManifestById(pluginIdentifier), isEqual);
|
|
29
23
|
|
|
30
24
|
return (
|
|
31
25
|
<ErrorActionContainer>
|
|
32
26
|
<Center gap={16} style={{ maxWidth: 400 }}>
|
|
33
27
|
<Avatar
|
|
34
|
-
avatar={pluginHelpers.getPluginAvatar(
|
|
28
|
+
avatar={pluginHelpers.getPluginAvatar(pluginMeta?.meta) || 'βοΈ'}
|
|
35
29
|
background={theme.colorFillContent}
|
|
36
30
|
gap={12}
|
|
37
31
|
size={80}
|
|
38
32
|
/>
|
|
39
33
|
<Flexbox style={{ fontSize: 20 }}>
|
|
40
|
-
{t('pluginSettings.title', { name: pluginHelpers.getPluginTitle(
|
|
34
|
+
{t('pluginSettings.title', { name: pluginHelpers.getPluginTitle(pluginMeta?.meta) })}
|
|
41
35
|
</Flexbox>
|
|
42
36
|
<Flexbox className={styles.desc}>{t('pluginSettings.desc')}</Flexbox>
|
|
43
37
|
<Divider style={{ margin: '0 16px' }} />
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
|
|
2
|
+
import { ChatListProps } from '@lobehub/ui';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { ChatErrorType, ErrorType } from '@/types/fetch';
|
|
4
|
+
import { ChatErrorType } from '@/types/fetch';
|
|
6
5
|
|
|
7
6
|
import InvalidAccess from './InvalidAccess';
|
|
8
7
|
import OpenAPIKey from './OpenAPIKey';
|
|
@@ -10,39 +9,18 @@ import OpenAiBizError from './OpenAiBizError';
|
|
|
10
9
|
import PluginError from './Plugin/PluginError';
|
|
11
10
|
import PluginSettings from './Plugin/PluginSettings';
|
|
12
11
|
|
|
13
|
-
export const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
message.plugin?.identifier && (
|
|
29
|
-
<PluginSettings id={message.id} pluginIdentifier={message.plugin?.identifier} />
|
|
30
|
-
)
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
switch (error.type as ErrorType) {
|
|
36
|
-
case ChatErrorType.InvalidAccessCode: {
|
|
37
|
-
return <InvalidAccess id={message.id} />;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
case ChatErrorType.NoAPIKey: {
|
|
41
|
-
return <OpenAPIKey id={message.id} />;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
case ChatErrorType.OpenAIBizError: {
|
|
45
|
-
return <OpenAiBizError content={(error as any).body} id={message.id} />;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
12
|
+
export const renderErrorMessages: ChatListProps['renderErrorMessages'] = {
|
|
13
|
+
[PluginErrorType.PluginMarketIndexNotFound]: PluginError,
|
|
14
|
+
[PluginErrorType.PluginMarketIndexInvalid]: PluginError,
|
|
15
|
+
[PluginErrorType.PluginMetaInvalid]: PluginError,
|
|
16
|
+
[PluginErrorType.PluginMetaNotFound]: PluginError,
|
|
17
|
+
[PluginErrorType.PluginManifestInvalid]: PluginError,
|
|
18
|
+
[PluginErrorType.PluginManifestNotFound]: PluginError,
|
|
19
|
+
[PluginErrorType.PluginApiNotFound]: PluginError,
|
|
20
|
+
[PluginErrorType.PluginApiParamsError]: PluginError,
|
|
21
|
+
[PluginErrorType.PluginServerError]: PluginError,
|
|
22
|
+
[PluginErrorType.PluginSettingsInvalid]: PluginSettings,
|
|
23
|
+
[ChatErrorType.InvalidAccessCode]: InvalidAccess,
|
|
24
|
+
[ChatErrorType.NoAPIKey]: OpenAPIKey,
|
|
25
|
+
[ChatErrorType.OpenAIBizError]: OpenAiBizError,
|
|
48
26
|
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SiOpenai } from '@icons-pack/react-simple-icons';
|
|
2
|
+
import {
|
|
3
|
+
ActionIconGroup,
|
|
4
|
+
RenderAction,
|
|
5
|
+
RenderMessage,
|
|
6
|
+
RenderMessageExtra,
|
|
7
|
+
Tag,
|
|
8
|
+
useChatListActionsBar,
|
|
9
|
+
} from '@lobehub/ui';
|
|
10
|
+
import { createStyles } from 'antd-style';
|
|
11
|
+
import { memo } from 'react';
|
|
12
|
+
import { Flexbox } from 'react-layout-kit';
|
|
13
|
+
|
|
14
|
+
import { useSessionStore } from '@/store/session';
|
|
15
|
+
import { agentSelectors } from '@/store/session/slices/agentConfig';
|
|
16
|
+
import { currentFunctionCallProps } from '@/store/session/slices/chat/selectors/chat';
|
|
17
|
+
import { isFunctionMessage } from '@/utils/message';
|
|
18
|
+
|
|
19
|
+
import FunctionCall from '../Plugins/FunctionCall';
|
|
20
|
+
import { DefautMessage } from './Default';
|
|
21
|
+
import { SystemActionsBar } from './System';
|
|
22
|
+
|
|
23
|
+
const useStyles = createStyles(({ css }) => ({
|
|
24
|
+
container: css`
|
|
25
|
+
margin-top: 8px;
|
|
26
|
+
`,
|
|
27
|
+
plugin: css`
|
|
28
|
+
display: flex;
|
|
29
|
+
gap: 4px;
|
|
30
|
+
align-items: center;
|
|
31
|
+
width: fit-content;
|
|
32
|
+
`,
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
export const AssistantMessage: RenderMessage = memo(
|
|
36
|
+
({ id, plugin, function_call, content, ...props }) => {
|
|
37
|
+
const genFunctionCallProps = useSessionStore(currentFunctionCallProps);
|
|
38
|
+
|
|
39
|
+
if (!isFunctionMessage(content)) return <DefautMessage content={content} id={id} {...props} />;
|
|
40
|
+
|
|
41
|
+
const fcProps = genFunctionCallProps({ content, function_call, id, plugin });
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div id={id}>
|
|
45
|
+
<FunctionCall {...fcProps} />
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
export const AssistantMessageExtra: RenderMessageExtra = memo(({ extra, function_call }) => {
|
|
52
|
+
const { styles } = useStyles();
|
|
53
|
+
const model = useSessionStore(agentSelectors.currentAgentModel);
|
|
54
|
+
|
|
55
|
+
const hasModelTag = extra?.fromModel && model !== extra?.fromModel;
|
|
56
|
+
const hasFuncTag = !!function_call;
|
|
57
|
+
if (!(hasModelTag || hasFuncTag)) return;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<Flexbox className={styles.container} horizontal>
|
|
61
|
+
<div>
|
|
62
|
+
<Tag icon={<SiOpenai size={'1em'} />}>{extra?.fromModel as string}</Tag>
|
|
63
|
+
</div>
|
|
64
|
+
</Flexbox>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const AssistantActionsBar: RenderAction = memo(({ text, error, id, ...props }) => {
|
|
69
|
+
const { regenerate, edit, copy, divider, del } = useChatListActionsBar(text);
|
|
70
|
+
if (id === 'default') return;
|
|
71
|
+
if (error) return <SystemActionsBar id={id} text={text} {...props} />;
|
|
72
|
+
return (
|
|
73
|
+
<ActionIconGroup
|
|
74
|
+
dropdownMenu={[edit, copy, regenerate, divider, del]}
|
|
75
|
+
items={[regenerate, copy]}
|
|
76
|
+
type="ghost"
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ActionIconGroup, RenderAction, RenderMessage, useChatListActionsBar } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { Flexbox } from 'react-layout-kit';
|
|
4
|
+
|
|
5
|
+
import { useSessionStore } from '@/store/session';
|
|
6
|
+
import { currentFunctionCallProps } from '@/store/session/slices/chat/selectors/chat';
|
|
7
|
+
|
|
8
|
+
import FunctionCall from '../Plugins/FunctionCall';
|
|
9
|
+
import PluginMessage from '../Plugins/PluginMessage';
|
|
10
|
+
|
|
11
|
+
export const FunctionMessage: RenderMessage = memo(
|
|
12
|
+
({ id, content, plugin, function_call, ...props }) => {
|
|
13
|
+
const genFunctionCallProps = useSessionStore(currentFunctionCallProps);
|
|
14
|
+
const fcProps = genFunctionCallProps({ content, function_call, id, plugin });
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Flexbox gap={12} id={id}>
|
|
18
|
+
<FunctionCall {...fcProps} />
|
|
19
|
+
<PluginMessage
|
|
20
|
+
content={content}
|
|
21
|
+
function_call={function_call}
|
|
22
|
+
id={id}
|
|
23
|
+
loading={fcProps.loading}
|
|
24
|
+
plugin={plugin}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
</Flexbox>
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const FunctionActionsBar: RenderAction = memo(({ text, ...props }) => {
|
|
33
|
+
const { regenerate, divider, del } = useChatListActionsBar(text);
|
|
34
|
+
return (
|
|
35
|
+
<ActionIconGroup
|
|
36
|
+
dropdownMenu={[regenerate, divider, del]}
|
|
37
|
+
items={[regenerate]}
|
|
38
|
+
type="ghost"
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ActionIconGroup, RenderAction, useChatListActionsBar } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
|
|
4
|
+
export const SystemActionsBar: RenderAction = memo(({ text, ...props }) => {
|
|
5
|
+
const { del } = useChatListActionsBar(text);
|
|
6
|
+
return <ActionIconGroup dropdownMenu={[del]} items={[]} type="ghost" {...props} />;
|
|
7
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ActionIconGroup, RenderAction, useChatListActionsBar } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
|
|
4
|
+
export const UserActionsBar: RenderAction = memo(({ text, ...props }) => {
|
|
5
|
+
const { regenerate, edit, copy, divider, del } = useChatListActionsBar(text);
|
|
6
|
+
return (
|
|
7
|
+
<ActionIconGroup
|
|
8
|
+
dropdownMenu={[edit, copy, regenerate, divider, del]}
|
|
9
|
+
items={[regenerate, edit]}
|
|
10
|
+
type="ghost"
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ChatListProps } from '@lobehub/ui';
|
|
2
|
+
|
|
3
|
+
import { AssistantActionsBar, AssistantMessage, AssistantMessageExtra } from './Assistant';
|
|
4
|
+
import { DefautMessage } from './Default';
|
|
5
|
+
import { FunctionActionsBar, FunctionMessage } from './Function';
|
|
6
|
+
import { SystemActionsBar } from './System';
|
|
7
|
+
import { UserActionsBar } from './User';
|
|
8
|
+
|
|
9
|
+
export const renderMessages: ChatListProps['renderMessages'] = {
|
|
10
|
+
assistant: AssistantMessage,
|
|
11
|
+
default: DefautMessage,
|
|
12
|
+
function: FunctionMessage,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const renderMessagesExtra: ChatListProps['renderMessagesExtra'] = {
|
|
16
|
+
assistant: AssistantMessageExtra,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const renderActions: ChatListProps['renderActions'] = {
|
|
20
|
+
assistant: AssistantActionsBar,
|
|
21
|
+
function: FunctionActionsBar,
|
|
22
|
+
system: SystemActionsBar,
|
|
23
|
+
user: UserActionsBar,
|
|
24
|
+
};
|
|
@@ -30,6 +30,8 @@ const FunctionCall = memo<FunctionCallProps>(
|
|
|
30
30
|
const pluginAvatar = pluginHelpers.getPluginAvatar(item?.meta);
|
|
31
31
|
const pluginTitle = pluginHelpers.getPluginTitle(item?.meta);
|
|
32
32
|
|
|
33
|
+
console.log(item?.meta);
|
|
34
|
+
|
|
33
35
|
const avatar = pluginAvatar ? (
|
|
34
36
|
<Avatar avatar={pluginAvatar} size={32} />
|
|
35
37
|
) : (
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { ChatList
|
|
1
|
+
import { ChatList } from '@lobehub/ui';
|
|
2
2
|
import isEqual from 'fast-deep-equal';
|
|
3
|
-
import { memo
|
|
3
|
+
import { memo } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
5
|
|
|
7
6
|
import { useSessionChatInit, useSessionStore } from '@/store/session';
|
|
8
7
|
import { agentSelectors, chatSelectors } from '@/store/session/selectors';
|
|
9
|
-
import { ChatMessage } from '@/types/chatMessage';
|
|
10
|
-
import { isFunctionMessage } from '@/utils/message';
|
|
11
8
|
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import FunctionCall from './Plugins/FunctionCall';
|
|
15
|
-
import PluginMessage from './Plugins/PluginMessage';
|
|
9
|
+
import { renderErrorMessages } from './Error';
|
|
10
|
+
import { renderActions, renderMessages, renderMessagesExtra } from './Messages';
|
|
16
11
|
import SkeletonList from './SkeletonList';
|
|
17
12
|
|
|
18
13
|
const List = memo(() => {
|
|
@@ -41,43 +36,6 @@ const List = memo(() => {
|
|
|
41
36
|
];
|
|
42
37
|
});
|
|
43
38
|
|
|
44
|
-
const renderMessage: RenderMessage = useCallback(
|
|
45
|
-
(content, message: ChatMessage) => {
|
|
46
|
-
const id = message.plugin?.identifier || message.function_call?.name;
|
|
47
|
-
const command = message.plugin ?? message.function_call;
|
|
48
|
-
const args = command?.arguments;
|
|
49
|
-
const fcProps = {
|
|
50
|
-
arguments: args,
|
|
51
|
-
command,
|
|
52
|
-
content: message.content,
|
|
53
|
-
id,
|
|
54
|
-
loading: message.id === chatLoadingId,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
if (message.role === 'function')
|
|
58
|
-
return (
|
|
59
|
-
<Flexbox gap={12} id={message.id}>
|
|
60
|
-
<FunctionCall {...fcProps} />
|
|
61
|
-
<PluginMessage loading={message.id === chatLoadingId} {...message} />
|
|
62
|
-
</Flexbox>
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
message.role === 'assistant' &&
|
|
67
|
-
// ε
ε«δΊ function δΏ‘ζ―
|
|
68
|
-
isFunctionMessage(message.content)
|
|
69
|
-
)
|
|
70
|
-
return (
|
|
71
|
-
<div id={message.id}>
|
|
72
|
-
<FunctionCall {...fcProps} />
|
|
73
|
-
</div>
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
return <div id={message.id}>{content}</div>;
|
|
77
|
-
},
|
|
78
|
-
[chatLoadingId],
|
|
79
|
-
);
|
|
80
|
-
|
|
81
39
|
if (!init) return <SkeletonList />;
|
|
82
40
|
|
|
83
41
|
return (
|
|
@@ -99,12 +57,13 @@ const List = memo(() => {
|
|
|
99
57
|
}
|
|
100
58
|
}
|
|
101
59
|
}}
|
|
102
|
-
onMessageChange={(id, content) =>
|
|
103
|
-
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: content })
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
60
|
+
onMessageChange={(id, content) =>
|
|
61
|
+
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: content })
|
|
62
|
+
}
|
|
63
|
+
renderActions={renderActions}
|
|
64
|
+
renderErrorMessages={renderErrorMessages}
|
|
65
|
+
renderMessages={renderMessages}
|
|
66
|
+
renderMessagesExtra={renderMessagesExtra}
|
|
108
67
|
style={{ marginTop: 24 }}
|
|
109
68
|
text={{
|
|
110
69
|
cancel: t('cancel'),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { t } from 'i18next';
|
|
2
2
|
|
|
3
|
+
import { FunctionCallProps } from '@/app/chat/features/Conversation/ChatList/Plugins/FunctionCall';
|
|
3
4
|
import { DEFAULT_INBOX_AVATAR, DEFAULT_USER_AVATAR } from '@/const/meta';
|
|
4
5
|
import { INBOX_SESSION_ID } from '@/const/session';
|
|
5
6
|
import { useGlobalStore } from '@/store/global';
|
|
@@ -84,3 +85,23 @@ export const chatsMessageString = (s: SessionStore): string => {
|
|
|
84
85
|
const chats = currentChatsWithHistoryConfig(s);
|
|
85
86
|
return chats.map((m) => m.content).join('');
|
|
86
87
|
};
|
|
88
|
+
|
|
89
|
+
export const currentFunctionCallProps = (
|
|
90
|
+
s: SessionStore,
|
|
91
|
+
): ((
|
|
92
|
+
props: Pick<ChatMessage, 'plugin' | 'function_call' | 'content' | 'id'>,
|
|
93
|
+
) => FunctionCallProps) => {
|
|
94
|
+
const chatLoadingId = s.chatLoadingId;
|
|
95
|
+
return ({ plugin, function_call, content, id }) => {
|
|
96
|
+
const itemId = plugin?.identifier || function_call?.name;
|
|
97
|
+
const command = plugin ?? function_call;
|
|
98
|
+
const args = command?.arguments;
|
|
99
|
+
return {
|
|
100
|
+
arguments: args,
|
|
101
|
+
command,
|
|
102
|
+
content,
|
|
103
|
+
id: itemId,
|
|
104
|
+
loading: id === chatLoadingId,
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { SiOpenai } from '@icons-pack/react-simple-icons';
|
|
2
|
-
import { Tag } from '@lobehub/ui';
|
|
3
|
-
import { createStyles } from 'antd-style';
|
|
4
|
-
import { ReactNode } from 'react';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
import { useSessionStore } from '@/store/session';
|
|
8
|
-
import { agentSelectors } from '@/store/session/selectors';
|
|
9
|
-
import { ChatMessage } from '@/types/chatMessage';
|
|
10
|
-
|
|
11
|
-
const useStyles = createStyles(({ css }) => ({
|
|
12
|
-
container: css`
|
|
13
|
-
margin-top: 8px;
|
|
14
|
-
`,
|
|
15
|
-
plugin: css`
|
|
16
|
-
display: flex;
|
|
17
|
-
gap: 4px;
|
|
18
|
-
align-items: center;
|
|
19
|
-
width: fit-content;
|
|
20
|
-
`,
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
const MessageExtra = ({
|
|
24
|
-
role,
|
|
25
|
-
extra,
|
|
26
|
-
// name,
|
|
27
|
-
function_call,
|
|
28
|
-
}: ChatMessage): ReactNode => {
|
|
29
|
-
const { styles } = useStyles();
|
|
30
|
-
|
|
31
|
-
// const { t } = useTranslation();
|
|
32
|
-
const [model] = useSessionStore((s) => [agentSelectors.currentAgentModel(s)]);
|
|
33
|
-
|
|
34
|
-
// const plugin = PluginsMap[name || ''];
|
|
35
|
-
|
|
36
|
-
// const funcTag = (
|
|
37
|
-
// <Tag bordered={false} className={styles.plugin} style={{ borderRadius: 6 }}>
|
|
38
|
-
// {plugin?.avatar ? (
|
|
39
|
-
// <Avatar avatar={plugin?.avatar} size={18} />
|
|
40
|
-
// ) : (
|
|
41
|
-
// <Icon icon={LucideToyBrick} />
|
|
42
|
-
// )}
|
|
43
|
-
// {t(`plugins.${name}` as any, { ns: 'plugin' })}
|
|
44
|
-
// </Tag>
|
|
45
|
-
// );
|
|
46
|
-
|
|
47
|
-
const modelTag = (
|
|
48
|
-
<div>
|
|
49
|
-
<Tag icon={<SiOpenai size={'1em'} />}>{extra?.fromModel as string}</Tag>
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
// 1. εε¨ fromModel
|
|
54
|
-
// 2. δΈε½εη model ε fromModel δΈδΈθ΄ζΆ
|
|
55
|
-
const hasModelTag = extra?.fromModel && model !== extra?.fromModel;
|
|
56
|
-
|
|
57
|
-
const hasFuncTag = !!function_call;
|
|
58
|
-
|
|
59
|
-
switch (role) {
|
|
60
|
-
case 'user':
|
|
61
|
-
case 'function':
|
|
62
|
-
case 'system': {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
case 'assistant': {
|
|
66
|
-
// 1. εͺζ ai η message
|
|
67
|
-
// 2. δΈεε¨ fromModel
|
|
68
|
-
// 3. δΈε½εη model ε fromModel δΈδΈθ΄ζΆ
|
|
69
|
-
if (!(hasModelTag || hasFuncTag)) return;
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
hasModelTag && (
|
|
73
|
-
<Flexbox className={styles.container} horizontal>
|
|
74
|
-
{modelTag}
|
|
75
|
-
</Flexbox>
|
|
76
|
-
)
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
// case 'function': {
|
|
80
|
-
// return <Flexbox className={styles.container}>{funcTag}</Flexbox>;
|
|
81
|
-
// }
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export default MessageExtra;
|