@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
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
|
|
2
|
+
// Disable the auto sort key eslint rule to make the code more logic and readable
|
|
3
|
+
import { MESSAGE_CANCEL_FLAT } from '@lobechat/const';
|
|
4
|
+
import { produce } from 'immer';
|
|
5
|
+
import { StateCreator } from 'zustand/vanilla';
|
|
6
|
+
|
|
7
|
+
import { ChatStore } from '@/store/chat/store';
|
|
8
|
+
import { setNamespace } from '@/utils/storeDebug';
|
|
9
|
+
|
|
10
|
+
import { messageMapKey } from '../../../utils/messageMapKey';
|
|
11
|
+
import { MainSendMessageOperation } from '../initialState';
|
|
12
|
+
|
|
13
|
+
const n = setNamespace('ai');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Actions for controlling conversation operations like cancellation and error handling
|
|
17
|
+
*/
|
|
18
|
+
export interface ConversationControlAction {
|
|
19
|
+
/**
|
|
20
|
+
* Interrupts the ongoing ai message generation process
|
|
21
|
+
*/
|
|
22
|
+
stopGenerateMessage: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Cancels sendMessage operation for a specific topic/session
|
|
25
|
+
*/
|
|
26
|
+
cancelSendMessageInServer: (topicId?: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Clears any error messages from the send message operation
|
|
29
|
+
*/
|
|
30
|
+
clearSendMessageError: () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Switches to a different branch of a message
|
|
33
|
+
*/
|
|
34
|
+
switchMessageBranch: (messageId: string, branchIndex: number) => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Toggle sendMessage operation state
|
|
37
|
+
*/
|
|
38
|
+
internal_toggleSendMessageOperation: (
|
|
39
|
+
key: string | { sessionId: string; topicId?: string | null },
|
|
40
|
+
loading: boolean,
|
|
41
|
+
cancelReason?: string,
|
|
42
|
+
) => AbortController | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Update sendMessage operation metadata
|
|
45
|
+
*/
|
|
46
|
+
internal_updateSendMessageOperation: (
|
|
47
|
+
key: string | { sessionId: string; topicId?: string | null },
|
|
48
|
+
value: Partial<MainSendMessageOperation> | null,
|
|
49
|
+
actionName?: any,
|
|
50
|
+
) => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const conversationControl: StateCreator<
|
|
54
|
+
ChatStore,
|
|
55
|
+
[['zustand/devtools', never]],
|
|
56
|
+
[],
|
|
57
|
+
ConversationControlAction
|
|
58
|
+
> = (set, get) => ({
|
|
59
|
+
stopGenerateMessage: () => {
|
|
60
|
+
const { chatLoadingIdsAbortController, internal_toggleChatLoading } = get();
|
|
61
|
+
|
|
62
|
+
if (!chatLoadingIdsAbortController) return;
|
|
63
|
+
|
|
64
|
+
chatLoadingIdsAbortController.abort(MESSAGE_CANCEL_FLAT);
|
|
65
|
+
|
|
66
|
+
internal_toggleChatLoading(false, undefined, n('stopGenerateMessage') as string);
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
cancelSendMessageInServer: (topicId?: string) => {
|
|
70
|
+
const { activeId, activeTopicId } = get();
|
|
71
|
+
|
|
72
|
+
// Determine which operation to cancel
|
|
73
|
+
const targetTopicId = topicId ?? activeTopicId;
|
|
74
|
+
const operationKey = messageMapKey(activeId, targetTopicId);
|
|
75
|
+
|
|
76
|
+
// Cancel the specific operation
|
|
77
|
+
get().internal_toggleSendMessageOperation(
|
|
78
|
+
operationKey,
|
|
79
|
+
false,
|
|
80
|
+
'User cancelled sendMessage operation',
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Only clear creating message state if it's the active session
|
|
84
|
+
if (operationKey === messageMapKey(activeId, activeTopicId)) {
|
|
85
|
+
const editorTempState = get().mainSendMessageOperations[operationKey]?.inputEditorTempState;
|
|
86
|
+
|
|
87
|
+
if (editorTempState) get().mainInputEditor?.setJSONState(editorTempState);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
clearSendMessageError: () => {
|
|
92
|
+
get().internal_updateSendMessageOperation(
|
|
93
|
+
{ sessionId: get().activeId, topicId: get().activeTopicId },
|
|
94
|
+
null,
|
|
95
|
+
'clearSendMessageError',
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
switchMessageBranch: async (messageId, branchIndex) => {
|
|
100
|
+
await get().optimisticUpdateMessageMetadata(messageId, { activeBranchIndex: branchIndex });
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
internal_toggleSendMessageOperation: (key, loading: boolean, cancelReason?: string) => {
|
|
104
|
+
if (loading) {
|
|
105
|
+
const abortController = new AbortController();
|
|
106
|
+
|
|
107
|
+
get().internal_updateSendMessageOperation(
|
|
108
|
+
key,
|
|
109
|
+
{ isLoading: true, abortController },
|
|
110
|
+
n('toggleSendMessageOperation(start)', { key }),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return abortController;
|
|
114
|
+
} else {
|
|
115
|
+
const operationKey =
|
|
116
|
+
typeof key === 'string' ? key : messageMapKey(key.sessionId, key.topicId);
|
|
117
|
+
|
|
118
|
+
const operation = get().mainSendMessageOperations[operationKey];
|
|
119
|
+
|
|
120
|
+
// If cancelReason is provided, abort the operation first
|
|
121
|
+
if (cancelReason && operation?.isLoading) {
|
|
122
|
+
operation.abortController?.abort(cancelReason);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
get().internal_updateSendMessageOperation(
|
|
126
|
+
key,
|
|
127
|
+
{ isLoading: false, abortController: null },
|
|
128
|
+
n('toggleSendMessageOperation(stop)', { key, cancelReason }),
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
internal_updateSendMessageOperation: (key, value, actionName) => {
|
|
136
|
+
const operationKey = typeof key === 'string' ? key : messageMapKey(key.sessionId, key.topicId);
|
|
137
|
+
|
|
138
|
+
set(
|
|
139
|
+
produce((draft) => {
|
|
140
|
+
if (!draft.mainSendMessageOperations[operationKey])
|
|
141
|
+
draft.mainSendMessageOperations[operationKey] = value;
|
|
142
|
+
else {
|
|
143
|
+
if (value === null) {
|
|
144
|
+
delete draft.mainSendMessageOperations[operationKey];
|
|
145
|
+
} else {
|
|
146
|
+
draft.mainSendMessageOperations[operationKey] = {
|
|
147
|
+
...draft.mainSendMessageOperations[operationKey],
|
|
148
|
+
...value,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}),
|
|
153
|
+
false,
|
|
154
|
+
actionName ?? n('updateSendMessageOperation', { operationKey, value }),
|
|
155
|
+
);
|
|
156
|
+
},
|
|
157
|
+
});
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
|
|
2
|
+
// Disable the auto sort key eslint rule to make the code more logic and readable
|
|
3
|
+
import { DEFAULT_AGENT_CHAT_CONFIG, INBOX_SESSION_ID } from '@lobechat/const';
|
|
4
|
+
import {
|
|
5
|
+
ChatImageItem,
|
|
6
|
+
ChatVideoItem,
|
|
7
|
+
SendMessageParams,
|
|
8
|
+
SendMessageServerResponse,
|
|
9
|
+
TraceEventType,
|
|
10
|
+
} from '@lobechat/types';
|
|
11
|
+
import { TRPCClientError } from '@trpc/client';
|
|
12
|
+
import { t } from 'i18next';
|
|
13
|
+
import { StateCreator } from 'zustand/vanilla';
|
|
14
|
+
|
|
15
|
+
import { aiChatService } from '@/services/aiChat';
|
|
16
|
+
import { getAgentStoreState } from '@/store/agent';
|
|
17
|
+
import { agentChatConfigSelectors, agentSelectors } from '@/store/agent/slices/chat';
|
|
18
|
+
import { ChatStore } from '@/store/chat/store';
|
|
19
|
+
import { getFileStoreState } from '@/store/file/store';
|
|
20
|
+
import { getSessionStoreState } from '@/store/session';
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
dbMessageSelectors,
|
|
24
|
+
displayMessageSelectors,
|
|
25
|
+
messageStateSelectors,
|
|
26
|
+
topicSelectors,
|
|
27
|
+
} from '../../../selectors';
|
|
28
|
+
import { messageMapKey } from '../../../utils/messageMapKey';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Actions managing the complete lifecycle of conversations including sending,
|
|
32
|
+
* regenerating, and resending messages
|
|
33
|
+
*/
|
|
34
|
+
export interface ConversationLifecycleAction {
|
|
35
|
+
/**
|
|
36
|
+
* Sends a new message to the AI chat system
|
|
37
|
+
*/
|
|
38
|
+
sendMessage: (params: SendMessageParams) => Promise<void>;
|
|
39
|
+
regenerateUserMessage: (
|
|
40
|
+
id: string,
|
|
41
|
+
params?: { skipTrace?: boolean; traceId?: string },
|
|
42
|
+
) => Promise<void>;
|
|
43
|
+
regenerateAssistantMessage: (
|
|
44
|
+
id: string,
|
|
45
|
+
params?: { skipTrace?: boolean; traceId?: string },
|
|
46
|
+
) => Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Deletes an existing message and generates a new one in its place
|
|
49
|
+
*/
|
|
50
|
+
delAndRegenerateMessage: (id: string) => Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const conversationLifecycle: StateCreator<
|
|
54
|
+
ChatStore,
|
|
55
|
+
[['zustand/devtools', never]],
|
|
56
|
+
[],
|
|
57
|
+
ConversationLifecycleAction
|
|
58
|
+
> = (set, get) => ({
|
|
59
|
+
sendMessage: async ({ message, files, onlyAddUserMessage }) => {
|
|
60
|
+
const { activeTopicId, activeId, activeThreadId, internal_execAgentRuntime, mainInputEditor } =
|
|
61
|
+
get();
|
|
62
|
+
if (!activeId) return;
|
|
63
|
+
|
|
64
|
+
const fileIdList = files?.map((f) => f.id);
|
|
65
|
+
|
|
66
|
+
const hasFile = !!fileIdList && fileIdList.length > 0;
|
|
67
|
+
|
|
68
|
+
// if message is empty or no files, then stop
|
|
69
|
+
if (!message && !hasFile) return;
|
|
70
|
+
|
|
71
|
+
if (onlyAddUserMessage) {
|
|
72
|
+
await get().addUserMessage({ message, fileList: fileIdList });
|
|
73
|
+
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const messages = displayMessageSelectors.activeDisplayMessages(get());
|
|
78
|
+
const parentId = displayMessageSelectors.lastDisplayMessageId(get());
|
|
79
|
+
|
|
80
|
+
const chatConfig = agentChatConfigSelectors.currentChatConfig(getAgentStoreState());
|
|
81
|
+
const autoCreateThreshold =
|
|
82
|
+
chatConfig.autoCreateTopicThreshold ?? DEFAULT_AGENT_CHAT_CONFIG.autoCreateTopicThreshold;
|
|
83
|
+
const shouldCreateNewTopic =
|
|
84
|
+
!activeTopicId &&
|
|
85
|
+
!!chatConfig.enableAutoCreateTopic &&
|
|
86
|
+
messages.length + 2 >= autoCreateThreshold;
|
|
87
|
+
|
|
88
|
+
// 构造服务端模式临时消息的本地媒体预览(优先使用 S3 URL)
|
|
89
|
+
const filesInStore = getFileStoreState().chatUploadFileList;
|
|
90
|
+
const tempImages: ChatImageItem[] = filesInStore
|
|
91
|
+
.filter((f) => f.file?.type?.startsWith('image'))
|
|
92
|
+
.map((f) => ({
|
|
93
|
+
id: f.id,
|
|
94
|
+
url: f.fileUrl || f.base64Url || f.previewUrl || '',
|
|
95
|
+
alt: f.file?.name || f.id,
|
|
96
|
+
}));
|
|
97
|
+
const tempVideos: ChatVideoItem[] = filesInStore
|
|
98
|
+
.filter((f) => f.file?.type?.startsWith('video'))
|
|
99
|
+
.map((f) => ({
|
|
100
|
+
id: f.id,
|
|
101
|
+
url: f.fileUrl || f.base64Url || f.previewUrl || '',
|
|
102
|
+
alt: f.file?.name || f.id,
|
|
103
|
+
}));
|
|
104
|
+
|
|
105
|
+
// use optimistic update to avoid the slow waiting
|
|
106
|
+
const tempId = get().optimisticCreateTmpMessage({
|
|
107
|
+
content: message,
|
|
108
|
+
// if message has attached with files, then add files to message and the agent
|
|
109
|
+
files: fileIdList,
|
|
110
|
+
role: 'user',
|
|
111
|
+
sessionId: activeId,
|
|
112
|
+
// if there is activeTopicId,then add topicId to message
|
|
113
|
+
topicId: activeTopicId,
|
|
114
|
+
threadId: activeThreadId,
|
|
115
|
+
imageList: tempImages.length > 0 ? tempImages : undefined,
|
|
116
|
+
videoList: tempVideos.length > 0 ? tempVideos : undefined,
|
|
117
|
+
});
|
|
118
|
+
get().internal_toggleMessageLoading(true, tempId);
|
|
119
|
+
|
|
120
|
+
const operationKey = messageMapKey(activeId, activeTopicId);
|
|
121
|
+
|
|
122
|
+
// Start tracking sendMessage operation with AbortController
|
|
123
|
+
const abortController = get().internal_toggleSendMessageOperation(operationKey, true)!;
|
|
124
|
+
|
|
125
|
+
const jsonState = mainInputEditor?.getJSONState();
|
|
126
|
+
get().internal_updateSendMessageOperation(
|
|
127
|
+
operationKey,
|
|
128
|
+
{ inputSendErrorMsg: undefined, inputEditorTempState: jsonState },
|
|
129
|
+
'creatingMessage/start',
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
let data: SendMessageServerResponse | undefined;
|
|
133
|
+
try {
|
|
134
|
+
const { model, provider } = agentSelectors.currentAgentConfig(getAgentStoreState());
|
|
135
|
+
|
|
136
|
+
data = await aiChatService.sendMessageInServer(
|
|
137
|
+
{
|
|
138
|
+
newUserMessage: { content: message, files: fileIdList, parentId },
|
|
139
|
+
// if there is activeTopicId,then add topicId to message
|
|
140
|
+
topicId: activeTopicId,
|
|
141
|
+
threadId: activeThreadId,
|
|
142
|
+
newTopic: shouldCreateNewTopic
|
|
143
|
+
? {
|
|
144
|
+
topicMessageIds: messages.map((m) => m.id),
|
|
145
|
+
title: t('defaultTitle', { ns: 'topic' }),
|
|
146
|
+
}
|
|
147
|
+
: undefined,
|
|
148
|
+
sessionId: activeId === INBOX_SESSION_ID ? undefined : activeId,
|
|
149
|
+
newAssistantMessage: { model, provider: provider! },
|
|
150
|
+
},
|
|
151
|
+
abortController,
|
|
152
|
+
);
|
|
153
|
+
let topicId = activeTopicId;
|
|
154
|
+
// refresh the total data
|
|
155
|
+
if (data?.topics) {
|
|
156
|
+
get().internal_dispatchTopic({ type: 'updateTopics', value: data.topics });
|
|
157
|
+
topicId = data.topicId;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get().replaceMessages(data.messages, { sessionId: activeId, topicId: topicId });
|
|
161
|
+
|
|
162
|
+
if (data.isCreateNewTopic && data.topicId) {
|
|
163
|
+
await get().switchTopic(data.topicId, true);
|
|
164
|
+
}
|
|
165
|
+
} catch (e) {
|
|
166
|
+
if (e instanceof TRPCClientError) {
|
|
167
|
+
const isAbort = e.message.includes('aborted') || e.name === 'AbortError';
|
|
168
|
+
// Check if error is due to cancellation
|
|
169
|
+
if (!isAbort) {
|
|
170
|
+
get().internal_updateSendMessageOperation(operationKey, { inputSendErrorMsg: e.message });
|
|
171
|
+
get().mainInputEditor?.setJSONState(jsonState);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
} finally {
|
|
175
|
+
// Stop tracking sendMessage operation
|
|
176
|
+
get().internal_toggleSendMessageOperation(operationKey, false);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// remove temporally message
|
|
180
|
+
if (data?.isCreateNewTopic) {
|
|
181
|
+
get().internal_dispatchMessage(
|
|
182
|
+
{ type: 'deleteMessage', id: tempId },
|
|
183
|
+
{ topicId: activeTopicId, sessionId: activeId },
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
get().internal_toggleMessageLoading(false, tempId);
|
|
188
|
+
get().internal_updateSendMessageOperation(
|
|
189
|
+
operationKey,
|
|
190
|
+
{ inputEditorTempState: null },
|
|
191
|
+
'creatingMessage/finished',
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
if (!data) return;
|
|
195
|
+
|
|
196
|
+
// update assistant update to make it rerank
|
|
197
|
+
getSessionStoreState().triggerSessionUpdate(get().activeId);
|
|
198
|
+
|
|
199
|
+
if (data.topicId) get().internal_updateTopicLoading(data.topicId, true);
|
|
200
|
+
|
|
201
|
+
const summaryTitle = async () => {
|
|
202
|
+
// check activeTopic and then auto update topic title
|
|
203
|
+
if (data.isCreateNewTopic) {
|
|
204
|
+
await get().summaryTopicTitle(data.topicId, data.messages);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!data.topicId) return;
|
|
209
|
+
|
|
210
|
+
const topic = topicSelectors.getTopicById(data.topicId)(get());
|
|
211
|
+
|
|
212
|
+
if (topic && !topic.title) {
|
|
213
|
+
const chats = displayMessageSelectors
|
|
214
|
+
.getDisplayMessagesByKey(messageMapKey(activeId, topic.id))(get())
|
|
215
|
+
.filter((item) => item.id !== data.assistantMessageId);
|
|
216
|
+
|
|
217
|
+
await get().summaryTopicTitle(topic.id, chats);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
summaryTitle().catch(console.error);
|
|
222
|
+
|
|
223
|
+
// Get the current messages to generate AI response
|
|
224
|
+
const displayMessages = displayMessageSelectors.activeDisplayMessages(get());
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
await internal_execAgentRuntime({
|
|
228
|
+
messages: displayMessages,
|
|
229
|
+
parentMessageId: data.assistantMessageId,
|
|
230
|
+
parentMessageType: 'assistant',
|
|
231
|
+
ragQuery: get().internal_shouldUseRAG() ? message : undefined,
|
|
232
|
+
threadId: activeThreadId,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
//
|
|
236
|
+
// // if there is relative files, then add files to agent
|
|
237
|
+
// // only available in server mode
|
|
238
|
+
const userFiles = dbMessageSelectors
|
|
239
|
+
.dbUserFiles(get())
|
|
240
|
+
.map((f) => f?.id)
|
|
241
|
+
.filter(Boolean) as string[];
|
|
242
|
+
|
|
243
|
+
await getAgentStoreState().addFilesToAgent(userFiles, false);
|
|
244
|
+
} catch (e) {
|
|
245
|
+
console.error(e);
|
|
246
|
+
} finally {
|
|
247
|
+
if (data.topicId) get().internal_updateTopicLoading(data.topicId, false);
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
regenerateUserMessage: async (id, params) => {
|
|
252
|
+
const isRegenerating = messageStateSelectors.isMessageRegenerating(id)(get());
|
|
253
|
+
if (isRegenerating) return;
|
|
254
|
+
|
|
255
|
+
const item = displayMessageSelectors.getDisplayMessageById(id)(get());
|
|
256
|
+
if (!item) return;
|
|
257
|
+
|
|
258
|
+
const chats = displayMessageSelectors.mainAIChats(get());
|
|
259
|
+
|
|
260
|
+
const currentIndex = chats.findIndex((c) => c.id === id);
|
|
261
|
+
const contextMessages = chats.slice(0, currentIndex + 1);
|
|
262
|
+
|
|
263
|
+
if (contextMessages.length <= 0) return;
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const { internal_execAgentRuntime, activeThreadId } = get();
|
|
267
|
+
|
|
268
|
+
// Mark message as regenerating
|
|
269
|
+
set(
|
|
270
|
+
{ regeneratingIds: [...get().regeneratingIds, id] },
|
|
271
|
+
false,
|
|
272
|
+
'regenerateUserMessage/start',
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const traceId = params?.traceId ?? dbMessageSelectors.getTraceIdByDbMessageId(id)(get());
|
|
276
|
+
|
|
277
|
+
// 切一个新的激活分支
|
|
278
|
+
await get().switchMessageBranch(id, item.branch ? item.branch.count : 1);
|
|
279
|
+
|
|
280
|
+
await internal_execAgentRuntime({
|
|
281
|
+
messages: contextMessages,
|
|
282
|
+
parentMessageId: id,
|
|
283
|
+
parentMessageType: 'user',
|
|
284
|
+
traceId,
|
|
285
|
+
ragQuery: get().internal_shouldUseRAG() ? item.content : undefined,
|
|
286
|
+
threadId: activeThreadId,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// trace the regenerate message
|
|
290
|
+
if (!params?.skipTrace)
|
|
291
|
+
get().internal_traceMessage(id, { eventType: TraceEventType.RegenerateMessage });
|
|
292
|
+
} finally {
|
|
293
|
+
// Remove message from regenerating state
|
|
294
|
+
set(
|
|
295
|
+
{ regeneratingIds: get().regeneratingIds.filter((msgId) => msgId !== id) },
|
|
296
|
+
false,
|
|
297
|
+
'regenerateUserMessage/end',
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
|
|
302
|
+
regenerateAssistantMessage: async (id, params) => {
|
|
303
|
+
const isRegenerating = messageStateSelectors.isMessageRegenerating(id)(get());
|
|
304
|
+
if (isRegenerating) return;
|
|
305
|
+
|
|
306
|
+
const chats = displayMessageSelectors.mainAIChats(get());
|
|
307
|
+
const currentIndex = chats.findIndex((c) => c.id === id);
|
|
308
|
+
const currentMessage = chats[currentIndex];
|
|
309
|
+
|
|
310
|
+
// 消息是 AI 发出的因此需要找到它的 user 消息
|
|
311
|
+
const userId = currentMessage.parentId;
|
|
312
|
+
const userIndex = chats.findIndex((c) => c.id === userId);
|
|
313
|
+
// 如果消息没有 parentId,那么同 user 模式
|
|
314
|
+
const contextMessages = chats.slice(0, userIndex < 0 ? currentIndex + 1 : userIndex + 1);
|
|
315
|
+
|
|
316
|
+
if (contextMessages.length <= 0 || !userId) return;
|
|
317
|
+
|
|
318
|
+
await get().regenerateUserMessage(userId, params);
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
delAndRegenerateMessage: async (id) => {
|
|
322
|
+
const traceId = dbMessageSelectors.getTraceIdByDbMessageId(id)(get());
|
|
323
|
+
get().regenerateAssistantMessage(id, { skipTrace: true, traceId });
|
|
324
|
+
get().deleteMessage(id);
|
|
325
|
+
|
|
326
|
+
// trace the delete and regenerate message
|
|
327
|
+
get().internal_traceMessage(id, { eventType: TraceEventType.DeleteAndRegenerateMessage });
|
|
328
|
+
},
|
|
329
|
+
});
|
|
@@ -271,7 +271,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
271
271
|
return {
|
|
272
272
|
sendGroupMessage: async ({ groupId, message, files, onlyAddUserMessage, targetMemberId }) => {
|
|
273
273
|
const {
|
|
274
|
-
|
|
274
|
+
optimisticCreateMessage,
|
|
275
275
|
internal_triggerSupervisorDecisionDebounced,
|
|
276
276
|
internal_setActiveGroup,
|
|
277
277
|
activeTopicId,
|
|
@@ -294,7 +294,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
294
294
|
targetId: targetMemberId,
|
|
295
295
|
};
|
|
296
296
|
|
|
297
|
-
const result = await
|
|
297
|
+
const result = await optimisticCreateMessage(userMessage);
|
|
298
298
|
|
|
299
299
|
// if only add user message, then stop
|
|
300
300
|
if (onlyAddUserMessage) {
|
|
@@ -379,7 +379,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
379
379
|
const {
|
|
380
380
|
messagesMap,
|
|
381
381
|
internal_toggleSupervisorLoading,
|
|
382
|
-
|
|
382
|
+
optimisticCreateMessage,
|
|
383
383
|
supervisorTodos,
|
|
384
384
|
} = get();
|
|
385
385
|
|
|
@@ -398,8 +398,8 @@ export const chatAiGroupChat: StateCreator<
|
|
|
398
398
|
const content = formatSupervisorTodoContent(todoList);
|
|
399
399
|
const supervisorMessage: CreateMessageParams = {
|
|
400
400
|
content,
|
|
401
|
-
|
|
402
|
-
|
|
401
|
+
model: groupConfig.orchestratorModel,
|
|
402
|
+
provider: groupConfig.orchestratorProvider,
|
|
403
403
|
groupId,
|
|
404
404
|
role: 'supervisor',
|
|
405
405
|
sessionId,
|
|
@@ -408,7 +408,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
408
408
|
|
|
409
409
|
console.log('Creating supervisor todo message:', supervisorMessage);
|
|
410
410
|
|
|
411
|
-
await
|
|
411
|
+
await optimisticCreateMessage(supervisorMessage);
|
|
412
412
|
};
|
|
413
413
|
|
|
414
414
|
const messages = messagesMap[messageMapKey(groupId, currentTopicId)] || [];
|
|
@@ -597,7 +597,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
597
597
|
});
|
|
598
598
|
const {
|
|
599
599
|
messagesMap,
|
|
600
|
-
|
|
600
|
+
optimisticCreateMessage,
|
|
601
601
|
internal_fetchAIChatMessage,
|
|
602
602
|
refreshMessages,
|
|
603
603
|
activeTopicId,
|
|
@@ -659,10 +659,10 @@ export const chatAiGroupChat: StateCreator<
|
|
|
659
659
|
// Create agent message using real agent config
|
|
660
660
|
const agentMessage: CreateMessageParams = {
|
|
661
661
|
role: 'assistant',
|
|
662
|
-
|
|
662
|
+
model: agentModel,
|
|
663
663
|
groupId,
|
|
664
664
|
content: LOADING_FLAT,
|
|
665
|
-
|
|
665
|
+
provider: agentProvider,
|
|
666
666
|
agentId,
|
|
667
667
|
sessionId: useSessionStore.getState().activeId,
|
|
668
668
|
topicId: activeTopicId,
|
|
@@ -671,7 +671,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
671
671
|
|
|
672
672
|
console.log('DEBUG: Creating agent message with:', agentMessage);
|
|
673
673
|
|
|
674
|
-
const result = await
|
|
674
|
+
const result = await optimisticCreateMessage(agentMessage);
|
|
675
675
|
if (!result) return;
|
|
676
676
|
const assistantId = result.id;
|
|
677
677
|
|
|
@@ -936,7 +936,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
936
936
|
},
|
|
937
937
|
|
|
938
938
|
internal_createSupervisorErrorMessage: async (groupId: string, error: Error | string) => {
|
|
939
|
-
const {
|
|
939
|
+
const { optimisticCreateTmpMessage, activeTopicId } = get();
|
|
940
940
|
|
|
941
941
|
try {
|
|
942
942
|
const errorMessage = error instanceof Error ? error.message : error;
|
|
@@ -944,8 +944,8 @@ export const chatAiGroupChat: StateCreator<
|
|
|
944
944
|
|
|
945
945
|
const supervisorMessage: CreateMessageParams = {
|
|
946
946
|
role: 'supervisor',
|
|
947
|
-
|
|
948
|
-
|
|
947
|
+
model: groupConfig.orchestratorModel,
|
|
948
|
+
provider: groupConfig.orchestratorProvider,
|
|
949
949
|
groupId,
|
|
950
950
|
sessionId: useSessionStore.getState().activeId || groupId,
|
|
951
951
|
topicId: activeTopicId,
|
|
@@ -957,7 +957,7 @@ export const chatAiGroupChat: StateCreator<
|
|
|
957
957
|
};
|
|
958
958
|
|
|
959
959
|
// Create a temporary message that only exists in UI state, no API call
|
|
960
|
-
|
|
960
|
+
optimisticCreateTmpMessage(supervisorMessage);
|
|
961
961
|
} catch (createError) {
|
|
962
962
|
console.error('Failed to create supervisor error message:', createError);
|
|
963
963
|
}
|
|
@@ -2,16 +2,20 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
2
2
|
|
|
3
3
|
import { ChatStore } from '@/store/chat/store';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { ConversationControlAction, conversationControl } from './conversationControl';
|
|
6
|
+
import { ConversationLifecycleAction, conversationLifecycle } from './conversationLifecycle';
|
|
7
7
|
import { ChatMemoryAction, chatMemory } from './memory';
|
|
8
8
|
import { ChatRAGAction, chatRag } from './rag';
|
|
9
|
+
import { StreamingExecutorAction, streamingExecutor } from './streamingExecutor';
|
|
10
|
+
import { StreamingStatesAction, streamingStates } from './streamingStates';
|
|
9
11
|
|
|
10
12
|
export interface ChatAIChatAction
|
|
11
13
|
extends ChatRAGAction,
|
|
12
14
|
ChatMemoryAction,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
ConversationLifecycleAction,
|
|
16
|
+
ConversationControlAction,
|
|
17
|
+
StreamingExecutorAction,
|
|
18
|
+
StreamingStatesAction {
|
|
15
19
|
/**/
|
|
16
20
|
}
|
|
17
21
|
|
|
@@ -22,7 +26,9 @@ export const chatAiChat: StateCreator<
|
|
|
22
26
|
ChatAIChatAction
|
|
23
27
|
> = (...params) => ({
|
|
24
28
|
...chatRag(...params),
|
|
25
|
-
...generateAIChat(...params),
|
|
26
29
|
...chatMemory(...params),
|
|
27
|
-
...
|
|
30
|
+
...conversationLifecycle(...params),
|
|
31
|
+
...conversationControl(...params),
|
|
32
|
+
...streamingExecutor(...params),
|
|
33
|
+
...streamingStates(...params),
|
|
28
34
|
});
|
|
@@ -6,7 +6,7 @@ import { ragService } from '@/services/rag';
|
|
|
6
6
|
import { useAgentStore } from '@/store/agent';
|
|
7
7
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
8
8
|
import { ChatStore } from '@/store/chat';
|
|
9
|
-
import {
|
|
9
|
+
import { dbMessageSelectors, displayMessageSelectors } from '@/store/chat/selectors';
|
|
10
10
|
import { toggleBooleanList } from '@/store/chat/utils';
|
|
11
11
|
import { useUserStore } from '@/store/user';
|
|
12
12
|
import { systemAgentSelectors } from '@/store/user/selectors';
|
|
@@ -43,7 +43,7 @@ export const chatRag: StateCreator<ChatStore, [['zustand/devtools', never]], [],
|
|
|
43
43
|
get,
|
|
44
44
|
) => ({
|
|
45
45
|
deleteUserMessageRagQuery: async (id) => {
|
|
46
|
-
const message =
|
|
46
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
47
47
|
|
|
48
48
|
if (!message || !message.ragQueryId) return;
|
|
49
49
|
|
|
@@ -61,7 +61,7 @@ export const chatRag: StateCreator<ChatStore, [['zustand/devtools', never]], [],
|
|
|
61
61
|
internal_retrieveChunks: async (id, userQuery, messages) => {
|
|
62
62
|
get().internal_toggleMessageRAGLoading(true, id);
|
|
63
63
|
|
|
64
|
-
const message =
|
|
64
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
65
65
|
|
|
66
66
|
// 1. get the rewrite query
|
|
67
67
|
let rewriteQuery = message?.ragQuery as string | undefined;
|
|
@@ -73,7 +73,10 @@ export const chatRag: StateCreator<ChatStore, [['zustand/devtools', never]], [],
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// 2. retrieve chunks from semantic search
|
|
76
|
-
const files =
|
|
76
|
+
const files = dbMessageSelectors
|
|
77
|
+
.dbUserFiles(get())
|
|
78
|
+
.map((f) => f?.id)
|
|
79
|
+
.filter(Boolean) as string[];
|
|
77
80
|
try {
|
|
78
81
|
const { chunks, queryId } = await ragService.semanticSearchForChat({
|
|
79
82
|
fileIds: knowledgeIds().fileIds.concat(files),
|
|
@@ -145,13 +148,13 @@ export const chatRag: StateCreator<ChatStore, [['zustand/devtools', never]], [],
|
|
|
145
148
|
},
|
|
146
149
|
|
|
147
150
|
rewriteQuery: async (id) => {
|
|
148
|
-
const message =
|
|
151
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
149
152
|
if (!message) return;
|
|
150
153
|
|
|
151
154
|
// delete the current ragQuery
|
|
152
155
|
await get().deleteUserMessageRagQuery(id);
|
|
153
156
|
|
|
154
|
-
const chats =
|
|
157
|
+
const chats = displayMessageSelectors.mainAIChatsWithHistoryConfig(get());
|
|
155
158
|
|
|
156
159
|
await get().internal_rewriteQuery(
|
|
157
160
|
id,
|