@lobehub/chat 0.45.0 → 0.46.1
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 +59 -0
- package/package.json +1 -1
- package/src/features/AgentSetting/AgentPrompt/index.tsx +11 -6
- package/src/pages/chat/features/Conversation/Input/index.tsx +11 -5
- package/src/pages/chat/features/Sidebar/Header.tsx +10 -0
- package/src/pages/chat/features/Sidebar/SystemRole.tsx +12 -2
- package/src/store/session/slices/chat/actions/message.ts +48 -18
- package/src/store/session/slices/chat/initialState.ts +1 -0
- package/vitest.config.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.46.1](https://github.com/lobehub/lobe-chat/compare/v0.46.0...v0.46.1)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-08-14**</sup>
|
|
8
|
+
|
|
9
|
+
#### 💄 Styles
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix SystemRole Skeleton padding.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Styles
|
|
19
|
+
|
|
20
|
+
- **misc**: Fix SystemRole Skeleton padding ([ce485a0](https://github.com/lobehub/lobe-chat/commit/ce485a0))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 0.46.0](https://github.com/lobehub/lobe-chat/compare/v0.45.0...v0.46.0)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-08-14**</sup>
|
|
33
|
+
|
|
34
|
+
#### ✨ Features
|
|
35
|
+
|
|
36
|
+
- **misc**: Update styling and functionality of AgentPrompt and EditableMessage components, 支持停止生成消息.
|
|
37
|
+
|
|
38
|
+
#### 🐛 Bug Fixes
|
|
39
|
+
|
|
40
|
+
- **misc**: Remove input highlight.
|
|
41
|
+
|
|
42
|
+
<br/>
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
46
|
+
|
|
47
|
+
#### What's improved
|
|
48
|
+
|
|
49
|
+
- **misc**: Update styling and functionality of AgentPrompt and EditableMessage components ([80b521c](https://github.com/lobehub/lobe-chat/commit/80b521c))
|
|
50
|
+
- **misc**: 支持停止生成消息, closes [#78](https://github.com/lobehub/lobe-chat/issues/78) ([9eeca80](https://github.com/lobehub/lobe-chat/commit/9eeca80))
|
|
51
|
+
|
|
52
|
+
#### What's fixed
|
|
53
|
+
|
|
54
|
+
- **misc**: Remove input highlight ([ad2001a](https://github.com/lobehub/lobe-chat/commit/ad2001a))
|
|
55
|
+
|
|
56
|
+
</details>
|
|
57
|
+
|
|
58
|
+
<div align="right">
|
|
59
|
+
|
|
60
|
+
[](#readme-top)
|
|
61
|
+
|
|
62
|
+
</div>
|
|
63
|
+
|
|
5
64
|
## [Version 0.45.0](https://github.com/lobehub/lobe-chat/compare/v0.44.4...v0.45.0)
|
|
6
65
|
|
|
7
66
|
<sup>Released on **2023-08-14**</sup>
|
package/package.json
CHANGED
|
@@ -14,14 +14,9 @@ import { LobeAgentConfig } from '@/types/session';
|
|
|
14
14
|
|
|
15
15
|
export const useStyles = createStyles(({ css, token }) => ({
|
|
16
16
|
input: css`
|
|
17
|
-
|
|
18
|
-
background: ${token.colorFillTertiary};
|
|
19
|
-
border: 1px solid ${token.colorPrimaryBorder};
|
|
20
|
-
border-radius: 8px;
|
|
17
|
+
border: 1px solid ${token.colorBorderSecondary};
|
|
21
18
|
`,
|
|
22
19
|
markdown: css`
|
|
23
|
-
padding: 12px;
|
|
24
|
-
background: ${token.colorFillTertiary};
|
|
25
20
|
border: 1px solid transparent;
|
|
26
21
|
`,
|
|
27
22
|
}));
|
|
@@ -45,6 +40,7 @@ const AgentPrompt = memo<AgentPromptProps>(({ config, updateConfig }) => {
|
|
|
45
40
|
<TokenTag
|
|
46
41
|
displayMode={'used'}
|
|
47
42
|
maxValue={ModelTokens[model]}
|
|
43
|
+
shape={'square'}
|
|
48
44
|
text={{
|
|
49
45
|
overload: t('tokenTag.overload', { ns: 'common' }),
|
|
50
46
|
remained: t('tokenTag.remained', { ns: 'common' }),
|
|
@@ -61,12 +57,20 @@ const AgentPrompt = memo<AgentPromptProps>(({ config, updateConfig }) => {
|
|
|
61
57
|
<Flexbox gap={16} paddingBlock={16}>
|
|
62
58
|
<EditableMessage
|
|
63
59
|
classNames={styles}
|
|
60
|
+
editButtonSize={'small'}
|
|
64
61
|
editing={editing}
|
|
62
|
+
height={'auto'}
|
|
63
|
+
inputType={'block'}
|
|
65
64
|
onChange={(e) => {
|
|
66
65
|
updateConfig({ systemRole: e });
|
|
67
66
|
}}
|
|
68
67
|
onEditingChange={setEditing}
|
|
68
|
+
placeholder={t('settingAgent.prompt.placeholder')}
|
|
69
69
|
showEditWhenEmpty
|
|
70
|
+
text={{
|
|
71
|
+
cancel: t('cancel', { ns: 'common' }),
|
|
72
|
+
confirm: t('ok', { ns: 'common' }),
|
|
73
|
+
}}
|
|
70
74
|
value={systemRole}
|
|
71
75
|
/>
|
|
72
76
|
{!editing && !!systemRole && (
|
|
@@ -76,6 +80,7 @@ const AgentPrompt = memo<AgentPromptProps>(({ config, updateConfig }) => {
|
|
|
76
80
|
e.stopPropagation();
|
|
77
81
|
setEditing(true);
|
|
78
82
|
}}
|
|
83
|
+
size={'small'}
|
|
79
84
|
type={'primary'}
|
|
80
85
|
>
|
|
81
86
|
{t('edit', { ns: 'common' })}
|
|
@@ -21,11 +21,15 @@ const ChatInput = () => {
|
|
|
21
21
|
s.preference.inputHeight,
|
|
22
22
|
s.updatePreference,
|
|
23
23
|
]);
|
|
24
|
-
const [
|
|
25
|
-
s
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const [isLoading, hasTopic, sendMessage, saveToTopic, stopGenerateMessage] = useSessionStore(
|
|
25
|
+
(s) => [
|
|
26
|
+
!!s.chatLoadingId,
|
|
27
|
+
!!s.activeTopicId,
|
|
28
|
+
s.sendMessage,
|
|
29
|
+
s.saveToTopic,
|
|
30
|
+
s.stopGenerateMessage,
|
|
31
|
+
],
|
|
32
|
+
);
|
|
29
33
|
|
|
30
34
|
const footer = hasTopic ? null : (
|
|
31
35
|
<Tooltip title={t('topic.saveCurrentMessages')}>
|
|
@@ -60,10 +64,12 @@ const ChatInput = () => {
|
|
|
60
64
|
actionsRight={<ActionsRight />}
|
|
61
65
|
expand={expand}
|
|
62
66
|
footer={footer}
|
|
67
|
+
loading={isLoading}
|
|
63
68
|
minHeight={CHAT_TEXTAREA_HEIGHT}
|
|
64
69
|
onExpandChange={setExpand}
|
|
65
70
|
onInputChange={setText}
|
|
66
71
|
onSend={sendMessage}
|
|
72
|
+
onStop={stopGenerateMessage}
|
|
67
73
|
placeholder={t('sendPlaceholder')}
|
|
68
74
|
text={{
|
|
69
75
|
send: t('send'),
|
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
import { createStyles } from 'antd-style';
|
|
1
2
|
import { type ReactNode, memo } from 'react';
|
|
2
3
|
import { Flexbox } from 'react-layout-kit';
|
|
3
4
|
|
|
5
|
+
const useStyles = createStyles(
|
|
6
|
+
({ css, token }) => css`
|
|
7
|
+
z-index: 10;
|
|
8
|
+
box-shadow: 0 2px 8px ${token.colorBgLayout};
|
|
9
|
+
`,
|
|
10
|
+
);
|
|
11
|
+
|
|
4
12
|
interface HeaderProps {
|
|
5
13
|
actions?: ReactNode;
|
|
6
14
|
title: string;
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
const Header = memo<HeaderProps>(({ title, actions }) => {
|
|
18
|
+
const { styles } = useStyles();
|
|
10
19
|
return (
|
|
11
20
|
<Flexbox
|
|
12
21
|
align={'center'}
|
|
22
|
+
className={styles}
|
|
13
23
|
distribution={'space-between'}
|
|
14
24
|
horizontal
|
|
15
25
|
padding={12}
|
|
@@ -13,7 +13,11 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
13
13
|
prompt: css`
|
|
14
14
|
overflow-x: hidden;
|
|
15
15
|
overflow-y: auto;
|
|
16
|
+
|
|
17
|
+
padding: 0 16px 16px;
|
|
18
|
+
|
|
16
19
|
opacity: 0.75;
|
|
20
|
+
|
|
17
21
|
transition: opacity 200ms ${token.motionEaseOut};
|
|
18
22
|
|
|
19
23
|
&:hover {
|
|
@@ -64,9 +68,15 @@ const SystemRole = memo(() => {
|
|
|
64
68
|
}
|
|
65
69
|
title={t('settingAgent.prompt.title', { ns: 'setting' })}
|
|
66
70
|
/>
|
|
67
|
-
<Flexbox className={styles.promptBox} height={200}
|
|
71
|
+
<Flexbox className={styles.promptBox} height={200}>
|
|
68
72
|
{!init ? (
|
|
69
|
-
<Skeleton
|
|
73
|
+
<Skeleton
|
|
74
|
+
active
|
|
75
|
+
avatar={false}
|
|
76
|
+
round
|
|
77
|
+
style={{ marginTop: 12, paddingInline: 16 }}
|
|
78
|
+
title={false}
|
|
79
|
+
/>
|
|
70
80
|
) : (
|
|
71
81
|
<>
|
|
72
82
|
<EditableMessage
|
|
@@ -46,7 +46,6 @@ export interface ChatMessageAction {
|
|
|
46
46
|
messages: ChatMessage[],
|
|
47
47
|
assistantMessageId: string,
|
|
48
48
|
) => Promise<{ isFunctionCall: boolean }>;
|
|
49
|
-
|
|
50
49
|
/**
|
|
51
50
|
* 实际获取 AI 响应
|
|
52
51
|
*
|
|
@@ -54,17 +53,24 @@ export interface ChatMessageAction {
|
|
|
54
53
|
* @param parentId - 父消息 ID,可选
|
|
55
54
|
*/
|
|
56
55
|
realFetchAIResponse: (messages: ChatMessage[], parentId: string) => Promise<void>;
|
|
56
|
+
|
|
57
57
|
/**
|
|
58
58
|
* 重新发送消息
|
|
59
59
|
* @param id - 消息 ID
|
|
60
60
|
*/
|
|
61
61
|
resendMessage: (id: string) => Promise<void>;
|
|
62
|
-
|
|
63
62
|
/**
|
|
64
63
|
* 发送消息
|
|
65
64
|
* @param text - 消息文本
|
|
66
65
|
*/
|
|
67
66
|
sendMessage: (text: string) => Promise<void>;
|
|
67
|
+
|
|
68
|
+
stopGenerateMessage: () => void;
|
|
69
|
+
toggleChatLoading: (
|
|
70
|
+
loading: boolean,
|
|
71
|
+
id?: string,
|
|
72
|
+
action?: string,
|
|
73
|
+
) => AbortController | undefined;
|
|
68
74
|
triggerFunctionCall: (id: string) => Promise<void>;
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -97,14 +103,15 @@ export const chatMessage: StateCreator<
|
|
|
97
103
|
|
|
98
104
|
get().dispatchSession({ chats, id: activeId, type: 'updateSessionChat' });
|
|
99
105
|
},
|
|
100
|
-
|
|
101
106
|
generateMessage: async (messages, assistantId) => {
|
|
102
|
-
const { dispatchMessage } = get();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
const { dispatchMessage, toggleChatLoading } = get();
|
|
108
|
+
|
|
109
|
+
const abortController = toggleChatLoading(
|
|
110
|
+
true,
|
|
111
|
+
assistantId,
|
|
112
|
+
t('generateMessage(start)', { assistantId, messages }) as string,
|
|
107
113
|
);
|
|
114
|
+
|
|
108
115
|
const config = agentSelectors.currentAgentConfig(get());
|
|
109
116
|
|
|
110
117
|
const compiler = template(config.inputTemplate, { interpolate: /{{([\S\s]+?)}}/g });
|
|
@@ -138,12 +145,15 @@ export const chatMessage: StateCreator<
|
|
|
138
145
|
}
|
|
139
146
|
|
|
140
147
|
const fetcher = () =>
|
|
141
|
-
fetchChatModel(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
fetchChatModel(
|
|
149
|
+
{
|
|
150
|
+
messages: postMessages,
|
|
151
|
+
model: config.model,
|
|
152
|
+
...config.params,
|
|
153
|
+
plugins: config.plugins,
|
|
154
|
+
},
|
|
155
|
+
{ signal: abortController?.signal },
|
|
156
|
+
);
|
|
147
157
|
|
|
148
158
|
let output = '';
|
|
149
159
|
let isFunctionCall = false;
|
|
@@ -175,7 +185,7 @@ export const chatMessage: StateCreator<
|
|
|
175
185
|
},
|
|
176
186
|
});
|
|
177
187
|
|
|
178
|
-
|
|
188
|
+
toggleChatLoading(false, undefined, t('generateMessage(end)') as string);
|
|
179
189
|
|
|
180
190
|
return { isFunctionCall };
|
|
181
191
|
},
|
|
@@ -281,8 +291,27 @@ export const chatMessage: StateCreator<
|
|
|
281
291
|
}
|
|
282
292
|
},
|
|
283
293
|
|
|
294
|
+
stopGenerateMessage: () => {
|
|
295
|
+
const { abortController, toggleChatLoading } = get();
|
|
296
|
+
if (!abortController) return;
|
|
297
|
+
|
|
298
|
+
abortController.abort();
|
|
299
|
+
|
|
300
|
+
toggleChatLoading(false);
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
toggleChatLoading: (loading, id, action) => {
|
|
304
|
+
if (loading) {
|
|
305
|
+
const abortController = new AbortController();
|
|
306
|
+
set({ abortController, chatLoadingId: id }, false, action);
|
|
307
|
+
return abortController;
|
|
308
|
+
} else {
|
|
309
|
+
set({ abortController: undefined, chatLoadingId: undefined }, false, action);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
|
|
284
313
|
triggerFunctionCall: async (id) => {
|
|
285
|
-
const { dispatchMessage, realFetchAIResponse } = get();
|
|
314
|
+
const { dispatchMessage, realFetchAIResponse, toggleChatLoading } = get();
|
|
286
315
|
const session = sessionSelectors.currentSession(get());
|
|
287
316
|
|
|
288
317
|
if (!session) return;
|
|
@@ -317,7 +346,9 @@ export const chatMessage: StateCreator<
|
|
|
317
346
|
// type: 'addMessage',
|
|
318
347
|
// });
|
|
319
348
|
|
|
320
|
-
const
|
|
349
|
+
const abortController = toggleChatLoading(true, id);
|
|
350
|
+
const data = await fetchPlugin(payload, { signal: abortController?.signal });
|
|
351
|
+
toggleChatLoading(false);
|
|
321
352
|
|
|
322
353
|
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: data });
|
|
323
354
|
|
|
@@ -325,7 +356,6 @@ export const chatMessage: StateCreator<
|
|
|
325
356
|
|
|
326
357
|
await realFetchAIResponse(chats, message.id);
|
|
327
358
|
},
|
|
328
|
-
|
|
329
359
|
// genShareUrl: () => {
|
|
330
360
|
// const session = sessionSelectors.currentSession(get());
|
|
331
361
|
// if (!session) return '';
|