@lobehub/lobehub 2.0.0-next.35 → 2.0.0-next.36
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/next.config.ts +5 -6
- package/package.json +2 -2
- package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +112 -77
- package/packages/agent-runtime/src/core/runtime.ts +63 -18
- package/packages/agent-runtime/src/types/generalAgent.ts +55 -0
- package/packages/agent-runtime/src/types/index.ts +1 -0
- package/packages/agent-runtime/src/types/instruction.ts +10 -3
- package/packages/const/src/user.ts +0 -1
- package/packages/context-engine/src/processors/GroupMessageFlatten.ts +8 -6
- package/packages/context-engine/src/processors/__tests__/GroupMessageFlatten.test.ts +12 -12
- package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/assistant-group-branches.json +249 -0
- package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/index.ts +4 -0
- package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/multi-assistant-group.json +260 -0
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/active-index-1.json +4 -0
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/assistant-group-branches.json +481 -0
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/conversation.json +5 -1
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/index.ts +4 -0
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/multi-assistant-group.json +407 -0
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/nested.json +18 -2
- package/packages/conversation-flow/src/__tests__/fixtures/outputs/complex-scenario.json +25 -3
- package/packages/conversation-flow/src/__tests__/parse.test.ts +12 -0
- package/packages/conversation-flow/src/index.ts +1 -1
- package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +112 -34
- package/packages/conversation-flow/src/types/flatMessageList.ts +0 -12
- package/packages/conversation-flow/src/{types.ts → types/index.ts} +3 -14
- package/packages/database/src/models/message.ts +18 -19
- package/packages/types/src/aiChat.ts +2 -0
- package/packages/types/src/importer.ts +2 -2
- package/packages/types/src/message/ui/chat.ts +17 -1
- package/packages/types/src/message/ui/extra.ts +2 -2
- package/packages/types/src/message/ui/params.ts +2 -2
- package/packages/types/src/user/preference.ts +0 -4
- package/packages/utils/src/tokenizer/index.ts +3 -11
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/Desktop/MessageFromUrl.tsx +3 -3
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/V1Mobile/index.tsx +1 -1
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/V1Mobile/useSend.ts +3 -3
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/useSend.ts +6 -6
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatList/Content.tsx +5 -3
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatList/WelcomeChatItem/AgentWelcome/OpeningQuestions.tsx +2 -2
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatList/WelcomeChatItem/GroupWelcome/GroupUsageSuggest.tsx +2 -2
- package/src/app/[variants]/(main)/labs/page.tsx +0 -9
- package/src/features/ChatInput/ActionBar/STT/browser.tsx +3 -3
- package/src/features/ChatInput/ActionBar/STT/openai.tsx +3 -3
- package/src/features/Conversation/Error/AccessCodeForm.tsx +1 -1
- package/src/features/Conversation/Error/ChatInvalidApiKey.tsx +1 -1
- package/src/features/Conversation/Error/ClerkLogin/index.tsx +1 -1
- package/src/features/Conversation/Error/OAuthForm.tsx +1 -1
- package/src/features/Conversation/Error/index.tsx +0 -5
- package/src/features/Conversation/Messages/Assistant/Actions/index.tsx +13 -10
- package/src/features/Conversation/Messages/Assistant/Extra/index.test.tsx +3 -8
- package/src/features/Conversation/Messages/Assistant/Extra/index.tsx +2 -6
- package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +7 -9
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/PluginResult.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/PluginState.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/PluginSettings.tsx +4 -1
- package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +2 -3
- package/src/features/Conversation/Messages/Assistant/index.tsx +57 -60
- package/src/features/Conversation/Messages/Default.tsx +1 -0
- package/src/features/Conversation/Messages/Group/Actions/WithContentId.tsx +38 -10
- package/src/features/Conversation/Messages/Group/Actions/index.tsx +1 -1
- package/src/features/Conversation/Messages/Group/ContentBlock.tsx +1 -3
- package/src/features/Conversation/Messages/Group/GroupChildren.tsx +12 -12
- package/src/features/Conversation/Messages/Group/MessageContent.tsx +7 -1
- package/src/features/Conversation/Messages/Group/Tool/Render/PluginSettings.tsx +1 -1
- package/src/features/Conversation/Messages/Group/index.tsx +2 -1
- package/src/features/Conversation/Messages/Supervisor/index.tsx +2 -2
- package/src/features/Conversation/Messages/User/{Actions.tsx → Actions/ActionsBar.tsx} +26 -25
- package/src/features/Conversation/Messages/User/Actions/MessageBranch.tsx +107 -0
- package/src/features/Conversation/Messages/User/Actions/index.tsx +42 -0
- package/src/features/Conversation/Messages/User/index.tsx +43 -44
- package/src/features/Conversation/Messages/index.tsx +3 -3
- package/src/features/Conversation/components/AutoScroll.tsx +3 -3
- package/src/features/Conversation/components/Extras/Usage/UsageDetail/AnimatedNumber.tsx +55 -0
- package/src/features/Conversation/components/Extras/Usage/UsageDetail/index.tsx +5 -2
- package/src/features/Conversation/components/VirtualizedList/index.tsx +29 -20
- package/src/features/Conversation/hooks/useChatListActionsBar.tsx +8 -10
- package/src/features/Portal/Thread/Chat/ChatInput/useSend.ts +3 -3
- package/src/hooks/useHotkeys/chatScope.ts +15 -7
- package/src/server/routers/lambda/__tests__/aiChat.test.ts +1 -1
- package/src/server/routers/lambda/__tests__/integration/message.integration.test.ts +0 -26
- package/src/server/routers/lambda/aiChat.ts +3 -2
- package/src/server/routers/lambda/message.ts +8 -16
- package/src/server/services/message/__tests__/index.test.ts +29 -39
- package/src/server/services/message/index.ts +41 -36
- package/src/services/electron/desktopNotification.ts +6 -6
- package/src/services/electron/file.ts +6 -6
- package/src/services/file/ClientS3/index.ts +8 -8
- package/src/services/message/__tests__/metadata-race-condition.test.ts +157 -0
- package/src/services/message/index.ts +21 -15
- package/src/services/upload.ts +11 -11
- package/src/services/utils/abortableRequest.test.ts +161 -0
- package/src/services/utils/abortableRequest.ts +67 -0
- package/src/store/chat/agents/GeneralChatAgent.ts +137 -0
- package/src/store/chat/agents/createAgentExecutors.ts +395 -0
- package/src/store/chat/helpers.test.ts +0 -99
- package/src/store/chat/helpers.ts +0 -11
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationControl.test.ts +332 -0
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +257 -0
- package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +11 -2
- package/src/store/chat/slices/aiChat/actions/__tests__/rag.test.ts +6 -6
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +391 -0
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingStates.test.ts +179 -0
- package/src/store/chat/slices/aiChat/actions/conversationControl.ts +157 -0
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +329 -0
- package/src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts +14 -14
- package/src/store/chat/slices/aiChat/actions/index.ts +12 -6
- package/src/store/chat/slices/aiChat/actions/rag.ts +9 -6
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +604 -0
- package/src/store/chat/slices/aiChat/actions/streamingStates.ts +84 -0
- package/src/store/chat/slices/builtinTool/actions/__tests__/localSystem.test.ts +4 -4
- package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +11 -11
- package/src/store/chat/slices/builtinTool/actions/interpreter.ts +8 -8
- package/src/store/chat/slices/builtinTool/actions/localSystem.ts +2 -2
- package/src/store/chat/slices/builtinTool/actions/search.ts +8 -8
- package/src/store/chat/slices/message/action.test.ts +79 -68
- package/src/store/chat/slices/message/actions/index.ts +39 -0
- package/src/store/chat/slices/message/actions/internals.ts +77 -0
- package/src/store/chat/slices/message/actions/optimisticUpdate.ts +260 -0
- package/src/store/chat/slices/message/actions/publicApi.ts +224 -0
- package/src/store/chat/slices/message/actions/query.ts +120 -0
- package/src/store/chat/slices/message/actions/runtimeState.ts +108 -0
- package/src/store/chat/slices/message/initialState.ts +13 -0
- package/src/store/chat/slices/message/reducer.test.ts +48 -370
- package/src/store/chat/slices/message/reducer.ts +17 -81
- package/src/store/chat/slices/message/selectors/chat.test.ts +13 -50
- package/src/store/chat/slices/message/selectors/chat.ts +78 -242
- package/src/store/chat/slices/message/selectors/dbMessage.ts +140 -0
- package/src/store/chat/slices/message/selectors/displayMessage.ts +301 -0
- package/src/store/chat/slices/message/selectors/messageState.ts +5 -2
- package/src/store/chat/slices/plugin/action.test.ts +62 -64
- package/src/store/chat/slices/plugin/action.ts +34 -28
- package/src/store/chat/slices/thread/action.test.ts +28 -31
- package/src/store/chat/slices/thread/action.ts +13 -10
- package/src/store/chat/slices/thread/selectors/index.ts +8 -6
- package/src/store/chat/slices/topic/reducer.ts +11 -3
- package/src/store/chat/store.ts +1 -1
- package/src/store/user/slices/preference/selectors/labPrefer.ts +0 -3
- package/packages/database/src/models/__tests__/message.grouping.test.ts +0 -812
- package/packages/database/src/utils/__tests__/groupMessages.test.ts +0 -1132
- package/packages/database/src/utils/groupMessages.ts +0 -361
- package/packages/utils/src/tokenizer/client.ts +0 -35
- package/packages/utils/src/tokenizer/estimated.ts +0 -4
- package/packages/utils/src/tokenizer/server.ts +0 -11
- package/packages/utils/src/tokenizer/tokenizer.worker.ts +0 -12
- package/src/app/(backend)/webapi/tokenizer/index.test.ts +0 -32
- package/src/app/(backend)/webapi/tokenizer/route.ts +0 -8
- package/src/features/Conversation/Error/InvalidAccessCode.tsx +0 -79
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +0 -975
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +0 -1050
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +0 -720
- package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +0 -849
- package/src/store/chat/slices/message/action.ts +0 -629
|
@@ -19,7 +19,7 @@ const AccessCodeForm = memo<AccessCodeFormProps>(({ id }) => {
|
|
|
19
19
|
keyVaultsConfigSelectors.password(s),
|
|
20
20
|
s.updateKeyVaults,
|
|
21
21
|
]);
|
|
22
|
-
const [resend, deleteMessage] = useChatStore((s) => [s.
|
|
22
|
+
const [resend, deleteMessage] = useChatStore((s) => [s.delAndRegenerateMessage, s.deleteMessage]);
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
25
|
<>
|
|
@@ -13,7 +13,7 @@ interface ChatInvalidAPIKeyProps {
|
|
|
13
13
|
const ChatInvalidAPIKey = memo<ChatInvalidAPIKeyProps>(({ id, provider }) => {
|
|
14
14
|
const { t } = useTranslation('modelProvider');
|
|
15
15
|
const { t: modelProviderErrorT } = useTranslation(['modelProvider', 'error']);
|
|
16
|
-
const [resend, deleteMessage] = useChatStore((s) => [s.
|
|
16
|
+
const [resend, deleteMessage] = useChatStore((s) => [s.delAndRegenerateMessage, s.deleteMessage]);
|
|
17
17
|
const providerName = useProviderName(provider as GlobalLLMProviderKey);
|
|
18
18
|
|
|
19
19
|
return (
|
|
@@ -15,7 +15,7 @@ const ClerkLogin = memo<{ id: string }>(({ id }) => {
|
|
|
15
15
|
const [openSignIn, isSignedIn] = useUserStore((s) => [s.openLogin, s.isSignedIn]);
|
|
16
16
|
const greeting = useGreeting();
|
|
17
17
|
const nickName = useUserStore(userProfileSelectors.nickName);
|
|
18
|
-
const [resend, deleteMessage] = useChatStore((s) => [s.
|
|
18
|
+
const [resend, deleteMessage] = useChatStore((s) => [s.delAndRegenerateMessage, s.deleteMessage]);
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<ErrorActionContainer>
|
|
@@ -18,7 +18,7 @@ const OAuthForm = memo<{ id: string }>(({ id }) => {
|
|
|
18
18
|
const user = useUserStore(userProfileSelectors.userProfile);
|
|
19
19
|
const isOAuthLoggedIn = useUserStore(authSelectors.isLoginWithAuth);
|
|
20
20
|
|
|
21
|
-
const [resend, deleteMessage] = useChatStore((s) => [s.
|
|
21
|
+
const [resend, deleteMessage] = useChatStore((s) => [s.delAndRegenerateMessage, s.deleteMessage]);
|
|
22
22
|
|
|
23
23
|
const { message, modal } = App.useApp();
|
|
24
24
|
|
|
@@ -12,7 +12,6 @@ import { useProviderName } from '@/hooks/useProviderName';
|
|
|
12
12
|
import ChatInvalidAPIKey from './ChatInvalidApiKey';
|
|
13
13
|
import ClerkLogin from './ClerkLogin';
|
|
14
14
|
import ErrorJsonViewer from './ErrorJsonViewer';
|
|
15
|
-
import InvalidAccessCode from './InvalidAccessCode';
|
|
16
15
|
import { ErrorActionContainer } from './style';
|
|
17
16
|
|
|
18
17
|
interface ErrorMessageData {
|
|
@@ -118,10 +117,6 @@ const ErrorMessageExtra = memo<ErrorExtraProps>(({ data, block }) => {
|
|
|
118
117
|
return <ClerkLogin id={data.id} />;
|
|
119
118
|
}
|
|
120
119
|
|
|
121
|
-
case ChatErrorType.InvalidAccessCode: {
|
|
122
|
-
return <InvalidAccessCode id={data.id} provider={data.error?.body?.provider} />;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
120
|
case AgentRuntimeErrorType.NoOpenAIAPIKey: {
|
|
126
121
|
{
|
|
127
122
|
return <ChatInvalidAPIKey id={data.id} provider={data.error?.body?.provider} />;
|
|
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
8
|
import ShareMessageModal from '@/features/Conversation/components/ShareMessageModal';
|
|
9
9
|
import { VirtuosoContext } from '@/features/Conversation/components/VirtualizedList/VirtuosoContext';
|
|
10
10
|
import { useChatStore } from '@/store/chat';
|
|
11
|
-
import { threadSelectors } from '@/store/chat/selectors';
|
|
11
|
+
import { messageStateSelectors, threadSelectors } from '@/store/chat/selectors';
|
|
12
12
|
import { useSessionStore } from '@/store/session';
|
|
13
13
|
import { sessionSelectors } from '@/store/session/selectors';
|
|
14
14
|
|
|
@@ -23,9 +23,10 @@ interface AssistantActionsProps {
|
|
|
23
23
|
}
|
|
24
24
|
export const AssistantActionsBar = memo<AssistantActionsProps>(({ id, data, index }) => {
|
|
25
25
|
const { error, tools } = data;
|
|
26
|
-
const [isThreadMode, hasThread] = useChatStore((s) => [
|
|
26
|
+
const [isThreadMode, hasThread, isRegenerating] = useChatStore((s) => [
|
|
27
27
|
!!s.activeThreadId,
|
|
28
28
|
threadSelectors.hasThreadBySourceMsgId(id)(s),
|
|
29
|
+
messageStateSelectors.isMessageRegenerating(id)(s),
|
|
29
30
|
]);
|
|
30
31
|
const isGroupSession = useSessionStore(sessionSelectors.isCurrentSessionGroupSession);
|
|
31
32
|
const [showShareModal, setShareModal] = useState(false);
|
|
@@ -42,7 +43,7 @@ export const AssistantActionsBar = memo<AssistantActionsProps>(({ id, data, inde
|
|
|
42
43
|
share,
|
|
43
44
|
tts,
|
|
44
45
|
translate,
|
|
45
|
-
} = useChatListActionsBar({ hasThread });
|
|
46
|
+
} = useChatListActionsBar({ hasThread, isRegenerating });
|
|
46
47
|
|
|
47
48
|
const hasTools = !!tools;
|
|
48
49
|
|
|
@@ -52,17 +53,19 @@ export const AssistantActionsBar = memo<AssistantActionsProps>(({ id, data, inde
|
|
|
52
53
|
const items = useMemo(() => {
|
|
53
54
|
if (hasTools) return [delAndRegenerate, copy];
|
|
54
55
|
|
|
55
|
-
return [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
return [
|
|
57
|
+
edit,
|
|
58
|
+
copy,
|
|
59
|
+
// inThread || isGroupSession ? null : branching
|
|
60
|
+
].filter(Boolean) as ActionIconGroupItemType[];
|
|
61
|
+
}, [inThread, hasTools, isGroupSession, delAndRegenerate, copy, edit, branching]);
|
|
59
62
|
|
|
60
63
|
const { t } = useTranslation('common');
|
|
61
64
|
const searchParams = useSearchParams();
|
|
62
65
|
const topic = searchParams.get('topic');
|
|
63
66
|
const [
|
|
64
67
|
deleteMessage,
|
|
65
|
-
|
|
68
|
+
regenerateAssistantMessage,
|
|
66
69
|
translateMessage,
|
|
67
70
|
ttsMessage,
|
|
68
71
|
delAndRegenerateMessage,
|
|
@@ -73,7 +76,7 @@ export const AssistantActionsBar = memo<AssistantActionsProps>(({ id, data, inde
|
|
|
73
76
|
toggleMessageEditing,
|
|
74
77
|
] = useChatStore((s) => [
|
|
75
78
|
s.deleteMessage,
|
|
76
|
-
s.
|
|
79
|
+
s.regenerateAssistantMessage,
|
|
77
80
|
s.translateMessage,
|
|
78
81
|
s.ttsMessage,
|
|
79
82
|
s.delAndRegenerateMessage,
|
|
@@ -120,7 +123,7 @@ export const AssistantActionsBar = memo<AssistantActionsProps>(({ id, data, inde
|
|
|
120
123
|
case 'regenerate': {
|
|
121
124
|
if (inPortalThread) {
|
|
122
125
|
resendThreadMessage(id);
|
|
123
|
-
} else
|
|
126
|
+
} else regenerateAssistantMessage(id);
|
|
124
127
|
|
|
125
128
|
// if this message is an error message, we need to delete it
|
|
126
129
|
if (data.error) deleteMessage(id);
|
|
@@ -46,20 +46,15 @@ describe('AssistantMessageExtra', () => {
|
|
|
46
46
|
expect(screen.queryByText('Translate Component')).toBeNull();
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
it('should not render content if extra is defined but does not contain
|
|
49
|
+
it('should not render content if extra is defined but does not contain model, tts, or translate', async () => {
|
|
50
50
|
render(<AssistantMessageExtra {...mockData} extra={{}} />);
|
|
51
51
|
expect(screen.queryByText('Usage Component')).toBeNull();
|
|
52
52
|
expect(screen.queryByText('TTS Component')).toBeNull();
|
|
53
53
|
expect(screen.queryByText('Translate Component')).toBeNull();
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
it('should render Usage component if extra.
|
|
57
|
-
render(
|
|
58
|
-
<AssistantMessageExtra
|
|
59
|
-
{...mockData}
|
|
60
|
-
extra={{ fromModel: 'gpt-4', fromProvider: 'openai' }}
|
|
61
|
-
/>,
|
|
62
|
-
);
|
|
56
|
+
it('should render Usage component if extra.model exists', async () => {
|
|
57
|
+
render(<AssistantMessageExtra {...mockData} extra={{ model: 'gpt-4', provider: 'openai' }} />);
|
|
63
58
|
|
|
64
59
|
expect(screen.getByText('Usage Component')).toBeInTheDocument();
|
|
65
60
|
});
|
|
@@ -24,12 +24,8 @@ export const AssistantMessageExtra = memo<AssistantMessageExtraProps>(
|
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
26
|
<Flexbox gap={8} style={{ marginTop: !!tools?.length ? 8 : 4 }}>
|
|
27
|
-
{content !== LOADING_FLAT && extra?.
|
|
28
|
-
<Usage
|
|
29
|
-
metadata={metadata || {}}
|
|
30
|
-
model={extra?.fromModel}
|
|
31
|
-
provider={extra.fromProvider!}
|
|
32
|
-
/>
|
|
27
|
+
{content !== LOADING_FLAT && extra?.model && (
|
|
28
|
+
<Usage metadata={metadata || {}} model={extra?.model} provider={extra.provider!} />
|
|
33
29
|
)}
|
|
34
30
|
<>
|
|
35
31
|
{!!extra?.tts && (
|
|
@@ -58,15 +58,13 @@ export const AssistantMessageContent = memo<
|
|
|
58
58
|
{isIntentUnderstanding ? (
|
|
59
59
|
<IntentUnderstanding />
|
|
60
60
|
) : (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/>
|
|
69
|
-
)
|
|
61
|
+
<DefaultMessage
|
|
62
|
+
addIdOnDOM={false}
|
|
63
|
+
content={content}
|
|
64
|
+
id={id}
|
|
65
|
+
isToolCallGenerating={isToolCallGenerating}
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
70
68
|
)}
|
|
71
69
|
{showImageItems && <ImageFileListViewer items={imageList} />}
|
|
72
70
|
{tools && (
|
|
@@ -2,7 +2,7 @@ import { Highlighter } from '@lobehub/ui';
|
|
|
2
2
|
import { memo, useMemo } from 'react';
|
|
3
3
|
|
|
4
4
|
import { useChatStore } from '@/store/chat';
|
|
5
|
-
import {
|
|
5
|
+
import { dbMessageSelectors } from '@/store/chat/selectors';
|
|
6
6
|
|
|
7
7
|
export interface FunctionMessageProps {
|
|
8
8
|
toolCallId: string;
|
|
@@ -10,7 +10,7 @@ export interface FunctionMessageProps {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const PluginResult = memo<FunctionMessageProps>(({ toolCallId, variant }) => {
|
|
13
|
-
const toolMessage = useChatStore(
|
|
13
|
+
const toolMessage = useChatStore(dbMessageSelectors.getDbMessageByToolCallId(toolCallId));
|
|
14
14
|
|
|
15
15
|
const { data, language } = useMemo(() => {
|
|
16
16
|
try {
|
|
@@ -2,14 +2,14 @@ import { Highlighter } from '@lobehub/ui';
|
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
4
|
import { useChatStore } from '@/store/chat';
|
|
5
|
-
import {
|
|
5
|
+
import { dbMessageSelectors } from '@/store/chat/selectors';
|
|
6
6
|
|
|
7
7
|
export interface FunctionMessageProps {
|
|
8
8
|
toolCallId: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const PluginState = memo<FunctionMessageProps>(({ toolCallId }) => {
|
|
12
|
-
const toolMessage = useChatStore(
|
|
12
|
+
const toolMessage = useChatStore(dbMessageSelectors.getDbMessageByToolCallId(toolCallId));
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
toolMessage?.pluginState && (
|
|
@@ -23,7 +23,10 @@ const PluginSettings = memo<PluginSettingsProps>(({ id, plugin }) => {
|
|
|
23
23
|
const { styles } = useStyles();
|
|
24
24
|
const { t } = useTranslation('error');
|
|
25
25
|
const theme = useTheme();
|
|
26
|
-
const [resend, deleteMessage] = useChatStore((s) => [
|
|
26
|
+
const [resend, deleteMessage] = useChatStore((s) => [
|
|
27
|
+
s.regenerateAssistantMessage,
|
|
28
|
+
s.deleteMessage,
|
|
29
|
+
]);
|
|
27
30
|
const pluginIdentifier = plugin?.identifier as string;
|
|
28
31
|
const pluginMeta = useToolStore(pluginSelectors.getPluginMetaById(pluginIdentifier), isEqual);
|
|
29
32
|
const manifest = useToolStore(pluginSelectors.getToolManifestById(pluginIdentifier), isEqual);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { LOADING_FLAT } from '@lobechat/const';
|
|
2
|
-
import isEqual from 'fast-deep-equal';
|
|
3
2
|
import { Suspense, memo } from 'react';
|
|
4
3
|
|
|
5
4
|
import { useChatStore } from '@/store/chat';
|
|
6
|
-
import {
|
|
5
|
+
import { dbMessageSelectors, messageStateSelectors } from '@/store/chat/selectors';
|
|
7
6
|
|
|
8
7
|
import CustomRender from './CustomRender';
|
|
9
8
|
import ErrorResponse from './ErrorResponse';
|
|
@@ -32,7 +31,7 @@ const Render = memo<RenderProps>(
|
|
|
32
31
|
apiName,
|
|
33
32
|
}) => {
|
|
34
33
|
const loading = useChatStore(messageStateSelectors.isToolCallStreaming(messageId, toolIndex));
|
|
35
|
-
const toolMessage = useChatStore(
|
|
34
|
+
const toolMessage = useChatStore(dbMessageSelectors.getDbMessageByToolCallId(toolCallId));
|
|
36
35
|
|
|
37
36
|
if (loading || !toolMessage) return null;
|
|
38
37
|
|
|
@@ -204,75 +204,72 @@ const AssistantMessage = memo<AssistantMessageProps>((props) => {
|
|
|
204
204
|
);
|
|
205
205
|
const errorMessage = <ErrorMessageExtra data={props} />;
|
|
206
206
|
return (
|
|
207
|
-
<Flexbox
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
size={mobile ? MOBILE_AVATAR_SIZE : undefined}
|
|
219
|
-
style={{ marginTop: 6 }}
|
|
220
|
-
/>
|
|
221
|
-
<Flexbox align={'flex-start'} className={styles.messageContainer}>
|
|
207
|
+
<Flexbox className={styles.container} gap={mobile ? 6 : 12}>
|
|
208
|
+
<Flexbox gap={4} horizontal>
|
|
209
|
+
<Avatar
|
|
210
|
+
alt={avatar.title || 'avatar'}
|
|
211
|
+
avatar={avatar}
|
|
212
|
+
loading={loading}
|
|
213
|
+
onClick={onAvatarClick}
|
|
214
|
+
placement={placement}
|
|
215
|
+
size={MOBILE_AVATAR_SIZE}
|
|
216
|
+
style={{ marginTop: 6 }}
|
|
217
|
+
/>
|
|
222
218
|
<Title
|
|
223
219
|
avatar={avatar}
|
|
224
220
|
placement={placement}
|
|
225
|
-
showTitle
|
|
221
|
+
showTitle
|
|
226
222
|
time={createdAt}
|
|
227
223
|
titleAddon={dmIndicator}
|
|
228
224
|
/>
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
<AssistantMessageExtra
|
|
255
|
-
content={content}
|
|
256
|
-
extra={extra}
|
|
257
|
-
id={id}
|
|
258
|
-
metadata={metadata}
|
|
259
|
-
tools={tools}
|
|
225
|
+
</Flexbox>
|
|
226
|
+
<Flexbox
|
|
227
|
+
align={'flex-start'}
|
|
228
|
+
className={styles.messageContent}
|
|
229
|
+
data-layout={'vertical'} // 添加数据属性以方便样式选择
|
|
230
|
+
direction={'vertical'}
|
|
231
|
+
gap={8}
|
|
232
|
+
width={'fit-content'}
|
|
233
|
+
>
|
|
234
|
+
<Flexbox style={{ flex: 1, maxWidth: '100%' }}>
|
|
235
|
+
{error && (message === LOADING_FLAT || !message) ? (
|
|
236
|
+
<ErrorContent error={errorContent} message={errorMessage} placement={placement} />
|
|
237
|
+
) : (
|
|
238
|
+
<MessageContent
|
|
239
|
+
editing={editing}
|
|
240
|
+
id={id}
|
|
241
|
+
markdownProps={markdownProps}
|
|
242
|
+
message={reducted ? `*${t('hideForYou')}*` : message}
|
|
243
|
+
messageExtra={
|
|
244
|
+
<>
|
|
245
|
+
{errorContent && (
|
|
246
|
+
<ErrorContent
|
|
247
|
+
error={errorContent}
|
|
248
|
+
message={errorMessage}
|
|
249
|
+
placement={placement}
|
|
260
250
|
/>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
251
|
+
)}
|
|
252
|
+
<AssistantMessageExtra
|
|
253
|
+
content={content}
|
|
254
|
+
extra={extra}
|
|
255
|
+
id={id}
|
|
256
|
+
metadata={metadata}
|
|
257
|
+
tools={tools}
|
|
258
|
+
/>
|
|
259
|
+
</>
|
|
260
|
+
}
|
|
261
|
+
onDoubleClick={onDoubleClick}
|
|
262
|
+
placement={placement}
|
|
263
|
+
renderMessage={renderMessage}
|
|
264
|
+
variant={variant}
|
|
265
|
+
/>
|
|
274
266
|
)}
|
|
275
267
|
</Flexbox>
|
|
268
|
+
{!disableEditing && !editing && (
|
|
269
|
+
<Flexbox align={'flex-start'} className={styles.actions} role="menubar">
|
|
270
|
+
<AssistantActionsBar data={props} id={id} index={index} />
|
|
271
|
+
</Flexbox>
|
|
272
|
+
)}
|
|
276
273
|
</Flexbox>
|
|
277
274
|
{mobile && <BorderSpacing borderSpacing={MOBILE_AVATAR_SIZE} />}
|
|
278
275
|
</Flexbox>
|
|
@@ -17,6 +17,7 @@ export const DefaultMessage = memo<
|
|
|
17
17
|
|
|
18
18
|
if (isToolCallGenerating) return;
|
|
19
19
|
|
|
20
|
+
if (!content) return <BubblesLoading />;
|
|
20
21
|
if (content === LOADING_FLAT && !editing) return <BubblesLoading />;
|
|
21
22
|
|
|
22
23
|
return <div id={addIdOnDOM ? id : undefined}>{editableContent}</div>;
|
|
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
8
|
import ShareMessageModal from '@/features/Conversation/components/ShareMessageModal';
|
|
9
9
|
import { VirtuosoContext } from '@/features/Conversation/components/VirtualizedList/VirtuosoContext';
|
|
10
10
|
import { useChatStore } from '@/store/chat';
|
|
11
|
-
import { threadSelectors } from '@/store/chat/selectors';
|
|
11
|
+
import { messageStateSelectors, threadSelectors } from '@/store/chat/selectors';
|
|
12
12
|
import { useSessionStore } from '@/store/session';
|
|
13
13
|
import { sessionSelectors } from '@/store/session/selectors';
|
|
14
14
|
|
|
@@ -24,16 +24,19 @@ interface GroupActionsProps {
|
|
|
24
24
|
|
|
25
25
|
const WithContentId = memo<GroupActionsProps>(({ id, data, index, contentBlock }) => {
|
|
26
26
|
const { tools } = data;
|
|
27
|
-
const [isThreadMode, hasThread] = useChatStore((s) => [
|
|
27
|
+
const [isThreadMode, hasThread, isRegenerating] = useChatStore((s) => [
|
|
28
28
|
!!s.activeThreadId,
|
|
29
29
|
threadSelectors.hasThreadBySourceMsgId(id)(s),
|
|
30
|
+
messageStateSelectors.isMessageRegenerating(id)(s),
|
|
30
31
|
]);
|
|
31
32
|
const isGroupSession = useSessionStore(sessionSelectors.isCurrentSessionGroupSession);
|
|
32
33
|
const [showShareModal, setShareModal] = useState(false);
|
|
33
34
|
|
|
34
|
-
const { edit, delAndRegenerate, copy, divider, del, branching, share } =
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const { edit, delAndRegenerate, regenerate, copy, divider, del, branching, share } =
|
|
36
|
+
useChatListActionsBar({
|
|
37
|
+
hasThread,
|
|
38
|
+
isRegenerating,
|
|
39
|
+
});
|
|
37
40
|
|
|
38
41
|
const hasTools = !!tools;
|
|
39
42
|
|
|
@@ -43,28 +46,34 @@ const WithContentId = memo<GroupActionsProps>(({ id, data, index, contentBlock }
|
|
|
43
46
|
const items = useMemo(() => {
|
|
44
47
|
if (hasTools) return [delAndRegenerate, copy];
|
|
45
48
|
|
|
46
|
-
return [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
return [
|
|
50
|
+
edit,
|
|
51
|
+
copy,
|
|
52
|
+
// inThread || isGroupSession ? null : branching
|
|
53
|
+
].filter(Boolean) as ActionIconGroupItemType[];
|
|
54
|
+
}, [inThread, hasTools, isGroupSession, delAndRegenerate, copy, edit, branching]);
|
|
50
55
|
|
|
51
56
|
const { t } = useTranslation('common');
|
|
52
57
|
const searchParams = useSearchParams();
|
|
53
58
|
const topic = searchParams.get('topic');
|
|
54
59
|
const [
|
|
55
60
|
deleteMessage,
|
|
61
|
+
regenerateAssistantMessage,
|
|
56
62
|
translateMessage,
|
|
57
63
|
delAndRegenerateMessage,
|
|
58
64
|
copyMessage,
|
|
59
65
|
openThreadCreator,
|
|
66
|
+
resendThreadMessage,
|
|
60
67
|
delAndResendThreadMessage,
|
|
61
68
|
toggleMessageEditing,
|
|
62
69
|
] = useChatStore((s) => [
|
|
63
70
|
s.deleteMessage,
|
|
71
|
+
s.regenerateAssistantMessage,
|
|
64
72
|
s.translateMessage,
|
|
65
73
|
s.delAndRegenerateMessage,
|
|
66
74
|
s.copyMessage,
|
|
67
75
|
s.openThreadCreator,
|
|
76
|
+
s.resendThreadMessage,
|
|
68
77
|
s.delAndResendThreadMessage,
|
|
69
78
|
s.toggleMessageEditing,
|
|
70
79
|
]);
|
|
@@ -103,6 +112,16 @@ const WithContentId = memo<GroupActionsProps>(({ id, data, index, contentBlock }
|
|
|
103
112
|
break;
|
|
104
113
|
}
|
|
105
114
|
|
|
115
|
+
case 'regenerate': {
|
|
116
|
+
if (inPortalThread) {
|
|
117
|
+
resendThreadMessage(id);
|
|
118
|
+
} else regenerateAssistantMessage(id);
|
|
119
|
+
|
|
120
|
+
// if this message is an error message, we need to delete it
|
|
121
|
+
if (data.error) deleteMessage(id);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
106
125
|
case 'delAndRegenerate': {
|
|
107
126
|
if (inPortalThread) {
|
|
108
127
|
delAndResendThreadMessage(id);
|
|
@@ -134,7 +153,16 @@ const WithContentId = memo<GroupActionsProps>(({ id, data, index, contentBlock }
|
|
|
134
153
|
<ActionIconGroup
|
|
135
154
|
items={items}
|
|
136
155
|
menu={{
|
|
137
|
-
items: [
|
|
156
|
+
items: [
|
|
157
|
+
edit,
|
|
158
|
+
copy,
|
|
159
|
+
divider,
|
|
160
|
+
share,
|
|
161
|
+
divider,
|
|
162
|
+
regenerate,
|
|
163
|
+
// delAndRegenerate,
|
|
164
|
+
del,
|
|
165
|
+
],
|
|
138
166
|
}}
|
|
139
167
|
onActionClick={onActionClick}
|
|
140
168
|
/>
|
|
@@ -16,6 +16,6 @@ export const GroupActionsBar = memo<GroupActionsProps>(
|
|
|
16
16
|
({ id, data, contentBlock, index, contentId }) => {
|
|
17
17
|
if (!contentId) return <WithoutContentId data={data} id={id} />;
|
|
18
18
|
|
|
19
|
-
return <WithContentId contentBlock={contentBlock} data={data} id={
|
|
19
|
+
return <WithContentId contentBlock={contentBlock} data={data} id={id} index={index} />;
|
|
20
20
|
},
|
|
21
21
|
);
|
|
@@ -77,9 +77,7 @@ export const ContentBlock = memo<ContentBlockProps>((props) => {
|
|
|
77
77
|
{showReasoning && <Reasoning {...reasoning} id={id} />}
|
|
78
78
|
|
|
79
79
|
{/* Content - markdown text */}
|
|
80
|
-
{content
|
|
81
|
-
<MessageContent content={content} hasTools={hasTools} markdownProps={markdownProps} />
|
|
82
|
-
)}
|
|
80
|
+
<MessageContent content={content} hasTools={hasTools} markdownProps={markdownProps} />
|
|
83
81
|
|
|
84
82
|
{/* Image files */}
|
|
85
83
|
{showImageItems && <ImageFileListViewer items={imageList} />}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AssistantContentBlock } from '@lobechat/types';
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
|
-
import { motion } from 'framer-motion';
|
|
4
3
|
import { memo, use } from 'react';
|
|
5
4
|
import { Flexbox } from 'react-layout-kit';
|
|
6
5
|
|
|
@@ -23,11 +22,12 @@ interface GroupChildrenProps {
|
|
|
23
22
|
blocks: AssistantContentBlock[];
|
|
24
23
|
contentId?: string;
|
|
25
24
|
disableEditing?: boolean;
|
|
25
|
+
id: string;
|
|
26
26
|
messageIndex: number;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const GroupChildren = memo<GroupChildrenProps>(
|
|
30
|
-
({ blocks, contentId, disableEditing, messageIndex }) => {
|
|
30
|
+
({ blocks, contentId, disableEditing, messageIndex, id }) => {
|
|
31
31
|
const { styles } = useStyles();
|
|
32
32
|
|
|
33
33
|
const [toggleMessageEditing] = useChatStore((s) => [s.toggleMessageEditing]);
|
|
@@ -53,16 +53,16 @@ const GroupChildren = memo<GroupChildrenProps>(
|
|
|
53
53
|
<ContentBlock index={index} {...item} />
|
|
54
54
|
</Flexbox>
|
|
55
55
|
) : (
|
|
56
|
-
<motion.div
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
>
|
|
64
|
-
|
|
65
|
-
</motion.div>
|
|
56
|
+
// <motion.div
|
|
57
|
+
// animate={{ height: 'auto', opacity: 1 }}
|
|
58
|
+
// exit={{ height: 0, opacity: 0 }}
|
|
59
|
+
// initial={{ height: 0, opacity: 0 }}
|
|
60
|
+
// key={`${id}_${index}`}
|
|
61
|
+
// style={{ overflow: 'hidden' }}
|
|
62
|
+
// transition={{ duration: 0.3, ease: 'easeInOut' }}
|
|
63
|
+
// >
|
|
64
|
+
<ContentBlock index={index} key={`${id}_${index}`} {...item} />
|
|
65
|
+
// </motion.div>
|
|
66
66
|
);
|
|
67
67
|
})}
|
|
68
68
|
</Flexbox>
|
|
@@ -25,7 +25,13 @@ const MessageContent = memo<ContentBlockProps>(({ content, hasTools, markdownPro
|
|
|
25
25
|
|
|
26
26
|
const { styles, cx } = useStyles();
|
|
27
27
|
|
|
28
|
-
if (content
|
|
28
|
+
if (!content && !hasTools) return <BubblesLoading />;
|
|
29
|
+
|
|
30
|
+
if (content === LOADING_FLAT) {
|
|
31
|
+
if (hasTools) return null;
|
|
32
|
+
|
|
33
|
+
return <BubblesLoading />;
|
|
34
|
+
}
|
|
29
35
|
|
|
30
36
|
return (
|
|
31
37
|
content && (
|
|
@@ -23,7 +23,7 @@ const PluginSettings = memo<PluginSettingsProps>(({ id, plugin }) => {
|
|
|
23
23
|
const { styles } = useStyles();
|
|
24
24
|
const { t } = useTranslation('error');
|
|
25
25
|
const theme = useTheme();
|
|
26
|
-
const [resend, deleteMessage] = useChatStore((s) => [s.
|
|
26
|
+
const [resend, deleteMessage] = useChatStore((s) => [s.delAndRegenerateMessage, s.deleteMessage]);
|
|
27
27
|
const pluginIdentifier = plugin?.identifier as string;
|
|
28
28
|
const pluginMeta = useToolStore(pluginSelectors.getPluginMetaById(pluginIdentifier), isEqual);
|
|
29
29
|
const manifest = useToolStore(pluginSelectors.getToolManifestById(pluginIdentifier), isEqual);
|
|
@@ -90,7 +90,7 @@ const GroupMessage = memo<GroupMessageProps>((props) => {
|
|
|
90
90
|
avatar={avatar}
|
|
91
91
|
onClick={onAvatarClick}
|
|
92
92
|
placement={placement}
|
|
93
|
-
size={
|
|
93
|
+
size={MOBILE_AVATAR_SIZE}
|
|
94
94
|
style={{ marginTop: 6 }}
|
|
95
95
|
/>
|
|
96
96
|
<Title avatar={avatar} placement={placement} showTitle time={createdAt} />
|
|
@@ -111,6 +111,7 @@ const GroupMessage = memo<GroupMessageProps>((props) => {
|
|
|
111
111
|
blocks={children}
|
|
112
112
|
contentId={contentId}
|
|
113
113
|
disableEditing={disableEditing}
|
|
114
|
+
id={id}
|
|
114
115
|
messageIndex={index}
|
|
115
116
|
/>
|
|
116
117
|
)}
|
|
@@ -128,8 +128,8 @@ const SupervisorMessage = memo<SupervisorMessageProps>((props) => {
|
|
|
128
128
|
|
|
129
129
|
// Render todo message with dedicated component
|
|
130
130
|
if (isTodoMessage && todoData) {
|
|
131
|
-
const model = props.extra?.
|
|
132
|
-
const provider = props.extra?.
|
|
131
|
+
const model = props.extra?.model;
|
|
132
|
+
const provider = props.extra?.provider;
|
|
133
133
|
const hasModelInfo = model || provider;
|
|
134
134
|
|
|
135
135
|
return (
|