@lobehub/lobehub 2.0.0-next.8 → 2.0.0-next.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/.github/workflows/desktop-pr-build.yml +8 -8
- package/.github/workflows/docker.yml +17 -16
- package/.github/workflows/e2e.yml +3 -3
- package/.github/workflows/release-desktop-beta.yml +8 -8
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/test.yml +4 -4
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/packages/const/src/index.ts +0 -1
- package/packages/const/src/url.ts +1 -4
- package/packages/context-engine/src/index.ts +1 -6
- package/packages/context-engine/src/processors/GroupMessageFlatten.ts +12 -2
- package/packages/context-engine/src/processors/__tests__/GroupMessageFlatten.test.ts +73 -9
- package/packages/context-engine/src/providers/index.ts +0 -2
- package/packages/database/package.json +1 -1
- package/packages/database/src/models/__tests__/message.grouping.test.ts +812 -0
- package/packages/database/src/models/__tests__/message.test.ts +322 -170
- package/packages/database/src/models/message.ts +62 -24
- package/packages/database/src/utils/__tests__/groupMessages.test.ts +145 -2
- package/packages/database/src/utils/groupMessages.ts +7 -5
- package/packages/types/src/message/common/base.ts +13 -0
- package/packages/types/src/message/common/image.ts +8 -0
- package/packages/types/src/message/common/metadata.ts +39 -0
- package/packages/types/src/message/common/tools.ts +10 -0
- package/packages/types/src/message/db/params.ts +47 -1
- package/packages/types/src/message/ui/chat.ts +4 -1
- package/packages/types/src/search.ts +16 -0
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/V1Mobile/index.tsx +2 -2
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/V1Mobile/useSend.ts +6 -4
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts +15 -10
- package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/index.tsx +4 -2
- package/src/components/Thinking/index.tsx +4 -3
- package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/browser.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/openai.tsx +2 -2
- package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +1 -3
- package/src/features/Conversation/Error/ErrorJsonViewer.tsx +4 -3
- package/src/features/Conversation/Error/OllamaBizError/index.tsx +7 -2
- package/src/features/Conversation/Error/index.tsx +15 -5
- package/src/features/Conversation/MarkdownElements/LobeArtifact/Render/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Extra/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +5 -3
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/BuiltinPluginTitle.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/ToolTitle.tsx +4 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/CustomRender.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/index.tsx +4 -4
- package/src/features/Conversation/Messages/Default.tsx +2 -2
- package/src/features/Conversation/Messages/User/Extra.tsx +2 -2
- package/src/features/Conversation/Messages/User/index.tsx +4 -4
- package/src/features/Conversation/Messages/index.tsx +3 -3
- package/src/features/Conversation/components/AutoScroll.tsx +2 -2
- package/src/features/Conversation/components/Extras/Usage/UsageDetail/index.tsx +9 -6
- package/src/features/PluginTag/index.tsx +1 -3
- package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +37 -28
- package/src/features/Portal/Artifacts/Body/index.tsx +2 -2
- package/src/server/modules/ModelRuntime/trace.ts +11 -4
- package/src/server/routers/lambda/message.ts +14 -3
- package/src/services/chat/chat.test.ts +1 -40
- package/src/services/chat/contextEngineering.test.ts +0 -30
- package/src/services/chat/contextEngineering.ts +1 -12
- package/src/services/chat/index.ts +2 -7
- package/src/services/chat/types.ts +1 -1
- package/src/services/message/_deprecated.ts +1 -1
- package/src/services/message/client.ts +8 -2
- package/src/services/message/server.ts +7 -2
- package/src/services/message/type.ts +6 -1
- package/src/store/chat/helpers.test.ts +99 -0
- package/src/store/chat/helpers.ts +21 -2
- package/src/store/chat/selectors.ts +1 -1
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +3 -3
- package/src/store/chat/slices/builtinTool/actions/index.ts +1 -4
- package/src/store/chat/slices/message/action.test.ts +5 -1
- package/src/store/chat/slices/message/action.ts +102 -14
- package/src/store/chat/slices/message/reducer.test.ts +363 -5
- package/src/store/chat/slices/message/reducer.ts +87 -3
- package/src/store/chat/slices/message/{selectors.test.ts → selectors/chat.test.ts} +266 -30
- package/src/store/chat/slices/message/{selectors.ts → selectors/chat.ts} +29 -79
- package/src/store/chat/slices/message/selectors/index.ts +2 -0
- package/src/store/chat/slices/message/selectors/messageState.test.ts +36 -0
- package/src/store/chat/slices/message/selectors/messageState.ts +80 -0
- package/src/store/chat/slices/plugin/action.test.ts +34 -132
- package/src/store/chat/slices/plugin/action.ts +1 -44
- package/src/store/tool/selectors/tool.test.ts +1 -1
- package/src/store/tool/selectors/tool.ts +6 -8
- package/src/store/tool/slices/builtin/action.test.ts +83 -35
- package/src/store/tool/slices/builtin/action.ts +0 -9
- package/src/store/tool/slices/builtin/selectors.test.ts +4 -30
- package/src/store/tool/slices/builtin/selectors.ts +15 -21
- package/src/tools/index.ts +0 -6
- package/src/tools/renders.ts +0 -3
- package/src/tools/web-browsing/Portal/Search/Footer.tsx +2 -2
- package/packages/const/src/guide.ts +0 -89
- package/packages/context-engine/src/providers/InboxGuide.ts +0 -102
- package/packages/context-engine/src/providers/__tests__/InboxGuideProvider.test.ts +0 -121
- package/src/services/chat/__snapshots__/chat.test.ts.snap +0 -110
- package/src/store/chat/slices/builtinTool/actions/__tests__/dalle.test.ts +0 -121
- package/src/store/chat/slices/builtinTool/actions/dalle.ts +0 -124
- package/src/tools/dalle/Render/GalleyGrid.tsx +0 -60
- package/src/tools/dalle/Render/Item/EditMode.tsx +0 -66
- package/src/tools/dalle/Render/Item/Error.tsx +0 -49
- package/src/tools/dalle/Render/Item/Image.tsx +0 -44
- package/src/tools/dalle/Render/Item/ImageFileItem.tsx +0 -57
- package/src/tools/dalle/Render/Item/index.tsx +0 -88
- package/src/tools/dalle/Render/ToolBar.tsx +0 -56
- package/src/tools/dalle/Render/index.tsx +0 -52
- package/src/tools/dalle/index.ts +0 -92
|
@@ -9,7 +9,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
9
9
|
import { ActionKeys } from '@/features/ChatInput/ActionBar/config';
|
|
10
10
|
import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
|
|
11
11
|
import { useChatStore } from '@/store/chat';
|
|
12
|
-
import {
|
|
12
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
13
13
|
|
|
14
14
|
import ActionBar from './ActionBar';
|
|
15
15
|
import Files from './Files';
|
|
@@ -37,7 +37,7 @@ const MobileChatInput = memo(() => {
|
|
|
37
37
|
const { isLoading } = useInitAgentConfig();
|
|
38
38
|
|
|
39
39
|
const [loading, value, onInput, onStop] = useChatStore((s) => [
|
|
40
|
-
|
|
40
|
+
messageStateSelectors.isAIGenerating(s),
|
|
41
41
|
s.inputMessage,
|
|
42
42
|
s.updateInputMessage,
|
|
43
43
|
s.stopGenerateMessage,
|
|
@@ -6,7 +6,7 @@ import { useGeminiChineseWarning } from '@/hooks/useGeminiChineseWarning';
|
|
|
6
6
|
import { getAgentStoreState } from '@/store/agent';
|
|
7
7
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
8
8
|
import { useChatStore } from '@/store/chat';
|
|
9
|
-
import { chatSelectors, topicSelectors } from '@/store/chat/selectors';
|
|
9
|
+
import { chatSelectors, messageStateSelectors, topicSelectors } from '@/store/chat/selectors';
|
|
10
10
|
import { fileChatSelectors, useFileStore } from '@/store/file';
|
|
11
11
|
import { getUserStoreState } from '@/store/user';
|
|
12
12
|
|
|
@@ -26,17 +26,19 @@ export const useSendMessage = () => {
|
|
|
26
26
|
const clearChatUploadFileList = useFileStore((s) => s.clearChatUploadFileList);
|
|
27
27
|
|
|
28
28
|
const isUploadingFiles = useFileStore(fileChatSelectors.isUploadingFiles);
|
|
29
|
-
const isSendButtonDisabledByMessage = useChatStore(
|
|
29
|
+
const isSendButtonDisabledByMessage = useChatStore(
|
|
30
|
+
messageStateSelectors.isSendButtonDisabledByMessage,
|
|
31
|
+
);
|
|
30
32
|
|
|
31
33
|
const canSend = !isUploadingFiles && !isSendButtonDisabledByMessage;
|
|
32
34
|
|
|
33
35
|
const send = useCallback(async (params: UseSendMessageParams = {}) => {
|
|
34
36
|
const store = useChatStore.getState();
|
|
35
|
-
if (
|
|
37
|
+
if (messageStateSelectors.isAIGenerating(store)) return;
|
|
36
38
|
|
|
37
39
|
// if uploading file or send button is disabled by message, then we should not send the message
|
|
38
40
|
const isUploadingFiles = fileChatSelectors.isUploadingFiles(useFileStore.getState());
|
|
39
|
-
const isSendButtonDisabledByMessage =
|
|
41
|
+
const isSendButtonDisabledByMessage = messageStateSelectors.isSendButtonDisabledByMessage(
|
|
40
42
|
useChatStore.getState(),
|
|
41
43
|
);
|
|
42
44
|
|
package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts
CHANGED
|
@@ -5,7 +5,12 @@ import { useGeminiChineseWarning } from '@/hooks/useGeminiChineseWarning';
|
|
|
5
5
|
import { getAgentStoreState } from '@/store/agent';
|
|
6
6
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
7
7
|
import { getChatStoreState, useChatStore } from '@/store/chat';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
aiChatSelectors,
|
|
10
|
+
chatSelectors,
|
|
11
|
+
messageStateSelectors,
|
|
12
|
+
topicSelectors,
|
|
13
|
+
} from '@/store/chat/selectors';
|
|
9
14
|
import { fileChatSelectors, useFileStore } from '@/store/file';
|
|
10
15
|
import { mentionSelectors, useMentionStore } from '@/store/mention';
|
|
11
16
|
import { useSessionStore } from '@/store/session';
|
|
@@ -38,8 +43,8 @@ export const useSend = () => {
|
|
|
38
43
|
s.addAIMessage,
|
|
39
44
|
s.stopGenerateMessage,
|
|
40
45
|
s.cancelSendMessageInServer,
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
messageStateSelectors.isAIGenerating(s),
|
|
47
|
+
messageStateSelectors.isSendButtonDisabledByMessage(s),
|
|
43
48
|
aiChatSelectors.isCurrentSendMessageLoading(s),
|
|
44
49
|
]);
|
|
45
50
|
const { analytics } = useAnalytics();
|
|
@@ -68,7 +73,7 @@ export const useSend = () => {
|
|
|
68
73
|
return;
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
if (
|
|
76
|
+
if (messageStateSelectors.isAIGenerating(store)) return;
|
|
72
77
|
|
|
73
78
|
const inputMessage = store.inputMessage;
|
|
74
79
|
// 发送时再取一次最新的文件列表,防止闭包拿到旧值
|
|
@@ -127,7 +132,7 @@ export const useSend = () => {
|
|
|
127
132
|
|
|
128
133
|
const stop = () => {
|
|
129
134
|
const store = getChatStoreState();
|
|
130
|
-
const generating =
|
|
135
|
+
const generating = messageStateSelectors.isAIGenerating(store);
|
|
131
136
|
|
|
132
137
|
if (generating) {
|
|
133
138
|
stopGenerateMessage();
|
|
@@ -165,8 +170,8 @@ export const useSendGroupMessage = () => {
|
|
|
165
170
|
s.sendGroupMessage,
|
|
166
171
|
s.updateInputMessage,
|
|
167
172
|
s.stopGenerateMessage,
|
|
168
|
-
|
|
169
|
-
|
|
173
|
+
messageStateSelectors.isSendButtonDisabledByMessage(s),
|
|
174
|
+
messageStateSelectors.isCreatingMessage(s),
|
|
170
175
|
]);
|
|
171
176
|
|
|
172
177
|
const isSupervisorThinking = useChatStore((s) =>
|
|
@@ -205,7 +210,7 @@ export const useSendGroupMessage = () => {
|
|
|
205
210
|
|
|
206
211
|
if (
|
|
207
212
|
chatSelectors.isSupervisorLoading(store.activeId)(store) ||
|
|
208
|
-
|
|
213
|
+
messageStateSelectors.isCreatingMessage(store)
|
|
209
214
|
)
|
|
210
215
|
return;
|
|
211
216
|
|
|
@@ -287,8 +292,8 @@ export const useSendGroupMessage = () => {
|
|
|
287
292
|
|
|
288
293
|
const stop = useCallback(() => {
|
|
289
294
|
const store = getChatStoreState();
|
|
290
|
-
const isAgentGenerating =
|
|
291
|
-
const isCreating =
|
|
295
|
+
const isAgentGenerating = messageStateSelectors.isAIGenerating(store);
|
|
296
|
+
const isCreating = messageStateSelectors.isCreatingMessage(store);
|
|
292
297
|
|
|
293
298
|
if (isAgentGenerating) {
|
|
294
299
|
stopGenerateMessage();
|
package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/index.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import { isDesktop } from '@/const/version';
|
|
|
8
8
|
import { useAgentStore } from '@/store/agent';
|
|
9
9
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
10
10
|
import { useChatStore } from '@/store/chat';
|
|
11
|
-
import {
|
|
11
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
12
12
|
import { useGlobalStore } from '@/store/global';
|
|
13
13
|
import { useSessionStore } from '@/store/session';
|
|
14
14
|
import { sessionHelpers } from '@/store/session/helpers';
|
|
@@ -33,7 +33,9 @@ const SessionItem = memo<SessionItemProps>(({ id }) => {
|
|
|
33
33
|
const openSessionInNewWindow = useGlobalStore((s) => s.openSessionInNewWindow);
|
|
34
34
|
|
|
35
35
|
const [active] = useSessionStore((s) => [s.activeId === id]);
|
|
36
|
-
const [loading] = useChatStore((s) => [
|
|
36
|
+
const [loading] = useChatStore((s) => [
|
|
37
|
+
messageStateSelectors.isAIGenerating(s) && id === s.activeId,
|
|
38
|
+
]);
|
|
37
39
|
|
|
38
40
|
const [pin, title, avatar, avatarBackground, updateAt, members, model, group, sessionType] =
|
|
39
41
|
useSessionStore((s) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ChatCitationItem } from '@lobechat/types';
|
|
2
|
-
import {
|
|
2
|
+
import { CopyButton, Icon, Markdown, ScrollShadow } from '@lobehub/ui';
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
4
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
5
|
-
import { AtomIcon
|
|
5
|
+
import { AtomIcon } from 'lucide-react';
|
|
6
6
|
import { rgba } from 'polished';
|
|
7
7
|
import { CSSProperties, RefObject, memo, useEffect, useRef, useState } from 'react';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
@@ -24,8 +24,10 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
24
24
|
color: ${token.colorTextTertiary};
|
|
25
25
|
`,
|
|
26
26
|
header: css`
|
|
27
|
+
min-height: 32px;
|
|
27
28
|
padding-block: 4px;
|
|
28
29
|
padding-inline: 8px 4px;
|
|
30
|
+
|
|
29
31
|
transition: background 0.2s ${token.motionEaseOut};
|
|
30
32
|
transition: all 0.2s ${token.motionEaseOut};
|
|
31
33
|
|
|
@@ -165,7 +167,6 @@ const Thinking = memo<ThinkingProps>((props) => {
|
|
|
165
167
|
<CopyButton content={content} size={'small'} title={t('copy', { ns: 'common' })} />
|
|
166
168
|
</div>
|
|
167
169
|
)}
|
|
168
|
-
<ActionIcon icon={showDetail ? ChevronDown : ChevronRight} size={'small'} />
|
|
169
170
|
</Flexbox>
|
|
170
171
|
</Flexbox>
|
|
171
172
|
<AnimatePresence initial={false}>
|
|
@@ -34,8 +34,8 @@ const AgentPlugin = memo(() => {
|
|
|
34
34
|
s.toggleAgentPlugin,
|
|
35
35
|
]);
|
|
36
36
|
|
|
37
|
-
const {
|
|
38
|
-
const installedPlugins = useToolStore(toolSelectors.metaList
|
|
37
|
+
const { showMarket } = useServerConfigStore(featureFlagsSelectors);
|
|
38
|
+
const installedPlugins = useToolStore(toolSelectors.metaList, isEqual);
|
|
39
39
|
|
|
40
40
|
const { isLoading } = useFetchInstalledPlugins();
|
|
41
41
|
|
|
@@ -8,7 +8,7 @@ import { SWRConfiguration } from 'swr';
|
|
|
8
8
|
import { useAgentStore } from '@/store/agent';
|
|
9
9
|
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
10
10
|
import { useChatStore } from '@/store/chat';
|
|
11
|
-
import {
|
|
11
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
12
12
|
import { useGlobalStore } from '@/store/global';
|
|
13
13
|
import { globalGeneralSelectors } from '@/store/global/selectors';
|
|
14
14
|
import { useUserStore } from '@/store/user';
|
|
@@ -43,7 +43,7 @@ const BrowserSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
43
43
|
const { t } = useTranslation('chat');
|
|
44
44
|
|
|
45
45
|
const [loading, updateInputMessage] = useChatStore((s) => [
|
|
46
|
-
|
|
46
|
+
messageStateSelectors.isAIGenerating(s),
|
|
47
47
|
s.updateInputMessage,
|
|
48
48
|
]);
|
|
49
49
|
|
|
@@ -11,7 +11,7 @@ import { API_ENDPOINTS } from '@/services/_url';
|
|
|
11
11
|
import { useAgentStore } from '@/store/agent';
|
|
12
12
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
13
13
|
import { useChatStore } from '@/store/chat';
|
|
14
|
-
import {
|
|
14
|
+
import { messageStateSelectors } from '@/store/chat/slices/message/selectors';
|
|
15
15
|
import { useGlobalStore } from '@/store/global';
|
|
16
16
|
import { globalGeneralSelectors } from '@/store/global/selectors';
|
|
17
17
|
import { useUserStore } from '@/store/user';
|
|
@@ -54,7 +54,7 @@ const OpenaiSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
54
54
|
const { t } = useTranslation('chat');
|
|
55
55
|
|
|
56
56
|
const [loading, updateInputMessage] = useChatStore((s) => [
|
|
57
|
-
|
|
57
|
+
messageStateSelectors.isAIGenerating(s),
|
|
58
58
|
s.updateInputMessage,
|
|
59
59
|
]);
|
|
60
60
|
|
|
@@ -9,7 +9,6 @@ import { useCheckPluginsIsInstalled } from '@/hooks/useCheckPluginsIsInstalled';
|
|
|
9
9
|
import { useFetchInstalledPlugins } from '@/hooks/useFetchInstalledPlugins';
|
|
10
10
|
import { useAgentStore } from '@/store/agent';
|
|
11
11
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
12
|
-
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
13
12
|
import { useToolStore } from '@/store/tool';
|
|
14
13
|
import { builtinToolSelectors, pluginSelectors } from '@/store/tool/selectors';
|
|
15
14
|
|
|
@@ -24,12 +23,11 @@ export const useControls = ({
|
|
|
24
23
|
}) => {
|
|
25
24
|
const { t } = useTranslation('setting');
|
|
26
25
|
const list = useToolStore(pluginSelectors.installedPluginMetaList, isEqual);
|
|
27
|
-
const { showDalle } = useServerConfigStore(featureFlagsSelectors);
|
|
28
26
|
const [checked, togglePlugin] = useAgentStore((s) => [
|
|
29
27
|
agentSelectors.currentAgentPlugins(s),
|
|
30
28
|
s.togglePlugin,
|
|
31
29
|
]);
|
|
32
|
-
const builtinList = useToolStore(builtinToolSelectors.metaList
|
|
30
|
+
const builtinList = useToolStore(builtinToolSelectors.metaList, isEqual);
|
|
33
31
|
const enablePluginCount = useAgentStore(
|
|
34
32
|
(s) =>
|
|
35
33
|
agentSelectors
|
|
@@ -4,18 +4,19 @@ import { memo } from 'react';
|
|
|
4
4
|
import { Flexbox } from 'react-layout-kit';
|
|
5
5
|
|
|
6
6
|
interface ErrorJSONViewerProps {
|
|
7
|
+
block?: boolean;
|
|
7
8
|
error?: ChatMessageError | null;
|
|
8
9
|
id: string;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
const ErrorJsonViewer = memo<ErrorJSONViewerProps>(({ error, id }) => {
|
|
12
|
+
const ErrorJsonViewer = memo<ErrorJSONViewerProps>(({ error, id, block }) => {
|
|
12
13
|
const errorBody = error?.body || error;
|
|
13
14
|
|
|
14
15
|
if (!errorBody) return;
|
|
15
16
|
|
|
16
17
|
return (
|
|
17
|
-
<Flexbox id={id} style={{ maxWidth: 600 }}>
|
|
18
|
-
<Highlighter actionIconSize={'small'} language={'json'}>
|
|
18
|
+
<Flexbox id={id} style={{ maxWidth: block ? '100%' : 600, width: block ? '100%' : undefined }}>
|
|
19
|
+
<Highlighter actionIconSize={'small'} language={'json'} wrap>
|
|
19
20
|
{JSON.stringify(errorBody, null, 2)}
|
|
20
21
|
</Highlighter>
|
|
21
22
|
</Flexbox>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChatMessageError } from '@lobechat/types';
|
|
2
2
|
import { Skeleton } from 'antd';
|
|
3
3
|
import dynamic from 'next/dynamic';
|
|
4
4
|
import { memo } from 'react';
|
|
@@ -24,7 +24,12 @@ interface OllamaErrorResponse {
|
|
|
24
24
|
|
|
25
25
|
const UNRESOLVED_MODEL_REGEXP = /model "([\w+,-_]+)" not found/;
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
interface OllamaBizErrorProps {
|
|
28
|
+
error?: ChatMessageError | null;
|
|
29
|
+
id: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const OllamaBizError = memo<OllamaBizErrorProps>(({ error, id }) => {
|
|
28
33
|
const errorBody: OllamaErrorResponse = (error as any)?.body;
|
|
29
34
|
|
|
30
35
|
const errorMessage = errorBody.error?.message;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '@lobechat/model-runtime';
|
|
2
|
-
import { ChatErrorType, ChatMessageError, ErrorType
|
|
2
|
+
import { ChatErrorType, ChatMessageError, ErrorType } from '@lobechat/types';
|
|
3
3
|
import { IPluginErrorType } from '@lobehub/chat-plugin-sdk';
|
|
4
4
|
import type { AlertProps } from '@lobehub/ui';
|
|
5
5
|
import { Skeleton } from 'antd';
|
|
@@ -15,6 +15,11 @@ import ErrorJsonViewer from './ErrorJsonViewer';
|
|
|
15
15
|
import InvalidAccessCode from './InvalidAccessCode';
|
|
16
16
|
import { ErrorActionContainer } from './style';
|
|
17
17
|
|
|
18
|
+
interface ErrorMessageData {
|
|
19
|
+
error?: ChatMessageError | null;
|
|
20
|
+
id: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
const loading = () => <Skeleton active />;
|
|
19
24
|
|
|
20
25
|
const OllamaBizError = dynamic(() => import('./OllamaBizError'), { loading, ssr: false });
|
|
@@ -87,7 +92,12 @@ export const useErrorContent = (error: any) => {
|
|
|
87
92
|
}, [error]);
|
|
88
93
|
};
|
|
89
94
|
|
|
90
|
-
|
|
95
|
+
interface ErrorExtraProps {
|
|
96
|
+
block?: boolean;
|
|
97
|
+
data: ErrorMessageData;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const ErrorMessageExtra = memo<ErrorExtraProps>(({ data, block }) => {
|
|
91
101
|
const error = data.error as ChatMessageError;
|
|
92
102
|
if (!error?.type) return;
|
|
93
103
|
|
|
@@ -123,10 +133,10 @@ const ErrorMessageExtra = memo<{ data: UIChatMessage }>(({ data }) => {
|
|
|
123
133
|
return <ChatInvalidAPIKey id={data.id} provider={data.error?.body?.provider} />;
|
|
124
134
|
}
|
|
125
135
|
|
|
126
|
-
return <ErrorJsonViewer error={data.error} id={data.id} />;
|
|
136
|
+
return <ErrorJsonViewer block={block} error={data.error} id={data.id} />;
|
|
127
137
|
});
|
|
128
138
|
|
|
129
|
-
export default memo<
|
|
139
|
+
export default memo<ErrorExtraProps>(({ data, block }) => (
|
|
130
140
|
<Suspense
|
|
131
141
|
fallback={
|
|
132
142
|
<ErrorActionContainer>
|
|
@@ -134,6 +144,6 @@ export default memo<{ data: UIChatMessage }>(({ data }) => (
|
|
|
134
144
|
</ErrorActionContainer>
|
|
135
145
|
}
|
|
136
146
|
>
|
|
137
|
-
<ErrorMessageExtra data={data} />
|
|
147
|
+
<ErrorMessageExtra block={block} data={data} />
|
|
138
148
|
</Suspense>
|
|
139
149
|
));
|
|
@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
7
7
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
9
|
import { useChatStore } from '@/store/chat';
|
|
10
|
-
import { chatPortalSelectors,
|
|
10
|
+
import { chatPortalSelectors, messageStateSelectors } from '@/store/chat/selectors';
|
|
11
11
|
import { dotLoading } from '@/styles/loading';
|
|
12
12
|
|
|
13
13
|
import { InPortalThreadContext } from '../../../context/InPortalThreadContext';
|
|
@@ -66,7 +66,7 @@ const Render = memo<ArtifactProps>(({ identifier, title, type, language, childre
|
|
|
66
66
|
const { message } = App.useApp();
|
|
67
67
|
const [isGenerating, isArtifactTagClosed, openArtifact, closeArtifact] = useChatStore((s) => {
|
|
68
68
|
return [
|
|
69
|
-
|
|
69
|
+
messageStateSelectors.isMessageGenerating(id)(s),
|
|
70
70
|
chatPortalSelectors.isArtifactTagClosed(id)(s),
|
|
71
71
|
s.openArtifact,
|
|
72
72
|
s.closeArtifact,
|
|
@@ -8,7 +8,7 @@ import TTS from '@/features/Conversation/components/Extras/TTS';
|
|
|
8
8
|
import Translate from '@/features/Conversation/components/Extras/Translate';
|
|
9
9
|
import Usage from '@/features/Conversation/components/Extras/Usage';
|
|
10
10
|
import { useChatStore } from '@/store/chat';
|
|
11
|
-
import {
|
|
11
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
12
12
|
|
|
13
13
|
interface AssistantMessageExtraProps {
|
|
14
14
|
content: string;
|
|
@@ -20,7 +20,7 @@ interface AssistantMessageExtraProps {
|
|
|
20
20
|
|
|
21
21
|
export const AssistantMessageExtra = memo<AssistantMessageExtraProps>(
|
|
22
22
|
({ extra, id, content, metadata, tools }) => {
|
|
23
|
-
const loading = useChatStore(
|
|
23
|
+
const loading = useChatStore(messageStateSelectors.isMessageGenerating(id));
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
26
|
<Flexbox gap={8} style={{ marginTop: !!tools?.length ? 8 : 4 }}>
|
|
@@ -4,7 +4,7 @@ import { ReactNode, memo } from 'react';
|
|
|
4
4
|
import { Flexbox } from 'react-layout-kit';
|
|
5
5
|
|
|
6
6
|
import { useChatStore } from '@/store/chat';
|
|
7
|
-
import { aiChatSelectors,
|
|
7
|
+
import { aiChatSelectors, messageStateSelectors } from '@/store/chat/selectors';
|
|
8
8
|
|
|
9
9
|
import { DefaultMessage } from '../Default';
|
|
10
10
|
import ImageFileListViewer from '../User/ImageFileListViewer';
|
|
@@ -19,8 +19,10 @@ export const AssistantMessageContent = memo<
|
|
|
19
19
|
editableContent: ReactNode;
|
|
20
20
|
}
|
|
21
21
|
>(({ id, tools, content, chunksList, search, imageList, ...props }) => {
|
|
22
|
-
const editing = useChatStore(
|
|
23
|
-
|
|
22
|
+
const [editing, generating] = useChatStore((s) => [
|
|
23
|
+
messageStateSelectors.isMessageEditing(id)(s),
|
|
24
|
+
messageStateSelectors.isMessageGenerating(id)(s),
|
|
25
|
+
]);
|
|
24
26
|
|
|
25
27
|
const isToolCallGenerating = generating && (content === LOADING_FLAT || !content) && !!tools;
|
|
26
28
|
|
|
@@ -5,7 +5,7 @@ import { ReactNode, memo } from 'react';
|
|
|
5
5
|
import { Flexbox } from 'react-layout-kit';
|
|
6
6
|
|
|
7
7
|
import { useChatStore } from '@/store/chat';
|
|
8
|
-
import {
|
|
8
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
9
9
|
import { shinyTextStylish } from '@/styles/loading';
|
|
10
10
|
|
|
11
11
|
export const useStyles = createStyles(({ css, token }) => ({
|
|
@@ -38,7 +38,7 @@ const BuiltinPluginTitle = memo<BuiltinPluginTitleProps>(
|
|
|
38
38
|
const { styles } = useStyles();
|
|
39
39
|
|
|
40
40
|
const isLoading = useChatStore(
|
|
41
|
-
|
|
41
|
+
messageStateSelectors.isToolApiNameShining(messageId, index, toolCallId),
|
|
42
42
|
);
|
|
43
43
|
|
|
44
44
|
return (
|
|
@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
9
|
import { useChatStore } from '@/store/chat';
|
|
10
|
-
import {
|
|
10
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
11
11
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
12
12
|
import { toolSelectors } from '@/store/tool/selectors';
|
|
13
13
|
import { shinyTextStylish } from '@/styles/loading';
|
|
@@ -43,7 +43,9 @@ const ToolTitle = memo<ToolTitleProps>(({ identifier, messageId, index, apiName,
|
|
|
43
43
|
const { t } = useTranslation('plugin');
|
|
44
44
|
const { styles } = useStyles();
|
|
45
45
|
|
|
46
|
-
const isLoading = useChatStore(
|
|
46
|
+
const isLoading = useChatStore(
|
|
47
|
+
messageStateSelectors.isToolApiNameShining(messageId, index, toolCallId),
|
|
48
|
+
);
|
|
47
49
|
|
|
48
50
|
const pluginMeta = useToolStore(toolSelectors.getMetaById(identifier), isEqual);
|
|
49
51
|
|
|
@@ -10,7 +10,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
10
10
|
import PluginResult from '@/features/Conversation/Messages/Assistant/Tool/Inspector/PluginResult';
|
|
11
11
|
import PluginRender from '@/features/PluginsUI/Render';
|
|
12
12
|
import { useChatStore } from '@/store/chat';
|
|
13
|
-
import {
|
|
13
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
14
14
|
|
|
15
15
|
import Arguments from './Arguments';
|
|
16
16
|
import KeyValueEditor from './KeyValueEditor';
|
|
@@ -43,7 +43,7 @@ const CustomRender = memo<CustomRenderProps>(
|
|
|
43
43
|
tool_call_id,
|
|
44
44
|
}) => {
|
|
45
45
|
const { t } = useTranslation(['tool', 'common']);
|
|
46
|
-
const [loading] = useChatStore((s) => [
|
|
46
|
+
const [loading] = useChatStore((s) => [messageStateSelectors.isPluginApiInvoking(id)(s)]);
|
|
47
47
|
const [isEditing, setIsEditing] = useState(false);
|
|
48
48
|
const { message } = App.useApp();
|
|
49
49
|
const [updatePluginArguments, reInvokeToolMessage] = useChatStore((s) => [
|
|
@@ -3,7 +3,7 @@ import isEqual from 'fast-deep-equal';
|
|
|
3
3
|
import { Suspense, memo } from 'react';
|
|
4
4
|
|
|
5
5
|
import { useChatStore } from '@/store/chat';
|
|
6
|
-
import { chatSelectors } from '@/store/chat/selectors';
|
|
6
|
+
import { chatSelectors, messageStateSelectors } from '@/store/chat/selectors';
|
|
7
7
|
|
|
8
8
|
import CustomRender from './CustomRender';
|
|
9
9
|
import ErrorResponse from './ErrorResponse';
|
|
@@ -31,7 +31,7 @@ const Render = memo<RenderProps>(
|
|
|
31
31
|
identifier,
|
|
32
32
|
apiName,
|
|
33
33
|
}) => {
|
|
34
|
-
const loading = useChatStore(
|
|
34
|
+
const loading = useChatStore(messageStateSelectors.isToolCallStreaming(messageId, toolIndex));
|
|
35
35
|
const toolMessage = useChatStore(chatSelectors.getMessageByToolCallId(toolCallId), isEqual);
|
|
36
36
|
|
|
37
37
|
if (loading || !toolMessage) return null;
|
|
@@ -3,7 +3,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
3
3
|
|
|
4
4
|
import AnimatedCollapsed from '@/components/AnimatedCollapsed';
|
|
5
5
|
import { useChatStore } from '@/store/chat';
|
|
6
|
-
import {
|
|
6
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
7
7
|
|
|
8
8
|
import Inspectors from './Inspector';
|
|
9
9
|
import Render from './Render';
|
|
@@ -24,7 +24,7 @@ const Tool = memo<InspectorProps>(
|
|
|
24
24
|
({ arguments: requestArgs, apiName, messageId, id, index, identifier, style, payload, type }) => {
|
|
25
25
|
const [showDetail, setShowDetail] = useState(type !== 'mcp');
|
|
26
26
|
const [showPluginRender, setShowPluginRender] = useState(false);
|
|
27
|
-
const isLoading = useChatStore(
|
|
27
|
+
const isLoading = useChatStore(messageStateSelectors.isInToolsCalling(messageId, index));
|
|
28
28
|
|
|
29
29
|
useEffect(() => {
|
|
30
30
|
if (type !== 'mcp') return;
|
|
@@ -19,7 +19,7 @@ import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
|
19
19
|
import { useAgentStore } from '@/store/agent';
|
|
20
20
|
import { agentChatConfigSelectors } from '@/store/agent/selectors';
|
|
21
21
|
import { useChatStore } from '@/store/chat';
|
|
22
|
-
import {
|
|
22
|
+
import { messageStateSelectors } from '@/store/chat/slices/message/selectors';
|
|
23
23
|
import { chatGroupSelectors, useChatGroupStore } from '@/store/chatGroup';
|
|
24
24
|
import { useGlobalStore } from '@/store/global';
|
|
25
25
|
import { useSessionStore } from '@/store/session';
|
|
@@ -81,9 +81,9 @@ const AssistantMessage = memo<AssistantMessageProps>((props) => {
|
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
const [generating, isInRAGFlow, editing] = useChatStore((s) => [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
messageStateSelectors.isMessageGenerating(id)(s),
|
|
85
|
+
messageStateSelectors.isMessageInRAGFlow(id)(s),
|
|
86
|
+
messageStateSelectors.isMessageEditing(id)(s),
|
|
87
87
|
]);
|
|
88
88
|
|
|
89
89
|
const { styles } = useStyles({
|
|
@@ -4,7 +4,7 @@ import { ReactNode, memo } from 'react';
|
|
|
4
4
|
import BubblesLoading from '@/components/BubblesLoading';
|
|
5
5
|
import { LOADING_FLAT } from '@/const/message';
|
|
6
6
|
import { useChatStore } from '@/store/chat';
|
|
7
|
-
import {
|
|
7
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
8
8
|
|
|
9
9
|
export const DefaultMessage = memo<
|
|
10
10
|
UIChatMessage & {
|
|
@@ -13,7 +13,7 @@ export const DefaultMessage = memo<
|
|
|
13
13
|
isToolCallGenerating?: boolean;
|
|
14
14
|
}
|
|
15
15
|
>(({ id, editableContent, content, isToolCallGenerating, addIdOnDOM = true }) => {
|
|
16
|
-
const editing = useChatStore(
|
|
16
|
+
const editing = useChatStore(messageStateSelectors.isMessageEditing(id));
|
|
17
17
|
|
|
18
18
|
if (isToolCallGenerating) return;
|
|
19
19
|
|
|
@@ -5,7 +5,7 @@ import ExtraContainer from '@/features/Conversation/components/Extras/ExtraConta
|
|
|
5
5
|
import TTS from '@/features/Conversation/components/Extras/TTS';
|
|
6
6
|
import Translate from '@/features/Conversation/components/Extras/Translate';
|
|
7
7
|
import { useChatStore } from '@/store/chat';
|
|
8
|
-
import {
|
|
8
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
9
9
|
|
|
10
10
|
interface UserMessageExtraProps {
|
|
11
11
|
content: string;
|
|
@@ -13,7 +13,7 @@ interface UserMessageExtraProps {
|
|
|
13
13
|
id: string;
|
|
14
14
|
}
|
|
15
15
|
export const UserMessageExtra = memo<UserMessageExtraProps>(({ extra, id, content }) => {
|
|
16
|
-
const loading = useChatStore(
|
|
16
|
+
const loading = useChatStore(messageStateSelectors.isMessageGenerating(id));
|
|
17
17
|
|
|
18
18
|
const showTranslate = !!extra?.translate;
|
|
19
19
|
const showTTS = !!extra?.tts;
|
|
@@ -15,7 +15,7 @@ import { useUserAvatar } from '@/hooks/useUserAvatar';
|
|
|
15
15
|
import { useAgentStore } from '@/store/agent';
|
|
16
16
|
import { agentChatConfigSelectors } from '@/store/agent/selectors';
|
|
17
17
|
import { useChatStore } from '@/store/chat';
|
|
18
|
-
import {
|
|
18
|
+
import { messageStateSelectors } from '@/store/chat/selectors';
|
|
19
19
|
import { useSessionStore } from '@/store/session';
|
|
20
20
|
import { sessionSelectors } from '@/store/session/selectors';
|
|
21
21
|
import { useUserStore } from '@/store/user';
|
|
@@ -55,9 +55,9 @@ const UserMessage = memo<UserMessageProps>((props) => {
|
|
|
55
55
|
const displayMode = useAgentStore(agentChatConfigSelectors.displayMode);
|
|
56
56
|
|
|
57
57
|
const [editing, generating, isInRAGFlow] = useChatStore((s) => [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
messageStateSelectors.isMessageEditing(id)(s),
|
|
59
|
+
messageStateSelectors.isMessageGenerating(id)(s),
|
|
60
|
+
messageStateSelectors.isMessageInRAGFlow(id)(s),
|
|
61
61
|
]);
|
|
62
62
|
|
|
63
63
|
const loading = isInRAGFlow || generating;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { isDesktop } from '@lobechat/const';
|
|
3
4
|
import { createStyles } from 'antd-style';
|
|
4
5
|
import isEqual from 'fast-deep-equal';
|
|
5
6
|
import { ReactNode, memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
6
7
|
import { Flexbox } from 'react-layout-kit';
|
|
7
8
|
|
|
8
|
-
import { isDesktop } from '@/const/version';
|
|
9
9
|
import {
|
|
10
10
|
removeVirtuosoVisibleItem,
|
|
11
11
|
upsertVirtuosoVisibleItem,
|
|
12
12
|
} from '@/features/Conversation/components/VirtualizedList/VirtuosoContext';
|
|
13
13
|
import { useChatStore } from '@/store/chat';
|
|
14
|
-
import { chatSelectors } from '@/store/chat/selectors';
|
|
14
|
+
import { chatSelectors, messageStateSelectors } from '@/store/chat/selectors';
|
|
15
15
|
|
|
16
16
|
import History from '../components/History';
|
|
17
17
|
import { InPortalThreadContext } from '../context/InPortalThreadContext';
|
|
@@ -57,7 +57,7 @@ const Item = memo<ChatListItemProps>(
|
|
|
57
57
|
|
|
58
58
|
const item = useChatStore(chatSelectors.getMessageById(id), isEqual);
|
|
59
59
|
|
|
60
|
-
const [isMessageLoading] = useChatStore((s) => [
|
|
60
|
+
const [isMessageLoading] = useChatStore((s) => [messageStateSelectors.isMessageLoading(id)(s)]);
|
|
61
61
|
|
|
62
62
|
// ======================= Performance Optimization ======================= //
|
|
63
63
|
// these useMemo/useCallback are all for the performance optimization
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { memo, useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import { useChatStore } from '@/store/chat';
|
|
4
|
-
import { chatSelectors } from '@/store/chat/selectors';
|
|
4
|
+
import { chatSelectors, messageStateSelectors } from '@/store/chat/selectors';
|
|
5
5
|
|
|
6
6
|
import BackBottom from './BackBottom';
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ interface AutoScrollProps {
|
|
|
11
11
|
onScrollToBottom: (type: 'auto' | 'click') => void;
|
|
12
12
|
}
|
|
13
13
|
const AutoScroll = memo<AutoScrollProps>(({ atBottom, isScrolling, onScrollToBottom }) => {
|
|
14
|
-
const trackVisibility = useChatStore(
|
|
14
|
+
const trackVisibility = useChatStore(messageStateSelectors.isAIGenerating);
|
|
15
15
|
const str = useChatStore(chatSelectors.mainAIChatsMessageString);
|
|
16
16
|
const reasoningStr = useChatStore(chatSelectors.mainAILatestMessageReasoningContent);
|
|
17
17
|
|