@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 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
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#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
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#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 webui, exquisite interface design, highly customizable UI, and efficiency-boosting features.
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.7",
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<{ id: string }>(({ id }) => {
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<{ id: string }>(({ id }) => (
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<{ content: OpenAIErrorResponse; id: string }>(({ content, id }) => {
19
+ const OpenAiBizError: RenderErrorMessage = memo(({ error, id, ...props }) => {
20
20
  const { styles } = useStyles();
21
21
 
22
- const errorCode = content.error?.code;
22
+ const errorBody: OpenAIErrorResponse = (error as any)?.body;
23
23
 
24
- if (errorCode === 'invalid_api_key') return <OpenAPIKey id={id} />;
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(content, null, 2)}</Highlighter>
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<{ content: OpenAIErrorResponse; id: string }>(({ content }) => {
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(content, null, 2)}</Highlighter>
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
- interface PluginSettingsProps {
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 plugin = usePluginStore(pluginSelectors.getPluginMetaById(pluginIdentifier), isEqual);
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(plugin?.meta) || 'βš™οΈ'}
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(plugin?.meta) })}
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 { IPluginErrorType, PluginErrorType } from '@lobehub/chat-plugin-sdk';
2
- import { RenderErrorMessage } from '@lobehub/ui';
1
+ import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
2
+ import { ChatListProps } from '@lobehub/ui';
3
3
 
4
- import { ChatMessage } from '@/types/chatMessage';
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 renderErrorMessage: RenderErrorMessage = (error, message: ChatMessage) => {
14
- switch (error.type as IPluginErrorType) {
15
- case PluginErrorType.PluginMarketIndexNotFound:
16
- case PluginErrorType.PluginMarketIndexInvalid:
17
- case PluginErrorType.PluginMetaInvalid:
18
- case PluginErrorType.PluginMetaNotFound:
19
- case PluginErrorType.PluginManifestInvalid:
20
- case PluginErrorType.PluginManifestNotFound:
21
- case PluginErrorType.PluginApiNotFound:
22
- case PluginErrorType.PluginApiParamsError:
23
- case PluginErrorType.PluginServerError: {
24
- return <PluginError content={(error as any).body} id={message.id} />;
25
- }
26
- case PluginErrorType.PluginSettingsInvalid: {
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,6 @@
1
+ import { RenderMessage } from '@lobehub/ui';
2
+ import { memo } from 'react';
3
+
4
+ export const DefautMessage: RenderMessage = memo(({ id, editableContent }) => {
5
+ return <div id={id}>{editableContent}</div>;
6
+ });
@@ -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, RenderMessage } from '@lobehub/ui';
1
+ import { ChatList } from '@lobehub/ui';
2
2
  import isEqual from 'fast-deep-equal';
3
- import { memo, useCallback } from 'react';
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 { renderErrorMessage } from './Error';
13
- import MessageExtra from './MessageExtra';
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
- renderErrorMessage={renderErrorMessage}
106
- renderMessage={renderMessage}
107
- renderMessageExtra={MessageExtra}
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;