@lobehub/chat 0.149.1 → 0.149.2

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,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.149.2](https://github.com/lobehub/lobe-chat/compare/v0.149.1...v0.149.2)
6
+
7
+ <sup>Released on **2024-04-24**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Support to create ai message.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Support to create ai message, closes [#2185](https://github.com/lobehub/lobe-chat/issues/2185) ([ba3ba6a](https://github.com/lobehub/lobe-chat/commit/ba3ba6a))
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
+
5
30
  ### [Version 0.149.1](https://github.com/lobehub/lobe-chat/compare/v0.149.0...v0.149.1)
6
31
 
7
32
  <sup>Released on **2024-04-24**</sup>
@@ -25,8 +25,9 @@
25
25
  "title": "دردشة عشوائية"
26
26
  },
27
27
  "input": {
28
+ "addAi": "إضافة رسالة AI",
29
+ "addUser": "إضافة رسالة مستخدم",
28
30
  "more": "المزيد",
29
- "onlyAdd": "إضافة الرسالة فقط",
30
31
  "send": "إرسال",
31
32
  "sendWithCmdEnter": "اضغط {{meta}} + Enter للإرسال",
32
33
  "sendWithEnter": "اضغط Enter للإرسال",
@@ -25,8 +25,9 @@
25
25
  "title": "Просто чати"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Добави AI съобщение",
29
+ "addUser": "Добави потребителско съобщение",
28
30
  "more": "още",
29
- "onlyAdd": "Само добави съобщение",
30
31
  "send": "Изпрати",
31
32
  "sendWithCmdEnter": "Натисни {{meta}} + Enter за да изпратиш",
32
33
  "sendWithEnter": "Натисни Enter за да изпратиш",
@@ -25,8 +25,9 @@
25
25
  "title": "Lass uns plaudern"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Fügen Sie eine AI-Nachricht hinzu",
29
+ "addUser": "Fügen Sie eine Benutzer-Nachricht hinzu",
28
30
  "more": "Mehr",
29
- "onlyAdd": "Nur Nachricht hinzufügen",
30
31
  "send": "Senden",
31
32
  "sendWithCmdEnter": "Mit {{meta}} + Eingabetaste senden",
32
33
  "sendWithEnter": "Mit Eingabetaste senden",
@@ -8,7 +8,7 @@
8
8
  "clearCurrentMessages": "Clear current session messages",
9
9
  "confirmClearCurrentMessages": "You are about to clear the current session messages. Once cleared, they cannot be retrieved. Please confirm your action.",
10
10
  "confirmRemoveSessionItemAlert": "You are about to delete this agent. Once deleted, it cannot be retrieved. Please confirm your action.",
11
- "confirmRemoveSessionSuccess": "Assistant removed successfully",
11
+ "confirmRemoveSessionSuccess": "Agent removed successfully",
12
12
  "defaultAgent": "Default Agent",
13
13
  "defaultList": "Default List",
14
14
  "defaultSession": "Default Agent",
@@ -25,8 +25,9 @@
25
25
  "title": "Just Chat"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Add an AI message",
29
+ "addUser": "Add a user message",
28
30
  "more": "more",
29
- "onlyAdd": "Only add message",
30
31
  "send": "Send",
31
32
  "sendWithCmdEnter": "Press {{meta}} + Enter to send",
32
33
  "sendWithEnter": "Press Enter to send",
@@ -48,10 +49,10 @@
48
49
  "sessionGroup": {
49
50
  "config": "Group Management",
50
51
  "confirmRemoveGroupAlert": "This group is about to be deleted. After deletion, the agents in this group will be moved to the default list. Please confirm your operation.",
51
- "createAgentSuccess": "Assistant created successfully",
52
+ "createAgentSuccess": "Agent created successfully",
52
53
  "createGroup": "Add New Group",
53
54
  "createSuccess": "Created successfully",
54
- "creatingAgent": "Creating assistant...",
55
+ "creatingAgent": "Creating agent...",
55
56
  "inputPlaceholder": "Please enter group name...",
56
57
  "moveGroup": "Move to Group",
57
58
  "newGroup": "New Group",
@@ -25,8 +25,9 @@
25
25
  "title": "Charla casual"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Agregar un mensaje de IA",
29
+ "addUser": "Agregar un mensaje de usuario",
28
30
  "more": "más",
29
- "onlyAdd": "Añadir solo",
30
31
  "send": "Enviar",
31
32
  "sendWithCmdEnter": "Enviar con {{meta}} + Enter",
32
33
  "sendWithEnter": "Enviar con Enter",
@@ -8,7 +8,7 @@
8
8
  "clearCurrentMessages": "Effacer les messages actuels",
9
9
  "confirmClearCurrentMessages": "Vous êtes sur le point d'effacer les messages de cette session. Cette action est irréversible. Veuillez confirmer.",
10
10
  "confirmRemoveSessionItemAlert": "Vous êtes sur le point de supprimer cet agent. Cette action est irréversible. Veuillez confirmer.",
11
- "confirmRemoveSessionSuccess": "Assistant supprimé avec succès",
11
+ "confirmRemoveSessionSuccess": "Agent supprimé avec succès",
12
12
  "defaultAgent": "Agent par défaut",
13
13
  "defaultList": "Liste par défaut",
14
14
  "defaultSession": "Session par défaut",
@@ -25,8 +25,9 @@
25
25
  "title": "Discutons un peu"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Ajouter un message AI",
29
+ "addUser": "Ajouter un message utilisateur",
28
30
  "more": "Plus",
29
- "onlyAdd": "Ajouter uniquement",
30
31
  "send": "Envoyer",
31
32
  "sendWithCmdEnter": "Envoyer avec {{meta}} + Entrée",
32
33
  "sendWithEnter": "Envoyer avec Entrée",
@@ -48,10 +49,10 @@
48
49
  "sessionGroup": {
49
50
  "config": "Gestion des groupes",
50
51
  "confirmRemoveGroupAlert": "Vous êtes sur le point de supprimer ce groupe. Une fois supprimé, les agents de ce groupe seront déplacés vers la liste par défaut. Veuillez confirmer votre action.",
51
- "createAgentSuccess": "Création de l'assistant réussie",
52
+ "createAgentSuccess": "Création de l'agent réussie",
52
53
  "createGroup": "Créer un nouveau groupe",
53
54
  "createSuccess": "Création réussie",
54
- "creatingAgent": "Création de l'assistant en cours...",
55
+ "creatingAgent": "Création de l'agent en cours...",
55
56
  "inputPlaceholder": "Veuillez saisir le nom du groupe...",
56
57
  "moveGroup": "Déplacer vers un groupe",
57
58
  "newGroup": "Nouveau groupe",
@@ -25,8 +25,9 @@
25
25
  "title": "Chiacchierata casuale"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Aggiungi un messaggio AI",
29
+ "addUser": "Aggiungi un messaggio utente",
28
30
  "more": "Ulteriori",
29
- "onlyAdd": "Solo aggiungi messaggio",
30
31
  "send": "Invia",
31
32
  "sendWithCmdEnter": "Invia premendo {{meta}} + Invio",
32
33
  "sendWithEnter": "Invia premendo Invio",
@@ -25,8 +25,9 @@
25
25
  "title": "気軽におしゃべり"
26
26
  },
27
27
  "input": {
28
+ "addAi": "AIメッセージを追加",
29
+ "addUser": "ユーザーメッセージを追加",
28
30
  "more": "もっと",
29
- "onlyAdd": "メッセージのみ追加",
30
31
  "send": "送信",
31
32
  "sendWithCmdEnter": "{{meta}} + Enter キーで送信",
32
33
  "sendWithEnter": "Enter キーで送信",
@@ -25,8 +25,9 @@
25
25
  "title": "무작위 대화"
26
26
  },
27
27
  "input": {
28
+ "addAi": "AI 메시지 추가",
29
+ "addUser": "사용자 메시지 추가",
28
30
  "more": "더 많은",
29
- "onlyAdd": "메시지만 추가",
30
31
  "send": "전송",
31
32
  "sendWithCmdEnter": "{{meta}} + Enter 키로 전송",
32
33
  "sendWithEnter": "Enter 키로 전송",
@@ -25,8 +25,9 @@
25
25
  "title": "Praat maar raak"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Voeg een AI-bericht toe",
29
+ "addUser": "Voeg een gebruikersbericht toe",
28
30
  "more": "Meer",
29
- "onlyAdd": "Alleen bericht toevoegen",
30
31
  "send": "Verzenden",
31
32
  "sendWithCmdEnter": "Verzenden met {{meta}} + Enter",
32
33
  "sendWithEnter": "Verzenden met Enter",
@@ -25,8 +25,9 @@
25
25
  "title": "Pogadajmy sobie"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Dodaj wiadomość AI",
29
+ "addUser": "Dodaj wiadomość użytkownika",
28
30
  "more": "więcej",
29
- "onlyAdd": "Tylko dodaj wiadomość",
30
31
  "send": "Wyślij",
31
32
  "sendWithCmdEnter": "Wyślij za pomocą klawisza {{meta}} + Enter",
32
33
  "sendWithEnter": "Wyślij za pomocą klawisza Enter",
@@ -25,8 +25,9 @@
25
25
  "title": "Conversa Aleatória"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Adicionar uma mensagem de IA",
29
+ "addUser": "Adicionar uma mensagem de usuário",
28
30
  "more": "mais",
29
- "onlyAdd": "Apenas adicionar mensagem",
30
31
  "send": "Enviar",
31
32
  "sendWithCmdEnter": "Pressione {{meta}} + Enter para enviar",
32
33
  "sendWithEnter": "Pressione Enter para enviar",
@@ -25,8 +25,9 @@
25
25
  "title": "Просто поболтаем"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Добавить сообщение AI",
29
+ "addUser": "Добавить сообщение пользователя",
28
30
  "more": "больше",
29
- "onlyAdd": "Только добавить сообщение",
30
31
  "send": "Отправить",
31
32
  "sendWithCmdEnter": "Отправить с помощью {{meta}} + Enter",
32
33
  "sendWithEnter": "Отправить с помощью Enter",
@@ -25,8 +25,9 @@
25
25
  "title": "Sohbet Et"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Bir AI mesajı ekleyin",
29
+ "addUser": "Bir kullanıcı mesajı ekleyin",
28
30
  "more": "Daha fazla",
29
- "onlyAdd": "Sadece mesaj ekle",
30
31
  "send": "Gönder",
31
32
  "sendWithCmdEnter": "{{meta}} + Enter tuşuna basarak gönder",
32
33
  "sendWithEnter": "Enter tuşuna basarak gönder",
@@ -25,8 +25,9 @@
25
25
  "title": "Chuyện phiếm"
26
26
  },
27
27
  "input": {
28
+ "addAi": "Thêm một tin nhắn AI",
29
+ "addUser": "Thêm một tin nhắn người dùng",
28
30
  "more": "Thêm",
29
- "onlyAdd": "Chỉ thêm tin nhắn",
30
31
  "send": "Gửi",
31
32
  "sendWithCmdEnter": "Nhấn {{meta}} + Enter để gửi",
32
33
  "sendWithEnter": "Nhấn Enter để gửi",
@@ -25,8 +25,9 @@
25
25
  "title": "随便聊聊"
26
26
  },
27
27
  "input": {
28
+ "addAi": "添加一条 AI 消息",
29
+ "addUser": "添加一条用户消息",
28
30
  "more": "更多",
29
- "onlyAdd": "仅添加消息",
30
31
  "send": "发送",
31
32
  "sendWithCmdEnter": "按 {{meta}} + Enter 键发送",
32
33
  "sendWithEnter": "按 Enter 键发送",
@@ -25,8 +25,9 @@
25
25
  "title": "隨便聊聊"
26
26
  },
27
27
  "input": {
28
+ "addAi": "新增一條 AI 訊息",
29
+ "addUser": "新增一條使用者訊息",
28
30
  "more": "更多",
29
- "onlyAdd": "僅新增訊息",
30
31
  "send": "發送",
31
32
  "sendWithCmdEnter": "按 {{meta}} + Enter 鍵發送",
32
33
  "sendWithEnter": "按 Enter 鍵發送",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.149.1",
3
+ "version": "0.149.2",
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",
@@ -0,0 +1,117 @@
1
+ import { Icon } from '@lobehub/ui';
2
+ import { Button, Dropdown } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import { BotMessageSquare, LucideCheck, LucideChevronDown, MessageSquarePlus } from 'lucide-react';
5
+ import { memo } from 'react';
6
+ import { useHotkeys } from 'react-hotkeys-hook';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
9
+
10
+ import HotKeys from '@/components/HotKeys';
11
+ import { ALT_KEY } from '@/const/hotkeys';
12
+ import { useSendMessage } from '@/features/ChatInput/useSend';
13
+ import { useChatStore } from '@/store/chat';
14
+ import { useGlobalStore } from '@/store/global';
15
+ import { preferenceSelectors } from '@/store/global/selectors';
16
+ import { isMacOS } from '@/utils/platform';
17
+
18
+ const useStyles = createStyles(({ css, prefixCls }) => {
19
+ return {
20
+ arrow: css`
21
+ &.${prefixCls}-btn.${prefixCls}-btn-icon-only {
22
+ width: 28px;
23
+ }
24
+ `,
25
+ };
26
+ });
27
+
28
+ const isMac = isMacOS();
29
+
30
+ const SendMore = memo(() => {
31
+ const { t } = useTranslation('chat');
32
+
33
+ const { styles } = useStyles();
34
+
35
+ const [useCmdEnterToSend, updatePreference] = useGlobalStore((s) => [
36
+ preferenceSelectors.useCmdEnterToSend(s),
37
+ s.updatePreference,
38
+ ]);
39
+ const addAIMessage = useChatStore((s) => s.addAIMessage);
40
+
41
+ const sendMessage = useSendMessage();
42
+
43
+ const hotKey = [ALT_KEY, 'enter'].join('+');
44
+ useHotkeys(
45
+ hotKey,
46
+ (keyboardEvent, hotkeysEvent) => {
47
+ console.log(keyboardEvent, hotkeysEvent);
48
+ sendMessage(true);
49
+ },
50
+ {
51
+ enableOnFormTags: true,
52
+ preventDefault: true,
53
+ },
54
+ );
55
+
56
+ return (
57
+ <Dropdown
58
+ menu={{
59
+ items: [
60
+ {
61
+ icon: !useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
62
+ key: 'sendWithEnter',
63
+ label: t('input.sendWithEnter'),
64
+ onClick: () => {
65
+ updatePreference({ useCmdEnterToSend: false });
66
+ },
67
+ },
68
+ {
69
+ icon: useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
70
+ key: 'sendWithCmdEnter',
71
+ label: t('input.sendWithCmdEnter', {
72
+ meta: isMac ? 'Cmd' : 'Ctrl',
73
+ }),
74
+ onClick: () => {
75
+ updatePreference({ useCmdEnterToSend: true });
76
+ },
77
+ },
78
+ { type: 'divider' },
79
+ {
80
+ icon: <Icon icon={BotMessageSquare} />,
81
+ key: 'addAi',
82
+ label: t('input.addAi'),
83
+ onClick: () => {
84
+ addAIMessage();
85
+ },
86
+ },
87
+ {
88
+ icon: <Icon icon={MessageSquarePlus} />,
89
+ key: 'addUser',
90
+ label: (
91
+ <Flexbox gap={24} horizontal>
92
+ {t('input.addUser')}
93
+ <HotKeys keys={hotKey} />
94
+ </Flexbox>
95
+ ),
96
+ onClick: () => {
97
+ sendMessage(true);
98
+ },
99
+ },
100
+ ],
101
+ }}
102
+ placement={'topRight'}
103
+ trigger={['hover']}
104
+ >
105
+ <Button
106
+ aria-label={t('input.more')}
107
+ className={styles.arrow}
108
+ icon={<Icon icon={LucideChevronDown} />}
109
+ type={'primary'}
110
+ />
111
+ </Dropdown>
112
+ );
113
+ });
114
+
115
+ SendMore.displayName = 'SendMore';
116
+
117
+ export default SendMore;
@@ -1,14 +1,7 @@
1
1
  import { Icon } from '@lobehub/ui';
2
- import { Button, Dropdown, Space } from 'antd';
2
+ import { Button, Space } from 'antd';
3
3
  import { createStyles } from 'antd-style';
4
- import {
5
- ChevronUp,
6
- CornerDownLeft,
7
- LucideCheck,
8
- LucideChevronDown,
9
- LucideCommand,
10
- LucidePlus,
11
- } from 'lucide-react';
4
+ import { ChevronUp, CornerDownLeft, LucideCommand } from 'lucide-react';
12
5
  import { rgba } from 'polished';
13
6
  import { memo } from 'react';
14
7
  import { useTranslation } from 'react-i18next';
@@ -26,6 +19,7 @@ import { isMacOS } from '@/utils/platform';
26
19
 
27
20
  import DragUpload from './DragUpload';
28
21
  import { LocalFiles } from './LocalFiles';
22
+ import SendMore from './SendMore';
29
23
 
30
24
  const useStyles = createStyles(({ css, prefixCls, token }) => {
31
25
  return {
@@ -69,13 +63,13 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
69
63
  !!s.chatLoadingId,
70
64
  s.stopGenerateMessage,
71
65
  ]);
72
- const [useCmdEnterToSend, updatePreference] = useGlobalStore((s) => [
73
- preferenceSelectors.useCmdEnterToSend(s),
74
- s.updatePreference,
75
- ]);
76
66
 
77
67
  const model = useSessionStore(agentSelectors.currentAgentModel);
78
- const canUpload = useGlobalStore(modelProviderSelectors.isModelEnabledUpload(model));
68
+
69
+ const [useCmdEnterToSend, canUpload] = useGlobalStore((s) => [
70
+ preferenceSelectors.useCmdEnterToSend(s),
71
+ modelProviderSelectors.isModelEnabledUpload(model)(s),
72
+ ]);
79
73
 
80
74
  const sendMessage = useSendMessage();
81
75
 
@@ -147,48 +141,7 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
147
141
  >
148
142
  {t('input.send')}
149
143
  </Button>
150
- <Dropdown
151
- menu={{
152
- items: [
153
- {
154
- icon: !useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
155
- key: 'sendWithEnter',
156
- label: t('input.sendWithEnter'),
157
- onClick: () => {
158
- updatePreference({ useCmdEnterToSend: false });
159
- },
160
- },
161
- {
162
- icon: useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
163
- key: 'sendWithCmdEnter',
164
- label: t('input.sendWithCmdEnter', {
165
- meta: isMac ? 'Cmd' : 'Ctrl',
166
- }),
167
- onClick: () => {
168
- updatePreference({ useCmdEnterToSend: true });
169
- },
170
- },
171
- { type: 'divider' },
172
- {
173
- icon: <Icon icon={LucidePlus} />,
174
- key: 'onlyAdd',
175
- label: t('input.onlyAdd'),
176
- onClick: () => {
177
- sendMessage(true);
178
- },
179
- },
180
- ],
181
- }}
182
- placement={'topRight'}
183
- trigger={['hover']}
184
- >
185
- <Button
186
- aria-label={t('input.more')}
187
- className={styles.arrow}
188
- icon={<Icon icon={LucideChevronDown} />}
189
- type={'primary'}
190
- />
191
- </Dropdown>
144
+ <SendMore />
192
145
  </Space.Compact>
193
146
  )}
194
147
  </Flexbox>
@@ -88,7 +88,7 @@ const InputArea = memo<InputAreaProps>(({ setExpand }) => {
88
88
  isChineseInput.current = true;
89
89
  }}
90
90
  onPressEnter={(e) => {
91
- if (loading || e.shiftKey || isChineseInput.current) return;
91
+ if (loading || e.altKey || e.shiftKey || isChineseInput.current) return;
92
92
 
93
93
  // eslint-disable-next-line unicorn/consistent-function-scoping
94
94
  const send = () => {
@@ -2,13 +2,13 @@ import isEqual from 'fast-deep-equal';
2
2
  import { useCallback } from 'react';
3
3
  import { useHotkeys } from 'react-hotkeys-hook';
4
4
 
5
- import { CLEAN_MESSAGE_KEY, META_KEY, PREFIX_KEY, REGENERATE_KEY } from '@/const/hotkeys';
5
+ import { ALT_KEY, CLEAN_MESSAGE_KEY, META_KEY, REGENERATE_KEY } from '@/const/hotkeys';
6
6
  import { useChatStore } from '@/store/chat';
7
7
  import { chatSelectors } from '@/store/chat/selectors';
8
8
  import { useFileStore } from '@/store/file';
9
9
 
10
10
  const HotKeys = () => {
11
- const resendHotkeys = [PREFIX_KEY, REGENERATE_KEY].join('+');
11
+ const resendHotkeys = [ALT_KEY, REGENERATE_KEY].join('+');
12
12
 
13
13
  const [regenerateMessage, clearMessage] = useChatStore((s) => [
14
14
  s.regenerateMessage,
@@ -17,7 +17,7 @@ const HotKeys = () => {
17
17
  const lastMessage = useChatStore(chatSelectors.latestMessage, isEqual);
18
18
 
19
19
  const [clearImageList] = useFileStore((s) => [s.clearImageList]);
20
- const clearHotkeys = [META_KEY, PREFIX_KEY, CLEAN_MESSAGE_KEY].join('+');
20
+ const clearHotkeys = [META_KEY, ALT_KEY, CLEAN_MESSAGE_KEY].join('+');
21
21
 
22
22
  const resetConversation = useCallback(() => {
23
23
  clearMessage();
@@ -4,53 +4,49 @@ import { Icon } from '@lobehub/ui';
4
4
  import { createStyles } from 'antd-style';
5
5
  import { isString } from 'lodash-es';
6
6
  import { Command, Delete, Option } from 'lucide-react';
7
+ import { rgba } from 'polished';
7
8
  import { memo, useEffect, useState } from 'react';
8
9
  import { Flexbox } from 'react-layout-kit';
9
10
 
10
- import { CLEAN_MESSAGE_KEY, META_KEY, PREFIX_KEY } from '@/const/hotkeys';
11
+ import { ALT_KEY, CLEAN_MESSAGE_KEY, META_KEY } from '@/const/hotkeys';
11
12
  import { usePlatform } from '@/hooks/usePlatform';
12
13
 
13
14
  const useStyles = createStyles(
14
- ({ css, token }) => css`
15
+ ({ css, token }, inverseTheme: boolean) => css`
15
16
  font-size: 12px;
16
17
 
17
- span {
18
- font-weight: 600;
19
- }
20
-
21
18
  kbd {
22
19
  min-width: 16px;
23
- padding: 3px 6px;
20
+ height: 22px;
21
+ padding-inline: 8px;
24
22
 
25
- line-height: 1;
26
- color: ${token.colorTextDescription};
23
+ line-height: 22px;
24
+ color: ${inverseTheme ? token.colorTextTertiary : token.colorTextSecondary};
27
25
  text-align: center;
28
26
 
29
- background: ${token.colorBgContainer};
30
- border: 1px solid ${token.colorBorderSecondary};
31
- border-bottom-color: ${token.colorBorder};
27
+ background: ${inverseTheme ? rgba(token.colorTextTertiary, 0.15) : token.colorFillTertiary};
32
28
  border-radius: ${token.borderRadius}px;
33
- box-shadow: inset 0 -1px 0 ${token.colorBorder};
34
29
  }
35
30
  `,
36
31
  );
37
32
 
38
33
  export interface HotKeysProps {
39
34
  desc?: string;
35
+ inverseTheme?: boolean;
40
36
  keys: string;
41
37
  }
42
38
 
43
- const HotKeys = memo<HotKeysProps>(({ keys, desc }) => {
44
- const { styles } = useStyles();
39
+ const HotKeys = memo<HotKeysProps>(({ keys, desc, inverseTheme }) => {
40
+ const { styles } = useStyles(inverseTheme);
45
41
  const [keysGroup, setKeysGroup] = useState(keys.split('+'));
46
42
  const visibility = typeof window === 'undefined' ? 'hidden' : 'visible';
47
43
  const { isApple } = usePlatform();
48
44
 
49
45
  useEffect(() => {
50
46
  const mapping: Record<string, any> = {
47
+ [ALT_KEY]: isApple ? <Icon icon={Option} /> : 'alt',
51
48
  [CLEAN_MESSAGE_KEY]: isApple ? <Icon icon={Delete} /> : 'backspace',
52
49
  [META_KEY]: isApple ? <Icon icon={Command} /> : 'ctrl',
53
- [PREFIX_KEY]: isApple ? <Icon icon={Option} /> : 'alt',
54
50
  };
55
51
  const newValue = keys
56
52
  .split('+')
@@ -60,7 +56,7 @@ const HotKeys = memo<HotKeysProps>(({ keys, desc }) => {
60
56
  }, [keys]);
61
57
 
62
58
  const content = (
63
- <Flexbox align={'center'} className={styles} gap={2} horizontal>
59
+ <Flexbox align={'center'} className={styles} gap={4} horizontal>
64
60
  {keysGroup.map((key, index) => (
65
61
  <kbd key={index}>
66
62
  <span style={{ visibility }}>{isString(key) ? key.toUpperCase() : key}</span>
@@ -71,7 +67,7 @@ const HotKeys = memo<HotKeysProps>(({ keys, desc }) => {
71
67
 
72
68
  if (!desc) return content;
73
69
  return (
74
- <Flexbox align={'center'} style={{ textAlign: 'center' }}>
70
+ <Flexbox gap={16} horizontal>
75
71
  {desc}
76
72
  {content}
77
73
  </Flexbox>
@@ -1,4 +1,4 @@
1
- export const PREFIX_KEY = 'alt';
1
+ export const ALT_KEY = 'alt';
2
2
  export const META_KEY = 'mod';
3
3
  export const SAVE_TOPIC_KEY = 'n';
4
4
  export const CLEAN_MESSAGE_KEY = 'backspace';
@@ -5,7 +5,7 @@ import { memo, useCallback, useState } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import HotKeys from '@/components/HotKeys';
8
- import { CLEAN_MESSAGE_KEY, META_KEY, PREFIX_KEY } from '@/const/hotkeys';
8
+ import { ALT_KEY, CLEAN_MESSAGE_KEY, META_KEY } from '@/const/hotkeys';
9
9
  import { useChatStore } from '@/store/chat';
10
10
  import { useFileStore } from '@/store/file';
11
11
 
@@ -13,7 +13,7 @@ const Clear = memo(() => {
13
13
  const { t } = useTranslation('setting');
14
14
  const [clearMessage] = useChatStore((s) => [s.clearMessage]);
15
15
  const [clearImageList] = useFileStore((s) => [s.clearImageList]);
16
- const hotkeys = [META_KEY, PREFIX_KEY, CLEAN_MESSAGE_KEY].join('+');
16
+ const hotkeys = [META_KEY, ALT_KEY, CLEAN_MESSAGE_KEY].join('+');
17
17
  const [confirmOpened, updateConfirmOpened] = useState(false);
18
18
 
19
19
  const resetConversation = useCallback(async () => {
@@ -24,7 +24,7 @@ const Clear = memo(() => {
24
24
  const actionTitle: any = confirmOpened ? (
25
25
  void 0
26
26
  ) : (
27
- <HotKeys desc={t('clearCurrentMessages', { ns: 'chat' })} keys={hotkeys} />
27
+ <HotKeys desc={t('clearCurrentMessages', { ns: 'chat' })} inverseTheme keys={hotkeys} />
28
28
  );
29
29
 
30
30
  return (
@@ -6,7 +6,7 @@ import { useHotkeys } from 'react-hotkeys-hook';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
8
  import HotKeys from '@/components/HotKeys';
9
- import { PREFIX_KEY, SAVE_TOPIC_KEY } from '@/const/hotkeys';
9
+ import { ALT_KEY, SAVE_TOPIC_KEY } from '@/const/hotkeys';
10
10
  import { useActionSWR } from '@/libs/swr';
11
11
  import { useChatStore } from '@/store/chat';
12
12
 
@@ -24,7 +24,7 @@ const SaveTopic = memo<{ mobile?: boolean }>(({ mobile }) => {
24
24
  const iconRender: any = mobile ? icon : <Icon icon={icon} />;
25
25
  const desc = t(hasTopic ? 'topic.openNewTopic' : 'topic.saveCurrentMessages');
26
26
 
27
- const hotkeys = [PREFIX_KEY, SAVE_TOPIC_KEY].join('+');
27
+ const hotkeys = [ALT_KEY, SAVE_TOPIC_KEY].join('+');
28
28
 
29
29
  useHotkeys(hotkeys, () => mutate(), {
30
30
  enableOnFormTags: true,
@@ -32,7 +32,7 @@ const SaveTopic = memo<{ mobile?: boolean }>(({ mobile }) => {
32
32
  });
33
33
 
34
34
  return (
35
- <Tooltip title={<HotKeys desc={desc} keys={hotkeys} />}>
35
+ <Tooltip title={<HotKeys desc={desc} inverseTheme keys={hotkeys} />}>
36
36
  <Render aria-label={desc} icon={iconRender} loading={isValidating} onClick={() => mutate()} />
37
37
  </Tooltip>
38
38
  );
@@ -27,7 +27,7 @@ export const AssistantActionsBar: RenderAction = memo(({ id, onActionClick, erro
27
27
  delAndRegenerate,
28
28
  del,
29
29
  ]}
30
- items={[regenerate, copy]}
30
+ items={[edit, copy]}
31
31
  onActionClick={onActionClick}
32
32
  type="ghost"
33
33
  />
@@ -27,8 +27,9 @@ export default {
27
27
  title: '随便聊聊',
28
28
  },
29
29
  input: {
30
+ addAi: '添加一条 AI 消息',
31
+ addUser: '添加一条用户消息',
30
32
  more: '更多',
31
- onlyAdd: '仅添加消息',
32
33
  send: '发送',
33
34
  sendWithCmdEnter: '按 {{meta}} + Enter 键发送',
34
35
  sendWithEnter: '按 Enter 键发送',
@@ -38,6 +38,7 @@ interface SendMessageParams {
38
38
  export interface ChatMessageAction {
39
39
  // create
40
40
  sendMessage: (params: SendMessageParams) => Promise<void>;
41
+ addAIMessage: () => Promise<void>;
41
42
  /**
42
43
  * regenerate message
43
44
  * trace enabled
@@ -214,7 +215,21 @@ export const chatMessage: StateCreator<
214
215
  if (id) switchTopic(id);
215
216
  }
216
217
  },
218
+ addAIMessage: async () => {
219
+ const { internalCreateMessage, updateInputMessage, activeTopicId, activeId, inputMessage } =
220
+ get();
221
+ if (!activeId) return;
222
+
223
+ await internalCreateMessage({
224
+ content: inputMessage,
225
+ role: 'assistant',
226
+ sessionId: activeId,
227
+ // if there is activeTopicId,then add topicId to message
228
+ topicId: activeTopicId,
229
+ });
217
230
 
231
+ updateInputMessage('');
232
+ },
218
233
  copyMessage: async (id, content) => {
219
234
  await copyToClipboard(content);
220
235