@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
|
@@ -24,7 +24,7 @@ import { merge } from '@/utils/merge';
|
|
|
24
24
|
import { safeParseJSON } from '@/utils/safeParseJSON';
|
|
25
25
|
import { setNamespace } from '@/utils/storeDebug';
|
|
26
26
|
|
|
27
|
-
import {
|
|
27
|
+
import { dbMessageSelectors, displayMessageSelectors } from '../message/selectors';
|
|
28
28
|
import { threadSelectors } from '../thread/selectors';
|
|
29
29
|
|
|
30
30
|
const n = setNamespace('plugin');
|
|
@@ -103,9 +103,9 @@ export const chatPlugin: StateCreator<
|
|
|
103
103
|
},
|
|
104
104
|
|
|
105
105
|
fillPluginMessageContent: async (id, content, triggerAiMessage) => {
|
|
106
|
-
const { triggerAIMessage,
|
|
106
|
+
const { triggerAIMessage, optimisticUpdateMessageContent } = get();
|
|
107
107
|
|
|
108
|
-
await
|
|
108
|
+
await optimisticUpdateMessageContent(id, content);
|
|
109
109
|
|
|
110
110
|
if (triggerAiMessage) await triggerAIMessage({ parentId: id });
|
|
111
111
|
},
|
|
@@ -161,12 +161,12 @@ export const chatPlugin: StateCreator<
|
|
|
161
161
|
},
|
|
162
162
|
|
|
163
163
|
reInvokeToolMessage: async (id) => {
|
|
164
|
-
const message =
|
|
164
|
+
const message = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
165
165
|
if (!message || message.role !== 'tool' || !message.plugin) return;
|
|
166
166
|
|
|
167
167
|
// if there is error content, then clear the error
|
|
168
168
|
if (!!message.pluginError) {
|
|
169
|
-
get().
|
|
169
|
+
get().optimisticUpdateMessagePluginError(id, null);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
const payload: ChatToolPayload = { ...message.plugin, id: message.tool_call_id! };
|
|
@@ -175,13 +175,16 @@ export const chatPlugin: StateCreator<
|
|
|
175
175
|
},
|
|
176
176
|
|
|
177
177
|
triggerAIMessage: async ({ parentId, traceId, threadId, inPortalThread, inSearchWorkflow }) => {
|
|
178
|
-
const {
|
|
178
|
+
const { internal_execAgentRuntime } = get();
|
|
179
179
|
|
|
180
180
|
const chats = inPortalThread
|
|
181
181
|
? threadSelectors.portalAIChatsWithHistoryConfig(get())
|
|
182
|
-
:
|
|
182
|
+
: displayMessageSelectors.mainAIChatsWithHistoryConfig(get());
|
|
183
183
|
|
|
184
|
-
await
|
|
184
|
+
await internal_execAgentRuntime({
|
|
185
|
+
messages: chats,
|
|
186
|
+
parentMessageId: parentId ?? chats.at(-1)!.id,
|
|
187
|
+
parentMessageType: 'user',
|
|
185
188
|
traceId,
|
|
186
189
|
threadId,
|
|
187
190
|
inPortalThread,
|
|
@@ -190,11 +193,11 @@ export const chatPlugin: StateCreator<
|
|
|
190
193
|
},
|
|
191
194
|
|
|
192
195
|
summaryPluginContent: async (id) => {
|
|
193
|
-
const message =
|
|
196
|
+
const message = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
194
197
|
if (!message || message.role !== 'tool') return;
|
|
195
198
|
|
|
196
|
-
await get().
|
|
197
|
-
[
|
|
199
|
+
await get().internal_execAgentRuntime({
|
|
200
|
+
messages: [
|
|
198
201
|
{
|
|
199
202
|
role: 'assistant',
|
|
200
203
|
content: '作为一名总结专家,请结合以上系统提示词,将以下内容进行总结:',
|
|
@@ -207,12 +210,13 @@ export const chatPlugin: StateCreator<
|
|
|
207
210
|
tool_call_id: undefined,
|
|
208
211
|
},
|
|
209
212
|
] as UIChatMessage[],
|
|
210
|
-
message.id,
|
|
211
|
-
|
|
213
|
+
parentMessageId: message.id,
|
|
214
|
+
parentMessageType: 'assistant',
|
|
215
|
+
});
|
|
212
216
|
},
|
|
213
217
|
|
|
214
218
|
triggerToolCalls: async (assistantId, { threadId, inPortalThread, inSearchWorkflow } = {}) => {
|
|
215
|
-
const message =
|
|
219
|
+
const message = displayMessageSelectors.getDisplayMessageById(assistantId)(get());
|
|
216
220
|
if (!message || !message.tools) return;
|
|
217
221
|
|
|
218
222
|
let shouldCreateMessage = false;
|
|
@@ -230,7 +234,7 @@ export const chatPlugin: StateCreator<
|
|
|
230
234
|
groupId: message.groupId, // Propagate groupId from parent message for group chat
|
|
231
235
|
};
|
|
232
236
|
|
|
233
|
-
const result = await get().
|
|
237
|
+
const result = await get().optimisticCreateMessage(toolMessage);
|
|
234
238
|
if (!result) return;
|
|
235
239
|
|
|
236
240
|
// trigger the plugin call
|
|
@@ -249,7 +253,7 @@ export const chatPlugin: StateCreator<
|
|
|
249
253
|
// only default type tool calls should trigger AI message
|
|
250
254
|
if (!shouldCreateMessage) return;
|
|
251
255
|
|
|
252
|
-
const traceId =
|
|
256
|
+
const traceId = dbMessageSelectors.getTraceIdByDbMessageId(latestToolId)(get());
|
|
253
257
|
|
|
254
258
|
await get().triggerAIMessage({ traceId, threadId, inPortalThread, inSearchWorkflow });
|
|
255
259
|
},
|
|
@@ -271,10 +275,12 @@ export const chatPlugin: StateCreator<
|
|
|
271
275
|
|
|
272
276
|
updatePluginArguments: async (id, value, replace = false) => {
|
|
273
277
|
const { refreshMessages } = get();
|
|
274
|
-
const toolMessage =
|
|
278
|
+
const toolMessage = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
275
279
|
if (!toolMessage || !toolMessage?.tool_call_id) return;
|
|
276
280
|
|
|
277
|
-
let assistantMessage =
|
|
281
|
+
let assistantMessage = displayMessageSelectors.getDisplayMessageById(
|
|
282
|
+
toolMessage?.parentId || '',
|
|
283
|
+
)(get());
|
|
278
284
|
|
|
279
285
|
const prevArguments = toolMessage?.plugin?.arguments;
|
|
280
286
|
const prevJson = safeParseJSON(prevArguments || '');
|
|
@@ -296,7 +302,7 @@ export const chatPlugin: StateCreator<
|
|
|
296
302
|
tool_call_id: toolMessage?.tool_call_id,
|
|
297
303
|
value: { arguments: JSON.stringify(nextValue) },
|
|
298
304
|
});
|
|
299
|
-
assistantMessage =
|
|
305
|
+
assistantMessage = displayMessageSelectors.getDisplayMessageById(assistantMessage?.id)(get());
|
|
300
306
|
}
|
|
301
307
|
|
|
302
308
|
const updateAssistantMessage = async () => {
|
|
@@ -315,7 +321,7 @@ export const chatPlugin: StateCreator<
|
|
|
315
321
|
},
|
|
316
322
|
|
|
317
323
|
internal_addToolToAssistantMessage: async (id, tool) => {
|
|
318
|
-
const assistantMessage =
|
|
324
|
+
const assistantMessage = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
319
325
|
if (!assistantMessage) return;
|
|
320
326
|
|
|
321
327
|
const { internal_dispatchMessage, internal_refreshToUpdateMessageTools } = get();
|
|
@@ -329,7 +335,7 @@ export const chatPlugin: StateCreator<
|
|
|
329
335
|
},
|
|
330
336
|
|
|
331
337
|
internal_removeToolToAssistantMessage: async (id, tool_call_id) => {
|
|
332
|
-
const message =
|
|
338
|
+
const message = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
333
339
|
if (!message || !tool_call_id) return;
|
|
334
340
|
|
|
335
341
|
const { internal_dispatchMessage, internal_refreshToUpdateMessageTools } = get();
|
|
@@ -341,7 +347,7 @@ export const chatPlugin: StateCreator<
|
|
|
341
347
|
await internal_refreshToUpdateMessageTools(id);
|
|
342
348
|
},
|
|
343
349
|
internal_refreshToUpdateMessageTools: async (id) => {
|
|
344
|
-
const message =
|
|
350
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
345
351
|
if (!message || !message.tools) return;
|
|
346
352
|
|
|
347
353
|
const { internal_toggleMessageLoading, replaceMessages } = get();
|
|
@@ -363,7 +369,7 @@ export const chatPlugin: StateCreator<
|
|
|
363
369
|
},
|
|
364
370
|
|
|
365
371
|
internal_callPluginApi: async (id, payload) => {
|
|
366
|
-
const {
|
|
372
|
+
const { optimisticUpdateMessageContent, internal_togglePluginApiCalling } = get();
|
|
367
373
|
let data: string;
|
|
368
374
|
|
|
369
375
|
try {
|
|
@@ -373,7 +379,7 @@ export const chatPlugin: StateCreator<
|
|
|
373
379
|
n('fetchPlugin/start') as string,
|
|
374
380
|
);
|
|
375
381
|
|
|
376
|
-
const message =
|
|
382
|
+
const message = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
377
383
|
|
|
378
384
|
const res = await chatService.runPluginApi(payload, {
|
|
379
385
|
signal: abortController?.signal,
|
|
@@ -404,7 +410,7 @@ export const chatPlugin: StateCreator<
|
|
|
404
410
|
// 如果报错则结束了
|
|
405
411
|
if (!data) return;
|
|
406
412
|
|
|
407
|
-
await
|
|
413
|
+
await optimisticUpdateMessageContent(id, data);
|
|
408
414
|
|
|
409
415
|
return data;
|
|
410
416
|
},
|
|
@@ -435,7 +441,7 @@ export const chatPlugin: StateCreator<
|
|
|
435
441
|
},
|
|
436
442
|
invokeMCPTypePlugin: async (id, payload) => {
|
|
437
443
|
const {
|
|
438
|
-
|
|
444
|
+
optimisticUpdateMessageContent,
|
|
439
445
|
internal_togglePluginApiCalling,
|
|
440
446
|
internal_constructToolsCallingContext,
|
|
441
447
|
} = get();
|
|
@@ -472,7 +478,7 @@ export const chatPlugin: StateCreator<
|
|
|
472
478
|
// 如果报错则结束了
|
|
473
479
|
if (!data) return;
|
|
474
480
|
|
|
475
|
-
await
|
|
481
|
+
await optimisticUpdateMessageContent(id, data);
|
|
476
482
|
|
|
477
483
|
return data;
|
|
478
484
|
},
|
|
@@ -523,7 +529,7 @@ export const chatPlugin: StateCreator<
|
|
|
523
529
|
},
|
|
524
530
|
|
|
525
531
|
internal_constructToolsCallingContext: (id: string) => {
|
|
526
|
-
const message =
|
|
532
|
+
const message = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
527
533
|
if (!message) return;
|
|
528
534
|
|
|
529
535
|
return {
|
|
@@ -620,9 +620,9 @@ describe('thread action', () => {
|
|
|
620
620
|
const refreshMessagesSpy = vi.spyOn(result.current, 'refreshMessages').mockResolvedValue();
|
|
621
621
|
const openThreadSpy = vi.spyOn(result.current, 'openThreadInPortal');
|
|
622
622
|
const coreProcessSpy = vi
|
|
623
|
-
.spyOn(result.current, '
|
|
623
|
+
.spyOn(result.current, 'internal_execAgentRuntime')
|
|
624
624
|
.mockResolvedValue();
|
|
625
|
-
vi.spyOn(result.current, '
|
|
625
|
+
vi.spyOn(result.current, 'optimisticCreateTmpMessage');
|
|
626
626
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
627
627
|
|
|
628
628
|
await act(async () => {
|
|
@@ -659,7 +659,7 @@ describe('thread action', () => {
|
|
|
659
659
|
});
|
|
660
660
|
|
|
661
661
|
const createTmpSpy = vi
|
|
662
|
-
.spyOn(result.current, '
|
|
662
|
+
.spyOn(result.current, 'optimisticCreateTmpMessage')
|
|
663
663
|
.mockReturnValue('temp-msg-id');
|
|
664
664
|
|
|
665
665
|
vi.spyOn(result.current, 'createThread').mockResolvedValue({
|
|
@@ -669,7 +669,7 @@ describe('thread action', () => {
|
|
|
669
669
|
vi.spyOn(result.current, 'refreshThreads').mockResolvedValue();
|
|
670
670
|
vi.spyOn(result.current, 'refreshMessages').mockResolvedValue();
|
|
671
671
|
vi.spyOn(result.current, 'openThreadInPortal');
|
|
672
|
-
vi.spyOn(result.current, '
|
|
672
|
+
vi.spyOn(result.current, 'internal_execAgentRuntime').mockResolvedValue();
|
|
673
673
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
674
674
|
|
|
675
675
|
await act(async () => {
|
|
@@ -738,8 +738,8 @@ describe('thread action', () => {
|
|
|
738
738
|
useChatStore.setState({ portalThreadId: threadId });
|
|
739
739
|
});
|
|
740
740
|
});
|
|
741
|
-
vi.spyOn(result.current, '
|
|
742
|
-
vi.spyOn(result.current, '
|
|
741
|
+
vi.spyOn(result.current, 'internal_execAgentRuntime').mockResolvedValue();
|
|
742
|
+
vi.spyOn(result.current, 'optimisticCreateTmpMessage').mockReturnValue('temp-msg-id');
|
|
743
743
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
744
744
|
|
|
745
745
|
const summaryTitleSpy = vi.spyOn(result.current, 'summaryThreadTitle').mockResolvedValue();
|
|
@@ -763,12 +763,12 @@ describe('thread action', () => {
|
|
|
763
763
|
});
|
|
764
764
|
|
|
765
765
|
const createMessageSpy = vi
|
|
766
|
-
.spyOn(result.current, '
|
|
766
|
+
.spyOn(result.current, 'optimisticCreateMessage')
|
|
767
767
|
.mockResolvedValue({ id: 'new-msg-id', messages: [] });
|
|
768
768
|
const coreProcessSpy = vi
|
|
769
|
-
.spyOn(result.current, '
|
|
769
|
+
.spyOn(result.current, 'internal_execAgentRuntime')
|
|
770
770
|
.mockResolvedValue();
|
|
771
|
-
vi.spyOn(result.current, '
|
|
771
|
+
vi.spyOn(result.current, 'optimisticCreateTmpMessage').mockReturnValue('temp-msg-id');
|
|
772
772
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
773
773
|
|
|
774
774
|
await act(async () => {
|
|
@@ -785,9 +785,10 @@ describe('thread action', () => {
|
|
|
785
785
|
);
|
|
786
786
|
|
|
787
787
|
expect(coreProcessSpy).toHaveBeenCalledWith(
|
|
788
|
-
expect.any(Array),
|
|
789
|
-
'new-msg-id',
|
|
790
788
|
expect.objectContaining({
|
|
789
|
+
messages: expect.any(Array),
|
|
790
|
+
parentMessageId: 'new-msg-id',
|
|
791
|
+
parentMessageType: 'user',
|
|
791
792
|
inPortalThread: true,
|
|
792
793
|
threadId: 'existing-thread-id',
|
|
793
794
|
}),
|
|
@@ -803,12 +804,12 @@ describe('thread action', () => {
|
|
|
803
804
|
});
|
|
804
805
|
});
|
|
805
806
|
|
|
806
|
-
vi.spyOn(result.current, '
|
|
807
|
+
vi.spyOn(result.current, 'optimisticCreateMessage').mockResolvedValue({
|
|
807
808
|
id: 'new-msg-id',
|
|
808
809
|
messages: [],
|
|
809
810
|
});
|
|
810
|
-
vi.spyOn(result.current, '
|
|
811
|
-
vi.spyOn(result.current, '
|
|
811
|
+
vi.spyOn(result.current, 'internal_execAgentRuntime').mockResolvedValue();
|
|
812
|
+
vi.spyOn(result.current, 'optimisticCreateTmpMessage').mockReturnValue('temp-msg-id');
|
|
812
813
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
813
814
|
|
|
814
815
|
const summaryTitleSpy = vi.spyOn(result.current, 'summaryThreadTitle').mockResolvedValue();
|
|
@@ -836,12 +837,12 @@ describe('thread action', () => {
|
|
|
836
837
|
});
|
|
837
838
|
});
|
|
838
839
|
|
|
839
|
-
vi.spyOn(result.current, '
|
|
840
|
+
vi.spyOn(result.current, 'optimisticCreateMessage').mockResolvedValue({
|
|
840
841
|
id: 'new-msg-id',
|
|
841
842
|
messages: [],
|
|
842
843
|
});
|
|
843
|
-
vi.spyOn(result.current, '
|
|
844
|
-
vi.spyOn(result.current, '
|
|
844
|
+
vi.spyOn(result.current, 'internal_execAgentRuntime').mockResolvedValue();
|
|
845
|
+
vi.spyOn(result.current, 'optimisticCreateTmpMessage').mockReturnValue('temp-msg-id');
|
|
845
846
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
846
847
|
|
|
847
848
|
await act(async () => {
|
|
@@ -861,15 +862,15 @@ describe('thread action', () => {
|
|
|
861
862
|
});
|
|
862
863
|
|
|
863
864
|
vi.spyOn(result.current, 'internal_shouldUseRAG').mockReturnValue(true);
|
|
864
|
-
vi.spyOn(result.current, '
|
|
865
|
+
vi.spyOn(result.current, 'optimisticCreateMessage').mockResolvedValue({
|
|
865
866
|
id: 'new-msg-id',
|
|
866
867
|
messages: [],
|
|
867
868
|
});
|
|
868
|
-
vi.spyOn(result.current, '
|
|
869
|
+
vi.spyOn(result.current, 'optimisticCreateTmpMessage').mockReturnValue('temp-msg-id');
|
|
869
870
|
vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
|
870
871
|
|
|
871
872
|
const coreProcessSpy = vi
|
|
872
|
-
.spyOn(result.current, '
|
|
873
|
+
.spyOn(result.current, 'internal_execAgentRuntime')
|
|
873
874
|
.mockResolvedValue();
|
|
874
875
|
|
|
875
876
|
await act(async () => {
|
|
@@ -877,9 +878,10 @@ describe('thread action', () => {
|
|
|
877
878
|
});
|
|
878
879
|
|
|
879
880
|
expect(coreProcessSpy).toHaveBeenCalledWith(
|
|
880
|
-
expect.any(Array),
|
|
881
|
-
'new-msg-id',
|
|
882
881
|
expect.objectContaining({
|
|
882
|
+
messages: expect.any(Array),
|
|
883
|
+
parentMessageId: 'new-msg-id',
|
|
884
|
+
parentMessageType: 'user',
|
|
883
885
|
inPortalThread: true,
|
|
884
886
|
ragQuery: 'test with rag',
|
|
885
887
|
threadId: 'existing-thread-id',
|
|
@@ -899,20 +901,15 @@ describe('thread action', () => {
|
|
|
899
901
|
});
|
|
900
902
|
});
|
|
901
903
|
|
|
902
|
-
const resendSpy = vi
|
|
904
|
+
const resendSpy = vi
|
|
905
|
+
.spyOn(result.current, 'regenerateUserMessage')
|
|
906
|
+
.mockResolvedValue(undefined);
|
|
903
907
|
|
|
904
908
|
await act(async () => {
|
|
905
909
|
await result.current.resendThreadMessage('message-id');
|
|
906
910
|
});
|
|
907
911
|
|
|
908
|
-
expect(resendSpy).toHaveBeenCalledWith(
|
|
909
|
-
'message-id',
|
|
910
|
-
expect.objectContaining({
|
|
911
|
-
inPortalThread: true,
|
|
912
|
-
messages: expect.any(Array),
|
|
913
|
-
threadId: 'thread-id',
|
|
914
|
-
}),
|
|
915
|
-
);
|
|
912
|
+
expect(resendSpy).toHaveBeenCalledWith('message-id', {});
|
|
916
913
|
});
|
|
917
914
|
});
|
|
918
915
|
|
|
@@ -100,7 +100,7 @@ export const chatThreadMessage: StateCreator<
|
|
|
100
100
|
},
|
|
101
101
|
sendThreadMessage: async ({ message }) => {
|
|
102
102
|
const {
|
|
103
|
-
|
|
103
|
+
internal_execAgentRuntime,
|
|
104
104
|
activeTopicId,
|
|
105
105
|
activeId,
|
|
106
106
|
threadStartMessageId,
|
|
@@ -132,7 +132,7 @@ export const chatThreadMessage: StateCreator<
|
|
|
132
132
|
if (!portalThreadId) {
|
|
133
133
|
if (!threadStartMessageId) return;
|
|
134
134
|
// we need to create a temp message for optimistic update
|
|
135
|
-
tempMessageId = get().
|
|
135
|
+
tempMessageId = get().optimisticCreateTmpMessage({
|
|
136
136
|
...newMessage,
|
|
137
137
|
threadId: THREAD_DRAFT_ID,
|
|
138
138
|
});
|
|
@@ -155,10 +155,10 @@ export const chatThreadMessage: StateCreator<
|
|
|
155
155
|
} else {
|
|
156
156
|
// if there is a thread, just append message
|
|
157
157
|
// we need to create a temp message for optimistic update
|
|
158
|
-
tempMessageId = get().
|
|
158
|
+
tempMessageId = get().optimisticCreateTmpMessage(newMessage);
|
|
159
159
|
get().internal_toggleMessageLoading(true, tempMessageId);
|
|
160
160
|
|
|
161
|
-
const result = await get().
|
|
161
|
+
const result = await get().optimisticCreateMessage(newMessage, { tempMessageId });
|
|
162
162
|
if (!result) return;
|
|
163
163
|
parentMessageId = result.id;
|
|
164
164
|
}
|
|
@@ -172,7 +172,10 @@ export const chatThreadMessage: StateCreator<
|
|
|
172
172
|
// Get the current messages to generate AI response
|
|
173
173
|
const messages = threadSelectors.portalAIChats(get());
|
|
174
174
|
|
|
175
|
-
await
|
|
175
|
+
await internal_execAgentRuntime({
|
|
176
|
+
messages,
|
|
177
|
+
parentMessageId,
|
|
178
|
+
parentMessageType: 'user',
|
|
176
179
|
ragQuery: get().internal_shouldUseRAG() ? message : undefined,
|
|
177
180
|
threadId: get().portalThreadId,
|
|
178
181
|
inPortalThread: true,
|
|
@@ -191,12 +194,12 @@ export const chatThreadMessage: StateCreator<
|
|
|
191
194
|
}
|
|
192
195
|
},
|
|
193
196
|
resendThreadMessage: async (messageId) => {
|
|
194
|
-
const chats = threadSelectors.portalAIChats(get());
|
|
197
|
+
// const chats = threadSelectors.portalAIChats(get());
|
|
195
198
|
|
|
196
|
-
await get().
|
|
197
|
-
messages: chats,
|
|
198
|
-
threadId: get().portalThreadId,
|
|
199
|
-
inPortalThread: true,
|
|
199
|
+
await get().regenerateUserMessage(messageId, {
|
|
200
|
+
// messages: chats,
|
|
201
|
+
// threadId: get().portalThreadId,
|
|
202
|
+
// inPortalThread: true,
|
|
200
203
|
});
|
|
201
204
|
},
|
|
202
205
|
delAndResendThreadMessage: async (id) => {
|
|
@@ -6,7 +6,7 @@ import { agentChatConfigSelectors } from '@/store/agent/selectors';
|
|
|
6
6
|
import type { ChatStoreState } from '@/store/chat';
|
|
7
7
|
import { chatHelpers } from '@/store/chat/helpers';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { displayMessageSelectors } from '../../message/selectors';
|
|
10
10
|
import { genMessage } from './util';
|
|
11
11
|
|
|
12
12
|
const currentTopicThreads = (s: ChatStoreState) => {
|
|
@@ -52,7 +52,7 @@ const getTheadParentMessages = (s: ChatStoreState, data: UIChatMessage[]) => {
|
|
|
52
52
|
* 获取当前 thread 的父级消息
|
|
53
53
|
*/
|
|
54
54
|
const portalDisplayParentMessages = (s: ChatStoreState): UIChatMessage[] => {
|
|
55
|
-
const data =
|
|
55
|
+
const data = displayMessageSelectors.activeDisplayMessages(s);
|
|
56
56
|
|
|
57
57
|
return getTheadParentMessages(s, data);
|
|
58
58
|
};
|
|
@@ -65,7 +65,7 @@ const portalDisplayChildChatsByThreadId =
|
|
|
65
65
|
(id?: string) =>
|
|
66
66
|
(s: ChatStoreState): UIChatMessage[] => {
|
|
67
67
|
// skip tool message
|
|
68
|
-
const data =
|
|
68
|
+
const data = displayMessageSelectors.activeDisplayMessages(s);
|
|
69
69
|
|
|
70
70
|
return data.filter((m) => !!id && m.threadId === id);
|
|
71
71
|
};
|
|
@@ -74,7 +74,9 @@ const portalDisplayChats = (s: ChatStoreState) => {
|
|
|
74
74
|
const parentMessages = portalDisplayParentMessages(s);
|
|
75
75
|
const afterMessages = portalDisplayChildChatsByThreadId(s.portalThreadId)(s);
|
|
76
76
|
// use for optimistic update
|
|
77
|
-
const draftMessage =
|
|
77
|
+
const draftMessage = displayMessageSelectors
|
|
78
|
+
.activeDisplayMessages(s)
|
|
79
|
+
.find((m) => m.threadId === THREAD_DRAFT_ID);
|
|
78
80
|
|
|
79
81
|
return [...parentMessages, draftMessage, ...afterMessages].filter(Boolean) as UIChatMessage[];
|
|
80
82
|
};
|
|
@@ -96,7 +98,7 @@ const portalDisplayChatIDs = (s: ChatStoreState): string[] =>
|
|
|
96
98
|
// ========================================== //
|
|
97
99
|
|
|
98
100
|
const portalAIParentMessages = (s: ChatStoreState): UIChatMessage[] => {
|
|
99
|
-
const data =
|
|
101
|
+
const data = displayMessageSelectors.activeDisplayMessages(s);
|
|
100
102
|
|
|
101
103
|
return getTheadParentMessages(s, data);
|
|
102
104
|
};
|
|
@@ -105,7 +107,7 @@ const portalAIChildChatsByThreadId =
|
|
|
105
107
|
(id?: string) =>
|
|
106
108
|
(s: ChatStoreState): UIChatMessage[] => {
|
|
107
109
|
// skip tool message
|
|
108
|
-
const data =
|
|
110
|
+
const data = displayMessageSelectors.activeDisplayMessages(s);
|
|
109
111
|
|
|
110
112
|
return data.filter((m) => !!id && m.threadId === id);
|
|
111
113
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import isEqual from 'fast-deep-equal';
|
|
1
2
|
import { produce } from 'immer';
|
|
2
3
|
|
|
3
4
|
import { ChatTopic, CreateTopicParams } from '@/types/topic';
|
|
@@ -52,9 +53,16 @@ export const topicReducer = (state: ChatTopic[] = [], payload: ChatTopicDispatch
|
|
|
52
53
|
const topicIndex = draftState.findIndex((topic) => topic.id === id);
|
|
53
54
|
|
|
54
55
|
if (topicIndex !== -1) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const currentTopic = draftState[topicIndex];
|
|
57
|
+
const mergedTopic = { ...currentTopic, ...value };
|
|
58
|
+
|
|
59
|
+
// Only update if the merged value is different from current (excluding updatedAt)
|
|
60
|
+
|
|
61
|
+
if (!isEqual(currentTopic, mergedTopic)) {
|
|
62
|
+
// TODO: updatedAt 类型后续需要修改为 Date
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
draftState[topicIndex] = { ...mergedTopic, updatedAt: new Date() };
|
|
65
|
+
}
|
|
58
66
|
}
|
|
59
67
|
});
|
|
60
68
|
}
|
package/src/store/chat/store.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { ChatStoreState, initialState } from './initialState';
|
|
|
9
9
|
import { ChatBuiltinToolAction, chatToolSlice } from './slices/builtinTool/actions';
|
|
10
10
|
import { ChatPortalAction, chatPortalSlice } from './slices/portal/action';
|
|
11
11
|
import { ChatTranslateAction, chatTranslate } from './slices/translate/action';
|
|
12
|
-
import { ChatMessageAction, chatMessage } from './slices/message/
|
|
12
|
+
import { ChatMessageAction, chatMessage } from './slices/message/actions';
|
|
13
13
|
import { ChatPluginAction, chatPlugin } from './slices/plugin/action';
|
|
14
14
|
import { ChatTopicAction, chatTopic } from './slices/topic/action';
|
|
15
15
|
import { ChatAIChatAction, chatAiChat } from './slices/aiChat/actions';
|
|
@@ -3,9 +3,6 @@ import { DEFAULT_PREFERENCE } from '@lobechat/const';
|
|
|
3
3
|
import type { UserState } from '@/store/user/initialState';
|
|
4
4
|
|
|
5
5
|
export const labPreferSelectors = {
|
|
6
|
-
enableAssistantMessageGroup: (s: UserState): boolean =>
|
|
7
|
-
s.preference.lab?.enableAssistantMessageGroup ??
|
|
8
|
-
DEFAULT_PREFERENCE.lab!.enableAssistantMessageGroup!,
|
|
9
6
|
enableGroupChat: (s: UserState): boolean =>
|
|
10
7
|
s.preference.lab?.enableGroupChat ?? DEFAULT_PREFERENCE.lab!.enableGroupChat!,
|
|
11
8
|
enableInputMarkdown: (s: UserState): boolean =>
|