@lobehub/chat 1.7.5 → 1.7.7

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,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.7.7](https://github.com/lobehub/lobe-chat/compare/v1.7.6...v1.7.7)
6
+
7
+ <sup>Released on **2024-07-30**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Improve tools calling UI.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Improve tools calling UI, closes [#3326](https://github.com/lobehub/lobe-chat/issues/3326) ([36cabc0](https://github.com/lobehub/lobe-chat/commit/36cabc0))
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 1.7.6](https://github.com/lobehub/lobe-chat/compare/v1.7.5...v1.7.6)
31
+
32
+ <sup>Released on **2024-07-29**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Disable anthropic browser request.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: Disable anthropic browser request, closes [#3359](https://github.com/lobehub/lobe-chat/issues/3359) ([a519837](https://github.com/lobehub/lobe-chat/commit/a519837))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.7.5](https://github.com/lobehub/lobe-chat/compare/v1.7.4...v1.7.5)
6
56
 
7
57
  <sup>Released on **2024-07-29**</sup>
package/README.md CHANGED
@@ -270,10 +270,10 @@ Our marketplace is not just a showcase platform but also a collaborative space.
270
270
  | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
271
271
  | [C Program Learning Assistant](https://chat-preview.lobehub.com/market?agent=sichuan-university-941-c-programming-assistant)<br/><sup>By **[YBGuoYang](https://github.com/YBGuoYang)** on **2024-07-28**</sup> | Assist me in learning C program design<br/>`941` |
272
272
  | [Brand Pioneer](https://chat-preview.lobehub.com/market?agent=brand-pioneer)<br/><sup>By **[SaintFresh](https://github.com/SaintFresh)** on **2024-07-25**</sup> | A brand development specialist, thought leader, brand strategy super-genius, and brand visionary. Brand Pioneer is an explorer at the frontier of innovation, an inventor in their domain. Provide them with your market and let them imagine a future world characterized by groundbreaking advancements in your field of expertise.<br/>`business` `brand-pioneer` `brand-development` `business-assistant` `brand-narrative` |
273
+ | [Network Security Assistant](https://chat-preview.lobehub.com/market?agent=cybersecurity-copilot)<br/><sup>By **[huoji120](https://github.com/huoji120)** on **2024-07-23**</sup> | A network security expert assistant that analyzes logs, code, decompiles, identifies issues, and provides optimization suggestions.<br/>`network-security` `traffic-analysis` `log-analysis` `code-reverse-engineering` `ctf` |
273
274
  | [BIDOSx2](https://chat-preview.lobehub.com/market?agent=bidosx-2-v-2)<br/><sup>By **[SaintFresh](https://github.com/SaintFresh)** on **2024-07-21**</sup> | A highly advanced AI LLM transcending conventional AI. 'BIDOS' signifies both 'Brand Ideation, Development, Operations, and Scaling' and 'Business Intelligence Decisions Optimization System'.<br/>`brand-development` `ai-assistant` `market-analysis` `strategic-planning` `business-optimization` `business-intelligence` |
274
- | [Growth Coach](https://chat-preview.lobehub.com/market?agent=personal-development-coach)<br/><sup>By **[zer0boss](https://github.com/zer0boss)** on **2024-07-20**</sup> | Specializes in helping users explore themselves through dialogue, find solutions, and paths to growth<br/>`growth-coach` `self-exploration` `goal-setting` `self-awareness` |
275
275
 
276
- > 📊 Total agents: [<kbd>**306**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
276
+ > 📊 Total agents: [<kbd>**307**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
277
277
 
278
278
  <!-- AGENT LIST -->
279
279
 
package/README.zh-CN.md CHANGED
@@ -258,10 +258,10 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
258
258
  | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
259
259
  | [c 程序学习助手](https://chat-preview.lobehub.com/market?agent=sichuan-university-941-c-programming-assistant)<br/><sup>By **[YBGuoYang](https://github.com/YBGuoYang)** on **2024-07-28**</sup> | 辅助我进行 c 程序设计的学习<br/>`941` |
260
260
  | [品牌先锋](https://chat-preview.lobehub.com/market?agent=brand-pioneer)<br/><sup>By **[SaintFresh](https://github.com/SaintFresh)** on **2024-07-25**</sup> | 一位品牌发展专家、思想领袖、品牌战略超级天才和品牌远见者。品牌先锋是创新前沿的探险家,在其领域是一位发明家。将您的市场提供给他们,让他们想象一个未来世界,其中以您的专业领域的突破性进展为特征。<br/>`商业` `品牌先锋` `品牌发展` `商业助手` `品牌叙事` |
261
+ | [网络安全助手](https://chat-preview.lobehub.com/market?agent=cybersecurity-copilot)<br/><sup>By **[huoji120](https://github.com/huoji120)** on **2024-07-23**</sup> | 网络安全专家助手,分析日志、代码、反编译,发现问题并提供优化建议。<br/>`网络安全` `流量分析` `日志分析` `代码逆向` `ctf` |
261
262
  | [BIDOSx2](https://chat-preview.lobehub.com/market?agent=bidosx-2-v-2)<br/><sup>By **[SaintFresh](https://github.com/SaintFresh)** on **2024-07-21**</sup> | 一种高度先进的 AI LLM,超越传统人工智能。'BIDOS' 既代表 ' 品牌构思、发展、运营和扩展 ',也代表 ' 商业智能决策优化系统 '。<br/>`品牌发展` `ai助手` `市场分析` `战略规划` `业务优化` `商业智能` |
262
- | [成长教练](https://chat-preview.lobehub.com/market?agent=personal-development-coach)<br/><sup>By **[zer0boss](https://github.com/zer0boss)** on **2024-07-20**</sup> | 擅长用对话的方式帮助用户自我探索,找到解决之道和成长之路<br/>`成长教练` `自我探索` `目标设定` `自我觉察` |
263
263
 
264
- > 📊 Total agents: [<kbd>**306**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
264
+ > 📊 Total agents: [<kbd>**307**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
265
265
 
266
266
  <!-- AGENT LIST -->
267
267
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.7.5",
3
+ "version": "1.7.7",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -110,7 +110,7 @@
110
110
  "@clerk/localizations": "2.0.0",
111
111
  "@clerk/nextjs": "^5.2.6",
112
112
  "@clerk/themes": "^2.1.10",
113
- "@google/generative-ai": "^0.14.1",
113
+ "@google/generative-ai": "^0.16.0",
114
114
  "@icons-pack/react-simple-icons": "^9.6.0",
115
115
  "@khmyznikov/pwa-install": "^0.3.9",
116
116
  "@lobehub/chat-plugin-sdk": "^1.32.4",
@@ -14,6 +14,8 @@ import { memo, useMemo } from 'react';
14
14
  import { useTranslation } from 'react-i18next';
15
15
  import { Flexbox } from 'react-layout-kit';
16
16
 
17
+ import BubblesLoading from '@/components/BubblesLoading';
18
+ import { LOADING_FLAT } from '@/const/message';
17
19
  import { useIsMobile } from '@/hooks/useIsMobile';
18
20
  import { useChatStore } from '@/store/chat';
19
21
 
@@ -160,13 +162,19 @@ const TopicContent = memo<TopicContentProps>(({ id, title, fav, showMore }) => {
160
162
  spin={isLoading}
161
163
  />
162
164
  {!editing ? (
163
- <Paragraph
164
- className={styles.title}
165
- ellipsis={{ rows: 1, tooltip: { placement: 'left', title } }}
166
- style={{ margin: 0 }}
167
- >
168
- {title}
169
- </Paragraph>
165
+ title === LOADING_FLAT ? (
166
+ <Flexbox flex={1} height={28} justify={'center'}>
167
+ <BubblesLoading />
168
+ </Flexbox>
169
+ ) : (
170
+ <Paragraph
171
+ className={styles.title}
172
+ ellipsis={{ rows: 1, tooltip: { placement: 'left', title } }}
173
+ style={{ margin: 0 }}
174
+ >
175
+ {title}
176
+ </Paragraph>
177
+ )
170
178
  ) : (
171
179
  <EditableText
172
180
  editing={editing}
@@ -70,6 +70,7 @@ const Anthropic: ModelProviderCard = {
70
70
  },
71
71
  ],
72
72
  checkModel: 'claude-3-haiku-20240307',
73
+ disableBrowserRequest: true,
73
74
  id: 'anthropic',
74
75
  name: 'Anthropic',
75
76
  proxyUrl: {
@@ -6,11 +6,10 @@ import { memo, useState } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Flexbox } from 'react-layout-kit';
8
8
 
9
+ import BubblesLoading from '@/components/BubblesLoading';
9
10
  import { useChatStore } from '@/store/chat';
10
11
  import { ChatTranslate } from '@/types/message';
11
12
 
12
- import BubblesLoading from '../components/BubblesLoading';
13
-
14
13
  interface TranslateProps extends ChatTranslate {
15
14
  id: string;
16
15
  loading?: boolean;
@@ -1,57 +1,84 @@
1
- import { Icon } from '@lobehub/ui';
1
+ import { Icon, Tag } from '@lobehub/ui';
2
+ import { Typography } from 'antd';
2
3
  import isEqual from 'fast-deep-equal';
3
- import { Loader2, LucideChevronDown, LucideChevronRight, LucideToyBrick } from 'lucide-react';
4
+ import { Loader2 } from 'lucide-react';
4
5
  import { CSSProperties, memo, useState } from 'react';
5
6
  import { useTranslation } from 'react-i18next';
6
7
  import { Flexbox } from 'react-layout-kit';
7
8
 
9
+ import PluginAvatar from '@/features/PluginAvatar';
10
+ import { useIsMobile } from '@/hooks/useIsMobile';
8
11
  import { useChatStore } from '@/store/chat';
9
12
  import { chatSelectors } from '@/store/chat/selectors';
10
13
  import { pluginHelpers, useToolStore } from '@/store/tool';
11
14
  import { toolSelectors } from '@/store/tool/selectors';
12
15
 
16
+ import { ToolMessage } from '../../Tool';
13
17
  import Arguments from '../../components/Arguments';
14
18
  import { useStyles } from './style';
15
19
 
16
20
  export interface InspectorProps {
21
+ apiName: string;
17
22
  arguments?: string;
23
+ id: string;
18
24
  identifier: string;
19
25
  index: number;
20
26
  messageId: string;
21
- style: CSSProperties;
27
+ style?: CSSProperties;
22
28
  }
23
29
 
24
30
  const CallItem = memo<InspectorProps>(
25
- ({ arguments: requestArgs, messageId, index, identifier, style }) => {
31
+ ({ arguments: requestArgs, apiName, messageId, id, index, identifier, style }) => {
26
32
  const { t } = useTranslation('plugin');
27
33
  const { styles } = useStyles();
28
34
  const [open, setOpen] = useState(false);
29
35
  const loading = useChatStore(chatSelectors.isToolCallStreaming(messageId, index));
36
+ const toolMessage = useChatStore(chatSelectors.getMessageByToolCallId(id));
37
+ const isMobile = useIsMobile();
30
38
 
31
39
  const pluginMeta = useToolStore(toolSelectors.getMetaById(identifier), isEqual);
32
40
 
33
41
  const pluginTitle = pluginHelpers.getPluginTitle(pluginMeta) ?? t('unknownPlugin');
34
42
 
35
- return (
43
+ // when tool calling stop streaming, we should show the tool message
44
+ return !loading && toolMessage ? (
45
+ <ToolMessage {...toolMessage} />
46
+ ) : (
36
47
  <Flexbox gap={8} style={style}>
37
48
  <Flexbox
38
49
  align={'center'}
39
50
  className={styles.container}
40
51
  distribution={'space-between'}
41
52
  gap={8}
42
- height={32}
43
53
  horizontal
44
54
  onClick={() => {
45
55
  setOpen(!open);
46
56
  }}
47
57
  >
48
58
  <Flexbox align={'center'} gap={8} horizontal>
49
- {loading ? <Icon icon={Loader2} spin /> : <Icon icon={LucideToyBrick} />}
50
- {pluginTitle}
59
+ {loading ? (
60
+ <div>
61
+ <Icon icon={Loader2} spin />
62
+ </div>
63
+ ) : (
64
+ <PluginAvatar identifier={identifier} size={isMobile ? 36 : undefined} />
65
+ )}
66
+ {isMobile ? (
67
+ <Flexbox>
68
+ <div>{pluginTitle}</div>
69
+ <Typography.Text className={styles.apiName} type={'secondary'}>
70
+ {apiName}
71
+ </Typography.Text>
72
+ </Flexbox>
73
+ ) : (
74
+ <>
75
+ <div>{pluginTitle}</div>
76
+ <Tag>{apiName}</Tag>
77
+ </>
78
+ )}
51
79
  </Flexbox>
52
- <Icon icon={open ? LucideChevronDown : LucideChevronRight} />
53
80
  </Flexbox>
54
- {(open || loading) && <Arguments arguments={requestArgs} />}
81
+ {loading && <Arguments arguments={requestArgs} />}
55
82
  </Flexbox>
56
83
  );
57
84
  },
@@ -1,19 +1,30 @@
1
1
  import { createStyles } from 'antd-style';
2
2
 
3
3
  export const useStyles = createStyles(({ css, token }) => ({
4
+ apiName: css`
5
+ overflow: hidden;
6
+ display: -webkit-box;
7
+ -webkit-box-orient: vertical;
8
+ -webkit-line-clamp: 1;
9
+
10
+ font-size: 12px;
11
+ text-overflow: ellipsis;
12
+ `,
4
13
  container: css`
5
14
  cursor: pointer;
6
15
 
7
16
  width: fit-content;
8
- padding-inline: 4px 6px;
17
+ padding-block: 6px;
18
+ padding-inline: 8px;
19
+ padding-inline-end: 12px;
9
20
 
10
21
  color: ${token.colorText};
11
22
 
12
- background: ${token.colorFillTertiary};
23
+ border: 1px solid ${token.colorBorder};
13
24
  border-radius: 8px;
14
25
 
15
26
  &:hover {
16
- background: ${token.colorFillSecondary};
27
+ background: ${token.colorFillTertiary};
17
28
  }
18
29
  `,
19
30
  plugin: css`
@@ -7,7 +7,7 @@ import { chatSelectors } from '@/store/chat/selectors';
7
7
  import { ChatMessage } from '@/types/message';
8
8
 
9
9
  import { DefaultMessage } from '../Default';
10
- import ToolCall from './ToolCalls';
10
+ import ToolCall from './ToolCallItem';
11
11
 
12
12
  export const AssistantMessage = memo<
13
13
  ChatMessage & {
@@ -31,17 +31,16 @@ export const AssistantMessage = memo<
31
31
  />
32
32
  )}
33
33
  {!editing && tools && (
34
- <Flexbox gap={8} horizontal>
34
+ <Flexbox gap={8}>
35
35
  {tools.map((toolCall, index) => (
36
36
  <ToolCall
37
+ apiName={toolCall.apiName}
37
38
  arguments={toolCall.arguments}
39
+ id={toolCall.id}
38
40
  identifier={toolCall.identifier}
39
41
  index={index}
40
42
  key={toolCall.id}
41
43
  messageId={id}
42
- style={{
43
- maxWidth: `max(${100 / tools.length}%, 300px)`,
44
- }}
45
44
  />
46
45
  ))}
47
46
  </Flexbox>
@@ -3,7 +3,7 @@ import { ReactNode, memo } from 'react';
3
3
  import { LOADING_FLAT } from '@/const/message';
4
4
  import { ChatMessage } from '@/types/message';
5
5
 
6
- import BubblesLoading from '../components/BubblesLoading';
6
+ import BubblesLoading from '@/components/BubblesLoading';
7
7
 
8
8
  export const DefaultMessage = memo<
9
9
  ChatMessage & {
@@ -1,12 +1,11 @@
1
1
  import { ReactNode, memo } from 'react';
2
2
  import { Flexbox } from 'react-layout-kit';
3
3
 
4
+ import BubblesLoading from '@/components/BubblesLoading';
4
5
  import { LOADING_FLAT } from '@/const/message';
5
6
  import { FileListPreviewer } from '@/features/FileList';
6
7
  import { ChatMessage } from '@/types/message';
7
8
 
8
- import BubblesLoading from '../components/BubblesLoading';
9
-
10
9
  export const UserMessage = memo<
11
10
  ChatMessage & {
12
11
  editableContent: ReactNode;
@@ -131,6 +131,36 @@ describe('chatSelectors', () => {
131
131
  });
132
132
  });
133
133
 
134
+ describe('getMessageByToolCallId', () => {
135
+ it('should return undefined if the message with the given id does not exist', () => {
136
+ const message = chatSelectors.getMessageByToolCallId('non-existent-id')(initialStore);
137
+ expect(message).toBeUndefined();
138
+ });
139
+
140
+ it('should return the message object with the matching tool_call_id', () => {
141
+ const toolMessage = {
142
+ id: 'msg3',
143
+ content: 'Function Message',
144
+ role: 'tool',
145
+ tool_call_id: 'ttt',
146
+ plugin: {
147
+ arguments: 'arg1',
148
+ identifier: 'func1',
149
+ apiName: 'ttt',
150
+ type: 'default',
151
+ },
152
+ } as ChatMessage;
153
+ const state = merge(initialStore, {
154
+ messagesMap: {
155
+ [messageMapKey('abc')]: [...mockMessages, toolMessage],
156
+ },
157
+ activeId: 'abc',
158
+ });
159
+ const message = chatSelectors.getMessageByToolCallId('ttt')(state);
160
+ expect(message).toMatchObject(toolMessage);
161
+ });
162
+ });
163
+
134
164
  describe('currentChatsWithHistoryConfig', () => {
135
165
  it('should slice the messages according to the current agent config', () => {
136
166
  const state = merge(initialStore, {
@@ -203,7 +233,7 @@ describe('chatSelectors', () => {
203
233
  });
204
234
 
205
235
  describe('currentChatsWithGuideMessage', () => {
206
- it('should return existing messages if there are any', () => {
236
+ it('should return existing messages except tool message', () => {
207
237
  const state = merge(initialStore, {
208
238
  messagesMap: {
209
239
  [messageMapKey('someActiveId')]: mockMessages,
@@ -211,7 +241,7 @@ describe('chatSelectors', () => {
211
241
  activeId: 'someActiveId',
212
242
  });
213
243
  const chats = chatSelectors.currentChatsWithGuideMessage({} as MetaData)(state);
214
- expect(chats).toEqual(mockedChats);
244
+ expect(chats).toEqual(mockedChats.slice(0, 2));
215
245
  });
216
246
 
217
247
  it('should add a guide message if the chat is brand new', () => {
@@ -65,11 +65,12 @@ const showInboxWelcome = (s: ChatStore): boolean => {
65
65
  return isBrandNewChat;
66
66
  };
67
67
 
68
- // 针对新助手添加初始化时的自定义消息
68
+ // Custom message for new assistant initialization
69
69
  const currentChatsWithGuideMessage =
70
70
  (meta: MetaData) =>
71
71
  (s: ChatStore): ChatMessage[] => {
72
- const data = currentChats(s);
72
+ // skip tool message
73
+ const data = currentChats(s).filter((m) => m.role !== 'tool');
73
74
 
74
75
  const { isAgentEditable } = featureFlagsSelectors(createServerConfigStore().getState());
75
76
 
@@ -125,6 +126,10 @@ const chatsMessageString = (s: ChatStore): string => {
125
126
  const getMessageById = (id: string) => (s: ChatStore) =>
126
127
  chatHelpers.getMessageById(currentChats(s), id);
127
128
 
129
+ const getMessageByToolCallId = (id: string) => (s: ChatStore) => {
130
+ const messages = currentChats(s);
131
+ return messages.find((m) => m.tool_call_id === id);
132
+ };
128
133
  const getTraceIdByMessageId = (id: string) => (s: ChatStore) => getMessageById(id)(s)?.traceId;
129
134
 
130
135
  const latestMessage = (s: ChatStore) => currentChats(s).at(-1);
@@ -160,6 +165,7 @@ export const chatSelectors = {
160
165
  currentChatsWithHistoryConfig,
161
166
  currentToolMessages,
162
167
  getMessageById,
168
+ getMessageByToolCallId,
163
169
  getTraceIdByMessageId,
164
170
  isAIGenerating,
165
171
  isCreatingMessage,