@lobehub/lobehub 2.0.0-next.35 → 2.0.0-next.37
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 +50 -0
- package/changelog/v1.json +18 -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/__tests__/apiKey.test.ts +444 -0
- 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/libs/trpc/client/lambda.ts +4 -3
- 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
|
@@ -40,7 +40,6 @@ import {
|
|
|
40
40
|
} from '../schemas';
|
|
41
41
|
import { LobeChatDatabase } from '../type';
|
|
42
42
|
import { genEndDateWhere, genRangeWhere, genStartDateWhere, genWhere } from '../utils/genWhere';
|
|
43
|
-
import { groupAssistantMessages } from '../utils/groupMessages';
|
|
44
43
|
import { idGenerator } from '../utils/idGenerator';
|
|
45
44
|
|
|
46
45
|
export class MessageModel {
|
|
@@ -227,8 +226,8 @@ export class MessageModel {
|
|
|
227
226
|
})),
|
|
228
227
|
|
|
229
228
|
extra: {
|
|
230
|
-
|
|
231
|
-
|
|
229
|
+
model: model,
|
|
230
|
+
provider: provider,
|
|
232
231
|
translate,
|
|
233
232
|
tts: ttsId
|
|
234
233
|
? {
|
|
@@ -269,9 +268,7 @@ export class MessageModel {
|
|
|
269
268
|
},
|
|
270
269
|
);
|
|
271
270
|
|
|
272
|
-
|
|
273
|
-
const { groupAssistantMessages: useGroup = false } = options;
|
|
274
|
-
return useGroup ? groupAssistantMessages(mappedMessages) : mappedMessages;
|
|
271
|
+
return mappedMessages;
|
|
275
272
|
};
|
|
276
273
|
|
|
277
274
|
findById = async (id: string) => {
|
|
@@ -464,8 +461,8 @@ export class MessageModel {
|
|
|
464
461
|
|
|
465
462
|
create = async (
|
|
466
463
|
{
|
|
467
|
-
fromModel,
|
|
468
|
-
fromProvider,
|
|
464
|
+
model: fromModel,
|
|
465
|
+
provider: fromProvider,
|
|
469
466
|
files,
|
|
470
467
|
plugin,
|
|
471
468
|
pluginState,
|
|
@@ -771,17 +768,19 @@ export class MessageModel {
|
|
|
771
768
|
sessionId?: string | null,
|
|
772
769
|
topicId?: string | null,
|
|
773
770
|
groupId?: string | null,
|
|
774
|
-
) =>
|
|
775
|
-
this.
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
771
|
+
) => {
|
|
772
|
+
const conditions = [eq(messages.userId, this.userId), this.matchSession(sessionId)];
|
|
773
|
+
|
|
774
|
+
// For deletion: only filter by topicId/groupId if explicitly provided
|
|
775
|
+
if (topicId !== undefined && topicId !== null) {
|
|
776
|
+
conditions.push(eq(messages.topicId, topicId));
|
|
777
|
+
}
|
|
778
|
+
if (groupId !== undefined && groupId !== null) {
|
|
779
|
+
conditions.push(eq(messages.groupId, groupId));
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return this.db.delete(messages).where(and(...conditions));
|
|
783
|
+
};
|
|
785
784
|
|
|
786
785
|
deleteAllMessages = async () => {
|
|
787
786
|
return this.db.delete(messages).where(eq(messages.userId, this.userId));
|
|
@@ -9,6 +9,7 @@ export interface SendNewMessage {
|
|
|
9
9
|
content: string;
|
|
10
10
|
// if message has attached with files, then add files to message and the agent
|
|
11
11
|
files?: string[];
|
|
12
|
+
parentId?: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export interface SendMessageServerParams {
|
|
@@ -41,6 +42,7 @@ export const AiSendMessageServerSchema = z.object({
|
|
|
41
42
|
newUserMessage: z.object({
|
|
42
43
|
content: z.string(),
|
|
43
44
|
files: z.array(z.string()).optional(),
|
|
45
|
+
parentId: z.string().optional(),
|
|
44
46
|
}),
|
|
45
47
|
sessionId: z.string().optional(),
|
|
46
48
|
threadId: z.string().optional(),
|
|
@@ -13,7 +13,13 @@ import { ChatMessageExtra } from './extra';
|
|
|
13
13
|
import { ChatFileChunk } from './rag';
|
|
14
14
|
import { ChatVideoItem } from './video';
|
|
15
15
|
|
|
16
|
-
export type UIMessageRoleType =
|
|
16
|
+
export type UIMessageRoleType =
|
|
17
|
+
| 'user'
|
|
18
|
+
| 'system'
|
|
19
|
+
| 'assistant'
|
|
20
|
+
| 'tool'
|
|
21
|
+
| 'supervisor'
|
|
22
|
+
| 'assistantGroup';
|
|
17
23
|
|
|
18
24
|
export interface ChatFileItem {
|
|
19
25
|
content?: string;
|
|
@@ -34,10 +40,20 @@ export interface AssistantContentBlock {
|
|
|
34
40
|
tools?: ChatToolPayloadWithResult[];
|
|
35
41
|
usage?: ModelUsage;
|
|
36
42
|
}
|
|
43
|
+
interface UIMessageBranch {
|
|
44
|
+
/** Index of the active branch (0-based) */
|
|
45
|
+
activeBranchIndex: number;
|
|
46
|
+
/** Total number of branches */
|
|
47
|
+
count: number;
|
|
48
|
+
}
|
|
37
49
|
|
|
38
50
|
export interface UIChatMessage {
|
|
39
51
|
// Group chat fields (alphabetically before other fields)
|
|
40
52
|
agentId?: string | 'supervisor';
|
|
53
|
+
/**
|
|
54
|
+
* Branch information for user messages with multiple children
|
|
55
|
+
*/
|
|
56
|
+
branch?: UIMessageBranch;
|
|
41
57
|
/**
|
|
42
58
|
* children messages for grouped display
|
|
43
59
|
* Used to group tool messages under their parent assistant message
|
|
@@ -16,8 +16,8 @@ export interface CreateMessageParams
|
|
|
16
16
|
error?: ChatMessageError | null;
|
|
17
17
|
fileChunks?: MessageSemanticSearchChunk[];
|
|
18
18
|
files?: string[];
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
model?: string;
|
|
20
|
+
provider?: string;
|
|
21
21
|
groupId?: string;
|
|
22
22
|
role: CreateMessageRoleType;
|
|
23
23
|
sessionId: string;
|
|
@@ -35,10 +35,6 @@ export const UserGuideSchema = z.object({
|
|
|
35
35
|
export type UserGuide = z.infer<typeof UserGuideSchema>;
|
|
36
36
|
|
|
37
37
|
export const UserLabSchema = z.object({
|
|
38
|
-
/**
|
|
39
|
-
* enable assistant message grouping in chat display
|
|
40
|
-
*/
|
|
41
|
-
enableAssistantMessageGroup: z.boolean().optional(),
|
|
42
38
|
/**
|
|
43
39
|
* enable multi-agent group chat mode
|
|
44
40
|
*/
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
+
import { estimateTokenCount } from 'tokenx';
|
|
2
|
+
|
|
1
3
|
export const encodeAsync = async (str: string): Promise<number> => {
|
|
2
4
|
if (str.length === 0) return 0;
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
// use approximation way if large then 10000
|
|
6
|
-
if (str.length <= 10_000) {
|
|
7
|
-
const { clientEncodeAsync } = await import('./client');
|
|
8
|
-
|
|
9
|
-
return await clientEncodeAsync(str);
|
|
10
|
-
} else {
|
|
11
|
-
const { estimatedEncodeAsync } = await import('./estimated');
|
|
12
|
-
|
|
13
|
-
return await estimatedEncodeAsync(str);
|
|
14
|
-
}
|
|
6
|
+
return estimateTokenCount(str);
|
|
15
7
|
};
|
|
@@ -8,7 +8,7 @@ import { useChatStore } from '@/store/chat';
|
|
|
8
8
|
import { useSend } from '../useSend';
|
|
9
9
|
|
|
10
10
|
const MessageFromUrl = () => {
|
|
11
|
-
const
|
|
11
|
+
const updateMessageInput = useChatStore((s) => s.updateMessageInput);
|
|
12
12
|
const { send: sendMessage } = useSend();
|
|
13
13
|
const searchParams = useSearchParams();
|
|
14
14
|
|
|
@@ -21,10 +21,10 @@ const MessageFromUrl = () => {
|
|
|
21
21
|
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
22
22
|
window.history.replaceState({}, '', newUrl);
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
updateMessageInput(message);
|
|
25
25
|
sendMessage();
|
|
26
26
|
}
|
|
27
|
-
}, [searchParams,
|
|
27
|
+
}, [searchParams, updateMessageInput, sendMessage]);
|
|
28
28
|
|
|
29
29
|
return null;
|
|
30
30
|
};
|
|
@@ -16,9 +16,9 @@ export type UseSendMessageParams = Pick<
|
|
|
16
16
|
>;
|
|
17
17
|
|
|
18
18
|
export const useSendMessage = () => {
|
|
19
|
-
const [sendMessage,
|
|
19
|
+
const [sendMessage, updateMessageInput] = useChatStore((s) => [
|
|
20
20
|
s.sendMessage,
|
|
21
|
-
s.
|
|
21
|
+
s.updateMessageInput,
|
|
22
22
|
]);
|
|
23
23
|
const { analytics } = useAnalytics();
|
|
24
24
|
const checkGeminiChineseWarning = useGeminiChineseWarning();
|
|
@@ -66,7 +66,7 @@ export const useSendMessage = () => {
|
|
|
66
66
|
...params,
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
updateMessageInput('');
|
|
70
70
|
clearChatUploadFileList();
|
|
71
71
|
|
|
72
72
|
// 获取分析数据
|
package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/useSend.ts
CHANGED
|
@@ -161,14 +161,14 @@ export const useSendGroupMessage = () => {
|
|
|
161
161
|
const [
|
|
162
162
|
isContentEmpty,
|
|
163
163
|
sendGroupMessage,
|
|
164
|
-
|
|
164
|
+
updateMessageInput,
|
|
165
165
|
stopGenerateMessage,
|
|
166
166
|
isSendButtonDisabledByMessage,
|
|
167
167
|
isCreatingMessage,
|
|
168
168
|
] = useChatStore((s) => [
|
|
169
169
|
!s.inputMessage,
|
|
170
170
|
s.sendGroupMessage,
|
|
171
|
-
s.
|
|
171
|
+
s.updateMessageInput,
|
|
172
172
|
s.stopGenerateMessage,
|
|
173
173
|
messageStateSelectors.isSendButtonDisabledByMessage(s),
|
|
174
174
|
messageStateSelectors.isCreatingMessage(s),
|
|
@@ -255,7 +255,7 @@ export const useSendGroupMessage = () => {
|
|
|
255
255
|
mainInputEditor.setExpand(false);
|
|
256
256
|
mainInputEditor.clearContent();
|
|
257
257
|
mainInputEditor.focus();
|
|
258
|
-
|
|
258
|
+
updateMessageInput('');
|
|
259
259
|
// clear mentioned users after sending
|
|
260
260
|
mentionState.clearMentionedUsers();
|
|
261
261
|
|
|
@@ -284,7 +284,7 @@ export const useSendGroupMessage = () => {
|
|
|
284
284
|
canNotSend,
|
|
285
285
|
fileList,
|
|
286
286
|
clearChatUploadFileList,
|
|
287
|
-
|
|
287
|
+
updateMessageInput,
|
|
288
288
|
analytics,
|
|
289
289
|
checkGeminiChineseWarning,
|
|
290
290
|
],
|
|
@@ -314,8 +314,8 @@ export const useSendGroupMessage = () => {
|
|
|
314
314
|
generating: isSupervisorThinking || isCreatingMessage,
|
|
315
315
|
send: handleSend,
|
|
316
316
|
stop,
|
|
317
|
-
|
|
317
|
+
updateMessageInput,
|
|
318
318
|
}),
|
|
319
|
-
[canNotSend, isSupervisorThinking, isCreatingMessage, handleSend, stop,
|
|
319
|
+
[canNotSend, isSupervisorThinking, isCreatingMessage, handleSend, stop, updateMessageInput],
|
|
320
320
|
);
|
|
321
321
|
};
|
package/src/app/[variants]/(main)/chat/components/conversation/features/ChatList/Content.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { SkeletonList, VirtualizedList } from '@/features/Conversation';
|
|
|
6
6
|
import WideScreenContainer from '@/features/Conversation/components/WideScreenContainer';
|
|
7
7
|
import { useFetchMessages } from '@/hooks/useFetchMessages';
|
|
8
8
|
import { useChatStore } from '@/store/chat';
|
|
9
|
-
import {
|
|
9
|
+
import { displayMessageSelectors } from '@/store/chat/selectors';
|
|
10
10
|
|
|
11
11
|
import MainChatItem from './ChatItem';
|
|
12
12
|
import Welcome from './WelcomeChatItem';
|
|
@@ -16,10 +16,12 @@ interface ListProps {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const Content = memo<ListProps>(({ mobile }) => {
|
|
19
|
-
const [isCurrentChatLoaded] = useChatStore((s) => [
|
|
19
|
+
const [isCurrentChatLoaded] = useChatStore((s) => [
|
|
20
|
+
displayMessageSelectors.isCurrentDisplayChatLoaded(s),
|
|
21
|
+
]);
|
|
20
22
|
|
|
21
23
|
useFetchMessages();
|
|
22
|
-
const data = useChatStore(
|
|
24
|
+
const data = useChatStore(displayMessageSelectors.mainDisplayChatIDs);
|
|
23
25
|
|
|
24
26
|
const itemContent = useCallback(
|
|
25
27
|
(index: number, id: string) => <MainChatItem id={id} index={index} />,
|
|
@@ -40,7 +40,7 @@ interface OpeningQuestionsProps {
|
|
|
40
40
|
|
|
41
41
|
const OpeningQuestions = memo<OpeningQuestionsProps>(({ mobile, questions }) => {
|
|
42
42
|
const { t } = useTranslation('welcome');
|
|
43
|
-
const [
|
|
43
|
+
const [updateMessageInput] = useChatStore((s) => [s.updateMessageInput]);
|
|
44
44
|
|
|
45
45
|
const { styles } = useStyles();
|
|
46
46
|
const { send: sendMessage } = useSend();
|
|
@@ -56,7 +56,7 @@ const OpeningQuestions = memo<OpeningQuestionsProps>(({ mobile, questions }) =>
|
|
|
56
56
|
clickable
|
|
57
57
|
key={question}
|
|
58
58
|
onClick={() => {
|
|
59
|
-
|
|
59
|
+
updateMessageInput(question);
|
|
60
60
|
sendMessage({ isWelcomeQuestion: true });
|
|
61
61
|
}}
|
|
62
62
|
paddingBlock={8}
|
|
@@ -77,7 +77,7 @@ const getFallbackActivities = (t: any) => {
|
|
|
77
77
|
const GroupUsageSuggest = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
78
78
|
const { t } = useTranslation('welcome');
|
|
79
79
|
const { styles } = useStyles();
|
|
80
|
-
const {
|
|
80
|
+
const { updateMessageInput, send } = useSendGroupMessage();
|
|
81
81
|
const templateMatch = useTemplateMatching();
|
|
82
82
|
|
|
83
83
|
const itemsPerPage = mobile ? 2 : 4;
|
|
@@ -139,7 +139,7 @@ const GroupUsageSuggest = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
139
139
|
horizontal
|
|
140
140
|
key={activityKey}
|
|
141
141
|
onClick={() => {
|
|
142
|
-
|
|
142
|
+
updateMessageInput(prompt);
|
|
143
143
|
send();
|
|
144
144
|
}}
|
|
145
145
|
variant={'outlined'}
|
|
@@ -24,13 +24,11 @@ const LabsPage = memo(() => {
|
|
|
24
24
|
const [
|
|
25
25
|
isPreferenceInit,
|
|
26
26
|
enableInputMarkdown,
|
|
27
|
-
enableAssistantMessageGroup,
|
|
28
27
|
// enableGroupChat,
|
|
29
28
|
updateLab,
|
|
30
29
|
] = useUserStore((s) => [
|
|
31
30
|
preferenceSelectors.isPreferenceInit(s),
|
|
32
31
|
labPreferSelectors.enableInputMarkdown(s),
|
|
33
|
-
labPreferSelectors.enableAssistantMessageGroup(s),
|
|
34
32
|
// labPreferSelectors.enableGroupChat(s),
|
|
35
33
|
s.updateLab,
|
|
36
34
|
]);
|
|
@@ -43,13 +41,6 @@ const LabsPage = memo(() => {
|
|
|
43
41
|
key: 'enableInputMarkdown',
|
|
44
42
|
title: t('features.inputMarkdown.title'),
|
|
45
43
|
},
|
|
46
|
-
{
|
|
47
|
-
checked: enableAssistantMessageGroup,
|
|
48
|
-
cover: 'https://github.com/user-attachments/assets/ba517751-1f3b-4269-979e-f8471e3ebb89',
|
|
49
|
-
desc: t('features.assistantMessageGroup.desc'),
|
|
50
|
-
key: 'enableAssistantMessageGroup',
|
|
51
|
-
title: t('features.assistantMessageGroup.title'),
|
|
52
|
-
},
|
|
53
44
|
// {
|
|
54
45
|
// checked: enableGroupChat,
|
|
55
46
|
// cover: 'https://github.com/user-attachments/assets/72894d24-a96a-4d7c-a823-ff9e6a1a8b6d',
|
|
@@ -42,9 +42,9 @@ const BrowserSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
42
42
|
const [error, setError] = useState<ChatMessageError>();
|
|
43
43
|
const { t } = useTranslation('chat');
|
|
44
44
|
|
|
45
|
-
const [loading,
|
|
45
|
+
const [loading, updateMessageInput] = useChatStore((s) => [
|
|
46
46
|
messageStateSelectors.isAIGenerating(s),
|
|
47
|
-
s.
|
|
47
|
+
s.updateMessageInput,
|
|
48
48
|
]);
|
|
49
49
|
|
|
50
50
|
const setDefaultError = useCallback(
|
|
@@ -76,7 +76,7 @@ const BrowserSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
76
76
|
},
|
|
77
77
|
onTextChange: (text) => {
|
|
78
78
|
if (loading) stop();
|
|
79
|
-
if (text)
|
|
79
|
+
if (text) updateMessageInput(text);
|
|
80
80
|
},
|
|
81
81
|
});
|
|
82
82
|
|
|
@@ -53,9 +53,9 @@ const OpenaiSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
53
53
|
const [error, setError] = useState<ChatMessageError>();
|
|
54
54
|
const { t } = useTranslation('chat');
|
|
55
55
|
|
|
56
|
-
const [loading,
|
|
56
|
+
const [loading, updateMessageInput] = useChatStore((s) => [
|
|
57
57
|
messageStateSelectors.isAIGenerating(s),
|
|
58
|
-
s.
|
|
58
|
+
s.updateMessageInput,
|
|
59
59
|
]);
|
|
60
60
|
|
|
61
61
|
const setDefaultError = useCallback(
|
|
@@ -87,7 +87,7 @@ const OpenaiSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
87
87
|
},
|
|
88
88
|
onTextChange: (text) => {
|
|
89
89
|
if (loading) stop();
|
|
90
|
-
if (text)
|
|
90
|
+
if (text) updateMessageInput(text);
|
|
91
91
|
},
|
|
92
92
|
});
|
|
93
93
|
|
|
@@ -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 {
|