@lobehub/chat 1.123.4 → 1.124.0
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 +25 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/chat.json +6 -2
- package/locales/ar/editor.json +47 -0
- package/locales/bg-BG/chat.json +6 -2
- package/locales/bg-BG/editor.json +47 -0
- package/locales/de-DE/chat.json +6 -2
- package/locales/de-DE/editor.json +47 -0
- package/locales/en-US/chat.json +6 -2
- package/locales/en-US/editor.json +47 -0
- package/locales/es-ES/chat.json +6 -2
- package/locales/es-ES/editor.json +47 -0
- package/locales/es-ES/models.json +3 -1
- package/locales/fa-IR/chat.json +6 -2
- package/locales/fa-IR/editor.json +47 -0
- package/locales/fr-FR/chat.json +6 -2
- package/locales/fr-FR/editor.json +47 -0
- package/locales/it-IT/chat.json +6 -2
- package/locales/it-IT/editor.json +47 -0
- package/locales/ja-JP/chat.json +6 -2
- package/locales/ja-JP/editor.json +47 -0
- package/locales/ko-KR/chat.json +6 -2
- package/locales/ko-KR/editor.json +47 -0
- package/locales/ko-KR/models.json +3 -1
- package/locales/nl-NL/chat.json +6 -2
- package/locales/nl-NL/editor.json +47 -0
- package/locales/nl-NL/models.json +3 -1
- package/locales/pl-PL/chat.json +6 -2
- package/locales/pl-PL/editor.json +47 -0
- package/locales/pt-BR/chat.json +6 -2
- package/locales/pt-BR/editor.json +47 -0
- package/locales/ru-RU/chat.json +6 -2
- package/locales/ru-RU/editor.json +47 -0
- package/locales/tr-TR/chat.json +6 -2
- package/locales/tr-TR/editor.json +47 -0
- package/locales/vi-VN/chat.json +6 -2
- package/locales/vi-VN/editor.json +47 -0
- package/locales/zh-CN/chat.json +6 -2
- package/locales/zh-CN/editor.json +47 -0
- package/locales/zh-TW/chat.json +6 -2
- package/locales/zh-TW/editor.json +47 -0
- package/locales/zh-TW/models.json +3 -1
- package/next.config.ts +4 -0
- package/package.json +4 -2
- package/packages/const/src/layoutTokens.ts +1 -0
- package/packages/types/src/index.ts +1 -0
- package/packages/utils/src/index.ts +1 -0
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/{Footer/MessageFromUrl.tsx → MessageFromUrl.tsx} +3 -2
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/index.tsx +129 -28
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/index.tsx +44 -66
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts +141 -0
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/Content.tsx +7 -1
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/InboxWelcome/QuestionSuggest.tsx +3 -2
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/OpeningQuestions.tsx +3 -2
- package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/HeaderAction.tsx +18 -2
- package/src/features/ChatInput/ActionBar/STT/common.tsx +41 -47
- package/src/features/ChatInput/{Topic → ActionBar/SaveTopic}/index.tsx +15 -4
- package/src/features/ChatInput/ActionBar/Typo/index.tsx +22 -0
- package/src/features/ChatInput/ActionBar/components/Action.tsx +4 -0
- package/src/features/ChatInput/ActionBar/config.ts +7 -1
- package/src/features/ChatInput/ActionBar/index.tsx +40 -51
- package/src/features/ChatInput/ChatInputProvider.tsx +54 -0
- package/src/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +20 -11
- package/src/features/ChatInput/Desktop/FilePreview/FileList.tsx +16 -15
- package/src/features/ChatInput/Desktop/index.tsx +81 -68
- package/src/features/ChatInput/InputEditor/index.tsx +134 -0
- package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/File.tsx +1 -2
- package/src/features/ChatInput/Mobile/FilePreview/index.tsx +44 -0
- package/src/features/ChatInput/Mobile/index.tsx +72 -0
- package/src/features/ChatInput/SendArea/ExpandButton.tsx +30 -0
- package/src/features/ChatInput/SendArea/SendButton.tsx +29 -0
- package/src/features/ChatInput/SendArea/ShortcutHint.tsx +52 -0
- package/src/features/ChatInput/SendArea/index.tsx +36 -0
- package/src/features/ChatInput/StoreUpdater.tsx +41 -0
- package/src/features/ChatInput/TypoBar/index.tsx +139 -0
- package/src/features/ChatInput/hooks/useChatInputEditor.ts +36 -0
- package/src/features/ChatInput/index.ts +7 -0
- package/src/features/ChatInput/store/action.ts +75 -0
- package/src/features/ChatInput/store/index.ts +23 -0
- package/src/features/ChatInput/store/initialState.ts +54 -0
- package/src/features/ChatInput/store/selectors.ts +5 -0
- package/src/features/Conversation/components/BackBottom/style.ts +1 -1
- package/src/features/Conversation/components/SkeletonList.tsx +10 -3
- package/src/features/Conversation/components/VirtualizedList/index.tsx +53 -44
- package/src/features/Conversation/components/WideScreenContainer/index.tsx +43 -0
- package/src/features/Portal/Thread/Chat/ChatInput/index.tsx +49 -42
- package/src/features/Portal/Thread/Chat/ChatInput/useSend.ts +48 -22
- package/src/features/Portal/Thread/Chat/index.tsx +2 -2
- package/src/features/Portal/Thread/Header/index.tsx +1 -1
- package/src/hooks/useHotkeys/chatScope.ts +5 -3
- package/src/layout/GlobalProvider/Editor.tsx +27 -0
- package/src/layout/GlobalProvider/Locale.tsx +3 -23
- package/src/locales/default/chat.ts +7 -2
- package/src/locales/default/editor.ts +47 -0
- package/src/locales/default/index.ts +2 -0
- package/src/services/aiChat.ts +8 -2
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +42 -33
- package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +174 -35
- package/src/store/chat/slices/aiChat/initialState.ts +19 -0
- package/src/store/chat/slices/aiChat/selectors.ts +18 -0
- package/src/store/global/action.test.ts +6 -5
- package/src/store/global/actions/__tests__/general.test.ts +6 -6
- package/src/store/global/actions/workspacePane.ts +6 -0
- package/src/store/global/initialState.ts +2 -4
- package/src/store/global/selectors/systemStatus.test.ts +1 -2
- package/src/store/global/selectors/systemStatus.ts +2 -5
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/SendMore.tsx +0 -104
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/ShortcutHint.tsx +0 -40
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +0 -125
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.test.tsx +0 -332
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.tsx +0 -29
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/index.tsx +0 -33
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/Container.tsx +0 -41
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/index.tsx +0 -156
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Send.tsx +0 -33
- package/src/features/ChatInput/Desktop/Header/index.tsx +0 -30
- package/src/features/ChatInput/Desktop/InputArea/index.tsx +0 -143
- package/src/features/ChatInput/Desktop/__tests__/useAutoFocus.test.ts +0 -45
- package/src/features/ChatInput/Desktop/useAutoFocus.ts +0 -13
- package/src/features/ChatInput/useSend.ts +0 -102
- package/src/features/Portal/Thread/Chat/ChatInput/Footer.tsx +0 -90
- package/src/features/Portal/Thread/Chat/ChatInput/TextArea.tsx +0 -30
- package/src/libs/trpc/client/types.ts +0 -18
- /package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/Image.tsx +0 -0
- /package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/index.tsx +0 -0
- /package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/style.ts +0 -0
|
@@ -4,63 +4,70 @@ import { Alert } from '@lobehub/ui';
|
|
|
4
4
|
import Link from 'next/link';
|
|
5
5
|
import { memo } from 'react';
|
|
6
6
|
import { Trans } from 'react-i18next';
|
|
7
|
+
import { Flexbox } from 'react-layout-kit';
|
|
7
8
|
|
|
8
|
-
import { ActionKeys } from '@/features/ChatInput
|
|
9
|
-
import
|
|
9
|
+
import { type ActionKeys, ChatInputProvider, DesktopChatInput } from '@/features/ChatInput';
|
|
10
|
+
import WideScreenContainer from '@/features/Conversation/components/WideScreenContainer';
|
|
11
|
+
import { useChatStore } from '@/store/chat';
|
|
10
12
|
import { useGlobalStore } from '@/store/global';
|
|
11
13
|
import { systemStatusSelectors } from '@/store/global/selectors';
|
|
12
14
|
|
|
13
|
-
import
|
|
14
|
-
import TextArea from './TextArea';
|
|
15
|
+
import { useSendThreadMessage } from './useSend';
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const rightActions = [] as ActionKeys[];
|
|
19
|
-
|
|
20
|
-
const renderTextArea = (onSend: () => void) => <TextArea onSend={onSend} />;
|
|
21
|
-
const renderFooter: FooterRender = (props) => <Footer {...props} />;
|
|
17
|
+
const threadActions: ActionKeys[] = ['typo', 'stt', 'portalToken'];
|
|
22
18
|
|
|
23
19
|
const Desktop = memo(() => {
|
|
24
|
-
const [
|
|
25
|
-
systemStatusSelectors.threadInputHeight(s),
|
|
20
|
+
const [hideThreadLimitAlert, updateSystemStatus] = useGlobalStore((s) => [
|
|
26
21
|
systemStatusSelectors.systemStatus(s).hideThreadLimitAlert,
|
|
27
22
|
s.updateSystemStatus,
|
|
28
23
|
]);
|
|
29
24
|
|
|
25
|
+
const { send, disabled, generating, stop } = useSendThreadMessage();
|
|
26
|
+
|
|
30
27
|
return (
|
|
31
|
-
|
|
28
|
+
<WideScreenContainer>
|
|
32
29
|
{!hideThreadLimitAlert && (
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
30
|
+
<Flexbox paddingBlock={'0 6px'} paddingInline={12}>
|
|
31
|
+
<Alert
|
|
32
|
+
closable
|
|
33
|
+
message={
|
|
34
|
+
<Trans i18nKey={'notSupportMultiModals'} ns={'thread'}>
|
|
35
|
+
子话题暂不支持文件/图片上传,如有需求,欢迎留言:
|
|
36
|
+
<Link
|
|
37
|
+
href={'https://github.com/lobehub/lobe-chat/discussions/4717'}
|
|
38
|
+
style={{ textDecoration: 'underline' }}
|
|
39
|
+
>
|
|
40
|
+
💬 讨论
|
|
41
|
+
</Link>
|
|
42
|
+
</Trans>
|
|
43
|
+
}
|
|
44
|
+
onClose={() => {
|
|
45
|
+
updateSystemStatus({ hideThreadLimitAlert: true });
|
|
46
|
+
}}
|
|
47
|
+
type={'info'}
|
|
48
|
+
/>
|
|
49
|
+
</Flexbox>
|
|
52
50
|
)}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
|
|
52
|
+
<ChatInputProvider
|
|
53
|
+
chatInputEditorRef={(instance) => {
|
|
54
|
+
if (!instance) return;
|
|
55
|
+
useChatStore.setState({ threadInputEditor: instance });
|
|
56
|
+
}}
|
|
57
|
+
leftActions={threadActions}
|
|
58
|
+
onSend={() => {
|
|
59
|
+
send();
|
|
60
|
+
}}
|
|
61
|
+
sendButtonProps={{
|
|
62
|
+
disabled,
|
|
63
|
+
generating,
|
|
64
|
+
onStop: stop,
|
|
65
|
+
shape: 'round',
|
|
58
66
|
}}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</>
|
|
67
|
+
>
|
|
68
|
+
<DesktopChatInput />
|
|
69
|
+
</ChatInputProvider>
|
|
70
|
+
</WideScreenContainer>
|
|
64
71
|
);
|
|
65
72
|
});
|
|
66
73
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo, useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useGeminiChineseWarning } from '@/hooks/useGeminiChineseWarning';
|
|
4
|
+
import { getAgentStoreState } from '@/store/agent';
|
|
5
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
3
6
|
import { useChatStore } from '@/store/chat';
|
|
4
7
|
import { threadSelectors } from '@/store/chat/selectors';
|
|
5
8
|
import { SendMessageParams } from '@/types/message';
|
|
@@ -10,41 +13,64 @@ export type UseSendMessageParams = Pick<
|
|
|
10
13
|
>;
|
|
11
14
|
|
|
12
15
|
export const useSendThreadMessage = () => {
|
|
16
|
+
const [loading, setLoading] = useState(false);
|
|
17
|
+
const canNotSend = useChatStore(threadSelectors.isSendButtonDisabledByMessage);
|
|
18
|
+
const generating = useChatStore((s) => threadSelectors.isThreadAIGenerating(s));
|
|
19
|
+
const stop = useChatStore((s) => s.stopGenerateMessage);
|
|
13
20
|
const [sendMessage, updateInputMessage] = useChatStore((s) => [
|
|
14
21
|
s.sendThreadMessage,
|
|
15
22
|
s.updateThreadInputMessage,
|
|
16
23
|
]);
|
|
24
|
+
const checkGeminiChineseWarning = useGeminiChineseWarning();
|
|
17
25
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const canSend = !isSendButtonDisabledByMessage;
|
|
21
|
-
|
|
22
|
-
const send = useCallback((params: UseSendMessageParams = {}) => {
|
|
26
|
+
const handleSend = async (params: UseSendMessageParams = {}) => {
|
|
23
27
|
const store = useChatStore.getState();
|
|
28
|
+
|
|
24
29
|
if (threadSelectors.isThreadAIGenerating(store)) return;
|
|
30
|
+
const canNotSend = threadSelectors.isSendButtonDisabledByMessage(store);
|
|
31
|
+
|
|
32
|
+
if (canNotSend) return;
|
|
33
|
+
|
|
34
|
+
const threadInputEditor = store.threadInputEditor;
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
if (!threadInputEditor) {
|
|
37
|
+
console.warn('not found threadInputEditor instance');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
29
40
|
|
|
30
|
-
const
|
|
31
|
-
if (!canSend) return;
|
|
41
|
+
const inputMessage = threadInputEditor.getMarkdownContent();
|
|
32
42
|
|
|
33
43
|
// if there is no message and no image, then we should not send the message
|
|
34
|
-
if (!
|
|
44
|
+
if (!inputMessage) return;
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
// Check for Chinese text warning with Gemini model
|
|
47
|
+
const agentStore = getAgentStoreState();
|
|
48
|
+
const currentModel = agentSelectors.currentAgentModel(agentStore);
|
|
49
|
+
const shouldContinue = await checkGeminiChineseWarning({
|
|
50
|
+
model: currentModel,
|
|
51
|
+
prompt: inputMessage,
|
|
52
|
+
scenario: 'chat',
|
|
53
|
+
});
|
|
37
54
|
|
|
38
|
-
|
|
55
|
+
if (!shouldContinue) return;
|
|
56
|
+
|
|
57
|
+
updateInputMessage(inputMessage);
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
sendMessage({ message: inputMessage, ...params });
|
|
60
|
+
|
|
61
|
+
updateInputMessage('');
|
|
62
|
+
threadInputEditor.clearContent();
|
|
63
|
+
threadInputEditor.focus();
|
|
64
|
+
};
|
|
42
65
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
66
|
+
const send = async (params: UseSendMessageParams = {}) => {
|
|
67
|
+
setLoading(true);
|
|
68
|
+
await handleSend(params);
|
|
69
|
+
setLoading(false);
|
|
70
|
+
};
|
|
48
71
|
|
|
49
|
-
return useMemo(
|
|
72
|
+
return useMemo(
|
|
73
|
+
() => ({ disabled: canNotSend, generating, loading, send, stop }),
|
|
74
|
+
[canNotSend, send, generating, stop, loading],
|
|
75
|
+
);
|
|
50
76
|
};
|
|
@@ -11,7 +11,7 @@ interface ConversationProps {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const Conversation = memo<ConversationProps>(({ mobile }) => (
|
|
14
|
-
|
|
14
|
+
<>
|
|
15
15
|
<Suspense
|
|
16
16
|
fallback={
|
|
17
17
|
<Flexbox flex={1} height={'100%'}>
|
|
@@ -22,7 +22,7 @@ const Conversation = memo<ConversationProps>(({ mobile }) => (
|
|
|
22
22
|
<ChatList mobile={mobile} />
|
|
23
23
|
</Suspense>
|
|
24
24
|
<ChatInput />
|
|
25
|
-
|
|
25
|
+
</>
|
|
26
26
|
));
|
|
27
27
|
|
|
28
28
|
export default Conversation;
|
|
@@ -40,7 +40,7 @@ const Header = memo(() => {
|
|
|
40
40
|
paddingBlock={6}
|
|
41
41
|
paddingInline={8}
|
|
42
42
|
style={{
|
|
43
|
-
|
|
43
|
+
borderBottom: `1px solid ${theme.colorBorderSecondary}`,
|
|
44
44
|
}}
|
|
45
45
|
title={<Title />}
|
|
46
46
|
/>
|
|
@@ -2,8 +2,8 @@ import isEqual from 'fast-deep-equal';
|
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { useHotkeysContext } from 'react-hotkeys-hook';
|
|
4
4
|
|
|
5
|
+
import { useSend } from '@/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend';
|
|
5
6
|
import { useClearCurrentMessages } from '@/features/ChatInput/ActionBar/Clear';
|
|
6
|
-
import { useSendMessage } from '@/features/ChatInput/useSend';
|
|
7
7
|
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
8
8
|
import { useActionSWR } from '@/libs/swr';
|
|
9
9
|
import { useChatStore } from '@/store/chat';
|
|
@@ -75,8 +75,10 @@ export const useToggleRightPanelHotkey = () => {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
export const useAddUserMessageHotkey = () => {
|
|
78
|
-
const { send } =
|
|
79
|
-
return useHotkeyById(HotkeyEnum.AddUserMessage, () =>
|
|
78
|
+
const { send } = useSend();
|
|
79
|
+
return useHotkeyById(HotkeyEnum.AddUserMessage, () => {
|
|
80
|
+
send({ onlyAddUserMessage: true });
|
|
81
|
+
});
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
export const useClearCurrentMessagesHotkey = () => {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { EditorProvider } from '@lobehub/editor/react';
|
|
4
|
+
import { PropsWithChildren, memo, useMemo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
const Editor = memo<PropsWithChildren>(({ children }) => {
|
|
8
|
+
const {
|
|
9
|
+
i18n: { language, getResourceBundle },
|
|
10
|
+
} = useTranslation('editor');
|
|
11
|
+
|
|
12
|
+
const localization = useMemo(() => getResourceBundle(language, 'editor'), [language]);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<EditorProvider
|
|
16
|
+
config={{
|
|
17
|
+
locale: localization,
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
{children}
|
|
21
|
+
</EditorProvider>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
Editor.displayName = 'Editor';
|
|
26
|
+
|
|
27
|
+
export default Editor;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { ConfigProvider } from 'antd';
|
|
4
|
-
import { useTheme } from 'antd-style';
|
|
5
4
|
import dayjs from 'dayjs';
|
|
6
5
|
import { PropsWithChildren, memo, useEffect, useState } from 'react';
|
|
7
6
|
import { isRtlLang } from 'rtl-detect';
|
|
@@ -10,6 +9,8 @@ import { createI18nNext } from '@/locales/create';
|
|
|
10
9
|
import { isOnServerSide } from '@/utils/env';
|
|
11
10
|
import { getAntdLocale } from '@/utils/locale';
|
|
12
11
|
|
|
12
|
+
import Editor from './Editor';
|
|
13
|
+
|
|
13
14
|
const updateDayjs = async (lang: string) => {
|
|
14
15
|
// load default lang
|
|
15
16
|
let dayJSLocale;
|
|
@@ -36,7 +37,6 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang, antdLocale }) =
|
|
|
36
37
|
const [i18n] = useState(createI18nNext(defaultLang));
|
|
37
38
|
const [lang, setLang] = useState(defaultLang);
|
|
38
39
|
const [locale, setLocale] = useState(antdLocale);
|
|
39
|
-
const theme = useTheme();
|
|
40
40
|
|
|
41
41
|
// if run on server side, init i18n instance everytime
|
|
42
42
|
if (isOnServerSide) {
|
|
@@ -91,30 +91,10 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang, antdLocale }) =
|
|
|
91
91
|
Button: {
|
|
92
92
|
contentFontSizeSM: 12,
|
|
93
93
|
},
|
|
94
|
-
DatePicker: {
|
|
95
|
-
activeBorderColor: theme.colorBorder,
|
|
96
|
-
hoverBorderColor: theme.colorBorder,
|
|
97
|
-
},
|
|
98
|
-
Input: {
|
|
99
|
-
activeBorderColor: theme.colorBorder,
|
|
100
|
-
hoverBorderColor: theme.colorBorder,
|
|
101
|
-
},
|
|
102
|
-
InputNumber: {
|
|
103
|
-
activeBorderColor: theme.colorBorder,
|
|
104
|
-
hoverBorderColor: theme.colorBorder,
|
|
105
|
-
},
|
|
106
|
-
Mentions: {
|
|
107
|
-
activeBorderColor: theme.colorBorder,
|
|
108
|
-
hoverBorderColor: theme.colorBorder,
|
|
109
|
-
},
|
|
110
|
-
Select: {
|
|
111
|
-
activeBorderColor: theme.colorBorder,
|
|
112
|
-
hoverBorderColor: theme.colorBorder,
|
|
113
|
-
},
|
|
114
94
|
},
|
|
115
95
|
}}
|
|
116
96
|
>
|
|
117
|
-
{children}
|
|
97
|
+
<Editor>{children}</Editor>
|
|
118
98
|
</ConfigProvider>
|
|
119
99
|
);
|
|
120
100
|
});
|
|
@@ -71,10 +71,11 @@ export default {
|
|
|
71
71
|
input: {
|
|
72
72
|
addAi: '添加一条 AI 消息',
|
|
73
73
|
addUser: '添加一条用户消息',
|
|
74
|
+
errorMsg: '消息发送失败,请检查网络后重试: {{errorMsg}}',
|
|
74
75
|
more: '更多',
|
|
75
76
|
send: '发送',
|
|
76
|
-
sendWithCmdEnter: '按
|
|
77
|
-
sendWithEnter: '按
|
|
77
|
+
sendWithCmdEnter: '按 <key/> 键发送',
|
|
78
|
+
sendWithEnter: '按 <key/> 键发送',
|
|
78
79
|
stop: '停止',
|
|
79
80
|
warp: '换行',
|
|
80
81
|
},
|
|
@@ -236,6 +237,10 @@ export default {
|
|
|
236
237
|
threadMessageCount: '{{messageCount}} 条消息',
|
|
237
238
|
title: '子话题',
|
|
238
239
|
},
|
|
240
|
+
toggleWideScreen: {
|
|
241
|
+
off: '关闭宽屏模式',
|
|
242
|
+
on: '开启宽屏模式',
|
|
243
|
+
},
|
|
239
244
|
tokenDetails: {
|
|
240
245
|
chats: '会话消息',
|
|
241
246
|
historySummary: '历史总结',
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
actions: {
|
|
3
|
+
expand: {
|
|
4
|
+
off: '收起',
|
|
5
|
+
on: '展开',
|
|
6
|
+
},
|
|
7
|
+
typobar: {
|
|
8
|
+
off: '隐藏格式工具栏',
|
|
9
|
+
on: '显示格式工具栏',
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
file: {
|
|
13
|
+
error: '错误:{{message}}',
|
|
14
|
+
uploading: '正在上传文件...',
|
|
15
|
+
},
|
|
16
|
+
image: {
|
|
17
|
+
broken: '图片损坏',
|
|
18
|
+
},
|
|
19
|
+
link: {
|
|
20
|
+
edit: '编辑链接',
|
|
21
|
+
open: '打开链接',
|
|
22
|
+
placeholder: '输入链接 URL',
|
|
23
|
+
unlink: '取消链接',
|
|
24
|
+
},
|
|
25
|
+
table: {
|
|
26
|
+
delete: '删除表格',
|
|
27
|
+
deleteColumn: '删除列',
|
|
28
|
+
deleteRow: '删除行',
|
|
29
|
+
insertColumnLeft: '在左侧插入 {{count}} 列',
|
|
30
|
+
insertColumnRight: '在右侧插入 {{count}} 列',
|
|
31
|
+
insertRowAbove: '在上方插入 {{count}} 行',
|
|
32
|
+
insertRowBelow: '在下方插入 {{count}} 行',
|
|
33
|
+
},
|
|
34
|
+
typobar: {
|
|
35
|
+
blockquote: '引用',
|
|
36
|
+
bold: '加粗',
|
|
37
|
+
bulletList: '无序列表',
|
|
38
|
+
code: '行内代码',
|
|
39
|
+
codeblock: '代码块',
|
|
40
|
+
italic: '斜体',
|
|
41
|
+
link: '链接',
|
|
42
|
+
numberList: '有序列表',
|
|
43
|
+
strikethrough: '删除线',
|
|
44
|
+
table: '插入表格',
|
|
45
|
+
underline: '下划线',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -6,6 +6,7 @@ import color from './color';
|
|
|
6
6
|
import common from './common';
|
|
7
7
|
import components from './components';
|
|
8
8
|
import discover from './discover';
|
|
9
|
+
import editor from './editor';
|
|
9
10
|
import electron from './electron';
|
|
10
11
|
import error from './error';
|
|
11
12
|
import file from './file';
|
|
@@ -37,6 +38,7 @@ const resources = {
|
|
|
37
38
|
common,
|
|
38
39
|
components,
|
|
39
40
|
discover,
|
|
41
|
+
editor,
|
|
40
42
|
electron,
|
|
41
43
|
error,
|
|
42
44
|
file,
|
package/src/services/aiChat.ts
CHANGED
|
@@ -4,8 +4,14 @@ import { cleanObject } from '@lobechat/utils';
|
|
|
4
4
|
import { lambdaClient } from '@/libs/trpc/client';
|
|
5
5
|
|
|
6
6
|
class AiChatService {
|
|
7
|
-
sendMessageInServer = async (
|
|
8
|
-
|
|
7
|
+
sendMessageInServer = async (
|
|
8
|
+
params: SendMessageServerParams,
|
|
9
|
+
abortController: AbortController,
|
|
10
|
+
) => {
|
|
11
|
+
return lambdaClient.aiChat.sendMessageInServer.mutate(cleanObject(params), {
|
|
12
|
+
context: { showNotification: false },
|
|
13
|
+
signal: abortController?.signal,
|
|
14
|
+
});
|
|
9
15
|
};
|
|
10
16
|
}
|
|
11
17
|
|
|
@@ -187,18 +187,21 @@ describe('generateAIChatV2 actions', () => {
|
|
|
187
187
|
await result.current.sendMessage({ message, files });
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
-
expect(aiChatService.sendMessageInServer).toHaveBeenCalledWith(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
190
|
+
expect(aiChatService.sendMessageInServer).toHaveBeenCalledWith(
|
|
191
|
+
{
|
|
192
|
+
newAssistantMessage: {
|
|
193
|
+
model: DEFAULT_MODEL,
|
|
194
|
+
provider: DEFAULT_PROVIDER,
|
|
195
|
+
},
|
|
196
|
+
newUserMessage: {
|
|
197
|
+
content: message,
|
|
198
|
+
files: files.map((f) => f.id),
|
|
199
|
+
},
|
|
200
|
+
sessionId: mockState.activeId,
|
|
201
|
+
topicId: mockState.activeTopicId,
|
|
194
202
|
},
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
files: files.map((f) => f.id),
|
|
198
|
-
},
|
|
199
|
-
sessionId: mockState.activeId,
|
|
200
|
-
topicId: mockState.activeTopicId,
|
|
201
|
-
});
|
|
203
|
+
expect.anything(),
|
|
204
|
+
);
|
|
202
205
|
expect(result.current.internal_execAgentRuntime).toHaveBeenCalled();
|
|
203
206
|
});
|
|
204
207
|
|
|
@@ -270,18 +273,21 @@ describe('generateAIChatV2 actions', () => {
|
|
|
270
273
|
await result.current.sendMessage({ message: '', files: [{ id: 'file-1' }] as any });
|
|
271
274
|
});
|
|
272
275
|
|
|
273
|
-
expect(aiChatService.sendMessageInServer).toHaveBeenCalledWith(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
expect(aiChatService.sendMessageInServer).toHaveBeenCalledWith(
|
|
277
|
+
{
|
|
278
|
+
newAssistantMessage: {
|
|
279
|
+
model: DEFAULT_MODEL,
|
|
280
|
+
provider: DEFAULT_PROVIDER,
|
|
281
|
+
},
|
|
282
|
+
newUserMessage: {
|
|
283
|
+
content: '',
|
|
284
|
+
files: ['file-1'],
|
|
285
|
+
},
|
|
286
|
+
sessionId: 'session-id',
|
|
287
|
+
topicId: 'topic-id',
|
|
281
288
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
});
|
|
289
|
+
expect.anything(),
|
|
290
|
+
);
|
|
285
291
|
});
|
|
286
292
|
|
|
287
293
|
it('当同时有文件和消息内容时,正确发送消息并关联文件', async () => {
|
|
@@ -291,18 +297,21 @@ describe('generateAIChatV2 actions', () => {
|
|
|
291
297
|
await result.current.sendMessage({ message: 'test', files: [{ id: 'file-1' }] as any });
|
|
292
298
|
});
|
|
293
299
|
|
|
294
|
-
expect(aiChatService.sendMessageInServer).toHaveBeenCalledWith(
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
300
|
+
expect(aiChatService.sendMessageInServer).toHaveBeenCalledWith(
|
|
301
|
+
{
|
|
302
|
+
newAssistantMessage: {
|
|
303
|
+
model: DEFAULT_MODEL,
|
|
304
|
+
provider: DEFAULT_PROVIDER,
|
|
305
|
+
},
|
|
306
|
+
newUserMessage: {
|
|
307
|
+
content: 'test',
|
|
308
|
+
files: ['file-1'],
|
|
309
|
+
},
|
|
310
|
+
sessionId: 'session-id',
|
|
311
|
+
topicId: 'topic-id',
|
|
302
312
|
},
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
});
|
|
313
|
+
expect.anything(),
|
|
314
|
+
);
|
|
306
315
|
});
|
|
307
316
|
|
|
308
317
|
it('当 createMessage 抛出错误时,正确处理错误而不影响整个应用', async () => {
|