mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-24 10:40:07 +08:00
优化消息块渲染性能,使用 useMemo 缓存图像块组;移除调试日志以清理代码 (#5722)
This commit is contained in:
parent
22315b7201
commit
afcb0eeae2
@ -12,7 +12,7 @@ import type {
|
||||
TranslationMessageBlock
|
||||
} from '@renderer/types/newMessage'
|
||||
import { MessageBlockStatus, MessageBlockType } from '@renderer/types/newMessage'
|
||||
import React from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -53,7 +53,7 @@ const MessageBlockRenderer: React.FC<Props> = ({ blocks, message }) => {
|
||||
const blockEntities = useSelector((state: RootState) => messageBlocksSelectors.selectEntities(state))
|
||||
// 根据blocks类型处理渲染数据
|
||||
const renderedBlocks = blocks.map((blockId) => blockEntities[blockId]).filter(Boolean)
|
||||
const groupedBlocks = filterImageBlockGroups(renderedBlocks)
|
||||
const groupedBlocks = useMemo(() => filterImageBlockGroups(renderedBlocks), [renderedBlocks])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -31,7 +31,6 @@ export default class AiProvider {
|
||||
onChunk,
|
||||
onFilterMessages
|
||||
}: CompletionsParams): Promise<void> {
|
||||
console.log('[DEBUG] AiProvider.completions called')
|
||||
return this.sdk.completions({ messages, assistant, mcpTools, onChunk, onFilterMessages })
|
||||
}
|
||||
|
||||
|
||||
@ -120,11 +120,9 @@ async function fetchExternalTool(
|
||||
// Pass the guaranteed model to the check function
|
||||
const webSearchParams = getOpenAIWebSearchParams(assistant, assistant.model)
|
||||
if (!isEmpty(webSearchParams) || isOpenAIWebSearch(assistant.model)) {
|
||||
console.log('Using built-in OpenAI web search, skipping external search.')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Performing external web search...')
|
||||
try {
|
||||
// Use the consolidated processWebsearch function
|
||||
WebSearchService.createAbortSignal(lastUserMessage.id)
|
||||
@ -151,7 +149,6 @@ async function fetchExternalTool(
|
||||
|
||||
if (!shouldSearch) return
|
||||
|
||||
console.log('Performing knowledge base search...')
|
||||
try {
|
||||
// Attempt to get knowledgeBaseIds from the main text block
|
||||
// NOTE: This assumes knowledgeBaseIds are ONLY on the main text block
|
||||
@ -170,7 +167,6 @@ async function fetchExternalTool(
|
||||
|
||||
// --- Execute Extraction and Searches ---
|
||||
const extractResults = await extract()
|
||||
// console.log('extractResults', extractResults)
|
||||
// Run searches potentially in parallel
|
||||
|
||||
let webSearchResponseFromSearch: WebSearchResponse | undefined
|
||||
@ -242,9 +238,7 @@ export async function fetchChatCompletion({
|
||||
// TODO
|
||||
// onChunkStatus: (status: 'searching' | 'processing' | 'success' | 'error') => void
|
||||
}) {
|
||||
console.log('[DEBUG] fetchChatCompletion started')
|
||||
const provider = getAssistantProvider(assistant)
|
||||
console.log('[DEBUG] Got assistant provider:', provider.id)
|
||||
const AI = new AiProvider(provider)
|
||||
|
||||
// Make sure that 'Clear Context' works for all scenarios including external tool and normal chat.
|
||||
@ -264,7 +258,6 @@ export async function fetchChatCompletion({
|
||||
const filteredMessages = filterUsefulMessages(messages)
|
||||
|
||||
// --- Call AI Completions ---
|
||||
console.log('[DEBUG] Calling AI.completions')
|
||||
await AI.completions({
|
||||
messages: filteredMessages,
|
||||
assistant,
|
||||
@ -272,7 +265,6 @@ export async function fetchChatCompletion({
|
||||
onChunk: onChunkReceived,
|
||||
mcpTools: mcpTools
|
||||
})
|
||||
console.log('[DEBUG] AI.completions call finished')
|
||||
}
|
||||
|
||||
interface FetchTranslateProps {
|
||||
|
||||
@ -40,7 +40,7 @@ export function createStreamProcessor(callbacks: StreamProcessorCallbacks = {})
|
||||
// The returned function processes a single chunk or a final signal
|
||||
return (chunk: Chunk) => {
|
||||
try {
|
||||
console.log(`[${new Date().toLocaleString()}] createStreamProcessor ${chunk.type}`, chunk)
|
||||
// console.log(`[${new Date().toLocaleString()}] createStreamProcessor ${chunk.type}`, chunk)
|
||||
// 1. Handle the manual final signal first
|
||||
if (chunk?.type === ChunkType.BLOCK_COMPLETE) {
|
||||
callbacks.onComplete?.(AssistantMessageStatus.SUCCESS, chunk?.response)
|
||||
|
||||
@ -41,23 +41,16 @@ import { removeManyBlocks, updateOneBlock, upsertManyBlocks, upsertOneBlock } fr
|
||||
import { newMessagesActions, selectMessagesForTopic } from '../newMessage'
|
||||
|
||||
const handleChangeLoadingOfTopic = async (topicId: string) => {
|
||||
console.log('topicId', topicId)
|
||||
await waitForTopicQueue(topicId)
|
||||
console.log('[DEBUG] Waiting for topic queue to complete')
|
||||
store.dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false }))
|
||||
}
|
||||
|
||||
// TODO: 后续可以将db操作移到Listener Middleware中
|
||||
export const saveMessageAndBlocksToDB = async (message: Message, blocks: MessageBlock[]) => {
|
||||
try {
|
||||
console.log(`[DEBUG] saveMessageAndBlocksToDB started for message ${message.id} with ${blocks.length} blocks`)
|
||||
if (blocks.length > 0) {
|
||||
console.log('[DEBUG] Saving blocks to DB')
|
||||
await db.message_blocks.bulkPut(blocks)
|
||||
console.log('[DEBUG] Blocks saved to DB')
|
||||
}
|
||||
console.log('[DEBUG] Getting topic from DB')
|
||||
const topic = await db.topics.get(message.topicId)
|
||||
console.log('[DEBUG] Got topic from DB:', topic)
|
||||
if (topic) {
|
||||
const messageIndex = topic.messages.findIndex((m) => m.id === message.id)
|
||||
const updatedMessages = [...topic.messages]
|
||||
@ -67,13 +60,10 @@ export const saveMessageAndBlocksToDB = async (message: Message, blocks: Message
|
||||
} else {
|
||||
updatedMessages.push(message)
|
||||
}
|
||||
console.log('[DEBUG] Updating topic in DB', updatedMessages)
|
||||
await db.topics.update(message.topicId, { messages: updatedMessages })
|
||||
console.log('[DEBUG] Topic updated in DB')
|
||||
} else {
|
||||
console.error(`[saveMessageAndBlocksToDB] Topic ${message.topicId} not found.`)
|
||||
}
|
||||
console.log(`[DEBUG] saveMessageAndBlocksToDB completed for message ${message.id}`)
|
||||
} catch (error) {
|
||||
console.error(`[saveMessageAndBlocksToDB] Failed to save message ${message.id}:`, error)
|
||||
}
|
||||
@ -145,7 +135,6 @@ export const throttledBlockDbUpdate = throttle(
|
||||
(block?.status === MessageBlockStatus.SUCCESS || block?.status === MessageBlockStatus.ERROR)
|
||||
)
|
||||
return
|
||||
console.log(`[DB Throttle Block Update] Updating block ${blockId} with changes:`, blockChanges)
|
||||
try {
|
||||
await db.message_blocks.update(blockId, blockChanges)
|
||||
} catch (error) {
|
||||
@ -163,11 +152,6 @@ const saveUpdatesToDB = async (
|
||||
messageUpdates: Partial<Message>, // 需要更新的消息字段
|
||||
blocksToUpdate: MessageBlock[] // 需要更新/创建的块
|
||||
) => {
|
||||
console.log(
|
||||
`[DB Save Updates] Triggered for message ${messageId}. MessageUpdates:`,
|
||||
messageUpdates,
|
||||
`BlocksToUpdate count: ${blocksToUpdate.length}`
|
||||
)
|
||||
try {
|
||||
const messageDataToSave: Partial<Message> & Pick<Message, 'id' | 'topicId'> = {
|
||||
id: messageId,
|
||||
@ -175,7 +159,6 @@ const saveUpdatesToDB = async (
|
||||
...messageUpdates
|
||||
}
|
||||
await updateExistingMessageAndBlocksInDB(messageDataToSave, blocksToUpdate)
|
||||
console.log(`[DB Save Updates] Successfully saved updates for message ${messageId}.`)
|
||||
} catch (error) {
|
||||
console.error(`[DB Save Updates] Failed for message ${messageId}:`, error)
|
||||
}
|
||||
@ -192,7 +175,6 @@ const saveUpdatedBlockToDB = async (
|
||||
console.warn('[DB Save Single Block] Received null/undefined blockId. Skipping save.')
|
||||
return
|
||||
}
|
||||
console.log(`[DB Save Single Block] Attempting to save block ${blockId} for message ${messageId}`)
|
||||
const state = getState()
|
||||
const blockToSave = state.messageBlocks.entities[blockId]
|
||||
if (blockToSave) {
|
||||
@ -212,9 +194,6 @@ const dispatchMultiModelResponses = async (
|
||||
assistant: Assistant,
|
||||
mentionedModels: Model[]
|
||||
) => {
|
||||
console.log(
|
||||
`[DEBUG] dispatchMultiModelResponses called for ${mentionedModels.length} models, triggered by message ${triggeringMessage.id}.`
|
||||
)
|
||||
const assistantMessageStubs: Message[] = []
|
||||
const tasksToQueue: { assistantConfig: Assistant; messageStub: Message }[] = []
|
||||
|
||||
@ -236,7 +215,6 @@ const dispatchMultiModelResponses = async (
|
||||
const currentEntities = getState().messages.entities
|
||||
const messagesToSaveInDB = currentTopicMessageIds.map((id) => currentEntities[id]).filter((m): m is Message => !!m)
|
||||
await db.topics.update(topicId, { messages: messagesToSaveInDB })
|
||||
console.log('[DEBUG] Topic updated in DB successfully.')
|
||||
} else {
|
||||
console.error(`[dispatchMultiModelResponses] Topic ${topicId} not found in DB during multi-model save.`)
|
||||
throw new Error(`Topic ${topicId} not found in DB.`)
|
||||
@ -260,11 +238,9 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
assistant: Assistant,
|
||||
assistantMessage: Message // Pass the prepared assistant message (new or reset)
|
||||
) => {
|
||||
console.log('[DEBUG] fetchAndProcessAssistantResponseImpl started for existing message:', assistantMessage.id)
|
||||
const assistantMsgId = assistantMessage.id
|
||||
let callbacks: StreamProcessorCallbacks = {}
|
||||
try {
|
||||
console.log('[DEBUG] Setting topic loading state')
|
||||
dispatch(newMessagesActions.setTopicLoading({ topicId, loading: true }))
|
||||
|
||||
let accumulatedContent = ''
|
||||
@ -284,7 +260,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
if (newBlockType !== MessageBlockType.THINKING) {
|
||||
accumulatedThinking = ''
|
||||
}
|
||||
console.log(`[Transition] Adding/Updating new ${newBlockType} block ${newBlock.id}.`)
|
||||
dispatch(
|
||||
newMessagesActions.updateMessage({
|
||||
topicId,
|
||||
@ -331,8 +306,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
} else {
|
||||
const contextSlice = allMessagesForTopic.slice(0, userMessageIndex + 1)
|
||||
messagesForContext = contextSlice.filter((m) => m && !m.status?.includes('ing'))
|
||||
console.log('messagesForContext', messagesForContext)
|
||||
console.log(`[DEBUG] Context for message ${assistantMsgId}: ${messagesForContext.length} messages.`)
|
||||
}
|
||||
|
||||
callbacks = {
|
||||
@ -375,7 +348,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
},
|
||||
onTextComplete: (finalText) => {
|
||||
if (lastBlockType === MessageBlockType.MAIN_TEXT && lastBlockId) {
|
||||
console.log(`[onTextComplete] Marking MAIN_TEXT block ${lastBlockId} as SUCCESS.`)
|
||||
const changes = {
|
||||
content: finalText,
|
||||
status: MessageBlockStatus.SUCCESS
|
||||
@ -393,8 +365,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
)
|
||||
handleBlockTransition(citationBlock, MessageBlockType.CITATION)
|
||||
saveUpdatedBlockToDB(citationBlock.id, assistantMsgId, topicId, getState)
|
||||
} else {
|
||||
console.log('[onTextComplete] No URLs found for OpenRouter citation.')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -416,7 +386,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
}
|
||||
dispatch(updateOneBlock({ id: lastBlockId, changes: initialChanges }))
|
||||
saveUpdatedBlockToDB(lastBlockId, assistantMsgId, topicId, getState)
|
||||
console.log(`[onThinkingChunk] Saved initial THINKING block ${lastBlockId} to DB.`)
|
||||
} else if (lastBlockType === MessageBlockType.THINKING) {
|
||||
const blockChanges: Partial<MessageBlock> = {
|
||||
content: accumulatedThinking,
|
||||
@ -436,7 +405,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
},
|
||||
onThinkingComplete: (finalText, final_thinking_millsec) => {
|
||||
if (lastBlockType === MessageBlockType.THINKING && lastBlockId) {
|
||||
console.log(`[onThinkingComplete] Marking THINKING block ${lastBlockId} as SUCCESS.`)
|
||||
const changes = {
|
||||
type: MessageBlockType.THINKING,
|
||||
content: finalText,
|
||||
@ -467,7 +435,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
}
|
||||
},
|
||||
onToolCallComplete: (toolResponse: MCPToolResponse) => {
|
||||
console.log('toolResponse', toolResponse, toolResponse.status)
|
||||
const existingBlockId = toolCallIdToBlockIdMap.get(toolResponse.id)
|
||||
if (toolResponse.status === 'done' || toolResponse.status === 'error') {
|
||||
if (!existingBlockId) {
|
||||
@ -485,7 +452,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
if (finalStatus === MessageBlockStatus.ERROR) {
|
||||
changes.error = { message: `Tool execution failed/error`, details: toolResponse.response }
|
||||
}
|
||||
console.log(`[${toolResponse.status}] Updating ToolBlock ${existingBlockId} with changes:`, changes)
|
||||
dispatch(updateOneBlock({ id: existingBlockId, changes }))
|
||||
saveUpdatedBlockToDB(existingBlockId, assistantMsgId, topicId, getState)
|
||||
} else {
|
||||
@ -495,7 +461,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
}
|
||||
},
|
||||
onExternalToolInProgress: () => {
|
||||
console.log('onExternalToolInProgress received, creating placeholder CitationBlock.')
|
||||
const citationBlock = createCitationBlock(assistantMsgId, {}, { status: MessageBlockStatus.PROCESSING })
|
||||
citationBlockId = citationBlock.id
|
||||
handleBlockTransition(citationBlock, MessageBlockType.CITATION)
|
||||
@ -516,9 +481,7 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
}
|
||||
},
|
||||
onLLMWebSearchComplete(llmWebSearchResult) {
|
||||
console.log('onLLMWebSearchComplete', llmWebSearchResult)
|
||||
if (citationBlockId) {
|
||||
console.log(`Updating existing citation block ${citationBlockId} with LLM search results.`)
|
||||
const changes: Partial<CitationMessageBlock> = {
|
||||
response: llmWebSearchResult,
|
||||
status: MessageBlockStatus.SUCCESS
|
||||
@ -526,7 +489,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
dispatch(updateOneBlock({ id: citationBlockId, changes }))
|
||||
saveUpdatedBlockToDB(citationBlockId, assistantMsgId, topicId, getState)
|
||||
} else {
|
||||
console.log('Creating new citation block for LLM search results.')
|
||||
const citationBlock = createCitationBlock(
|
||||
assistantMsgId,
|
||||
{ response: llmWebSearchResult },
|
||||
@ -594,8 +556,9 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
|
||||
const errorBlock = createErrorBlock(assistantMsgId, serializableError, { status: MessageBlockStatus.SUCCESS })
|
||||
handleBlockTransition(errorBlock, MessageBlockType.ERROR)
|
||||
|
||||
const messageErrorUpdate = { status: AssistantMessageStatus.ERROR }
|
||||
const messageErrorUpdate = {
|
||||
status: isAbortError(error) ? AssistantMessageStatus.SUCCESS : AssistantMessageStatus.ERROR
|
||||
}
|
||||
dispatch(newMessagesActions.updateMessage({ topicId, messageId: assistantMsgId, updates: messageErrorUpdate }))
|
||||
|
||||
saveUpdatesToDB(assistantMsgId, topicId, messageErrorUpdate, [])
|
||||
@ -639,7 +602,6 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
}
|
||||
|
||||
const messageUpdates: Partial<Message> = { status, metrics: response?.metrics, usage: response?.usage }
|
||||
console.log('Updating final message state in Redux:', { messageId: assistantMsgId, ...messageUpdates })
|
||||
dispatch(
|
||||
newMessagesActions.updateMessage({
|
||||
topicId,
|
||||
@ -654,16 +616,13 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[DEBUG] Creating stream processor')
|
||||
const streamProcessorCallbacks = createStreamProcessor(callbacks)
|
||||
|
||||
console.log('[DEBUG] Calling fetchChatCompletion')
|
||||
await fetchChatCompletion({
|
||||
messages: messagesForContext,
|
||||
assistant: assistant,
|
||||
onChunkReceived: streamProcessorCallbacks
|
||||
})
|
||||
console.log('[DEBUG] fetchChatCompletion completed')
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching chat completion:', error)
|
||||
if (assistantMessage) {
|
||||
@ -683,28 +642,23 @@ const fetchAndProcessAssistantResponseImpl = async (
|
||||
export const sendMessage =
|
||||
(userMessage: Message, userMessageBlocks: MessageBlock[], assistant: Assistant, topicId: Topic['id']) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
console.log('[DEBUG] sendMessage thunk started')
|
||||
try {
|
||||
if (userMessage.blocks.length === 0) {
|
||||
console.warn('sendMessage: No blocks in the provided message.')
|
||||
return
|
||||
}
|
||||
console.log('sendMessage', userMessage)
|
||||
await saveMessageAndBlocksToDB(userMessage, userMessageBlocks)
|
||||
dispatch(newMessagesActions.addMessage({ topicId, message: userMessage }))
|
||||
if (userMessageBlocks.length > 0) {
|
||||
dispatch(upsertManyBlocks(userMessageBlocks))
|
||||
}
|
||||
console.log('[DEBUG] Saved user message successfully')
|
||||
|
||||
const mentionedModels = userMessage.mentions
|
||||
const queue = getTopicQueue(topicId)
|
||||
|
||||
if (mentionedModels && mentionedModels.length > 0) {
|
||||
console.log(`[DEBUG] Multi-model send detected for ${mentionedModels.length} models.`)
|
||||
await dispatchMultiModelResponses(dispatch, getState, topicId, userMessage, assistant, mentionedModels)
|
||||
} else {
|
||||
console.log('[DEBUG] Single-model send.')
|
||||
const assistantMessage = createAssistantMessage(assistant.id, topicId, {
|
||||
askId: userMessage.id,
|
||||
model: assistant.model
|
||||
@ -712,17 +666,13 @@ export const sendMessage =
|
||||
await saveMessageAndBlocksToDB(assistantMessage, [])
|
||||
dispatch(newMessagesActions.addMessage({ topicId, message: assistantMessage }))
|
||||
|
||||
console.log('[DEBUG] Adding task to queue')
|
||||
queue.add(async () => {
|
||||
console.log('[DEBUG] Queue task started')
|
||||
await fetchAndProcessAssistantResponseImpl(dispatch, getState, topicId, assistant, assistantMessage)
|
||||
console.log('[DEBUG] fetchAndProcessAssistantResponseImpl completed')
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in sendMessage thunk:', error)
|
||||
} finally {
|
||||
console.log('sendMessage finally', userMessage)
|
||||
handleChangeLoadingOfTopic(topicId)
|
||||
}
|
||||
}
|
||||
@ -781,14 +731,12 @@ export const deleteSingleMessageThunk =
|
||||
const blockIdsToDelete = messageToDelete.blocks || []
|
||||
|
||||
try {
|
||||
console.log('deleteSingleMessageThunk', messageToDelete)
|
||||
dispatch(newMessagesActions.removeMessage({ topicId, messageId }))
|
||||
dispatch(removeManyBlocks(blockIdsToDelete))
|
||||
await db.message_blocks.bulkDelete(blockIdsToDelete)
|
||||
const topic = await db.topics.get(topicId)
|
||||
if (topic) {
|
||||
const finalMessagesToSave = selectMessagesForTopic(getState(), topicId)
|
||||
console.log('finalMessagesToSave', finalMessagesToSave)
|
||||
await db.topics.update(topicId, { messages: finalMessagesToSave })
|
||||
}
|
||||
} catch (error) {
|
||||
@ -880,9 +828,6 @@ export const clearTopicMessagesThunk =
|
||||
export const resendMessageThunk =
|
||||
(topicId: Topic['id'], userMessageToResend: Message, assistant: Assistant) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
console.log(
|
||||
`[resendMessageThunk] Regenerating responses for user message ${userMessageToResend.id} in topic ${topicId}`
|
||||
)
|
||||
try {
|
||||
const state = getState()
|
||||
// Use selector to get all messages for the topic
|
||||
@ -900,10 +845,6 @@ export const resendMessageThunk =
|
||||
return
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[resendMessageThunk] Found ${assistantMessagesToReset.length} assistant messages to reset and regenerate.`
|
||||
)
|
||||
|
||||
const resetDataList: { resetMsg: Message }[] = []
|
||||
const allBlockIdsToDelete: string[] = []
|
||||
const messagesToUpdateInRedux: { topicId: string; messageId: string; updates: Partial<Message> }[] = []
|
||||
@ -920,45 +861,34 @@ export const resendMessageThunk =
|
||||
messagesToUpdateInRedux.push({ topicId, messageId: resetMsg.id, updates: resetMsg })
|
||||
}
|
||||
|
||||
console.log('[resendMessageThunk] Updating Redux state...')
|
||||
messagesToUpdateInRedux.forEach((update) => dispatch(newMessagesActions.updateMessage(update)))
|
||||
if (allBlockIdsToDelete.length > 0) {
|
||||
dispatch(removeManyBlocks(allBlockIdsToDelete))
|
||||
console.log(`[resendMessageThunk] Removed ${allBlockIdsToDelete.length} old blocks from Redux.`)
|
||||
}
|
||||
|
||||
console.log('[resendMessageThunk] Updating Database...')
|
||||
try {
|
||||
if (allBlockIdsToDelete.length > 0) {
|
||||
await db.message_blocks.bulkDelete(allBlockIdsToDelete)
|
||||
console.log(`[resendMessageThunk] Removed ${allBlockIdsToDelete.length} old blocks from DB.`)
|
||||
}
|
||||
const finalMessagesToSave = selectMessagesForTopic(getState(), topicId)
|
||||
await db.topics.update(topicId, { messages: finalMessagesToSave })
|
||||
console.log(`[resendMessageThunk] Updated DB topic ${topicId} with latest messages from Redux state.`)
|
||||
} catch (dbError) {
|
||||
console.error('[resendMessageThunk] Error updating database:', dbError)
|
||||
}
|
||||
|
||||
console.log('[resendMessageThunk] Queueing regeneration tasks...')
|
||||
const queue = getTopicQueue(topicId)
|
||||
for (const { resetMsg } of resetDataList) {
|
||||
const assistantConfigForThisRegen = {
|
||||
...assistant,
|
||||
...(resetMsg.model ? { model: resetMsg.model } : {})
|
||||
}
|
||||
console.log(
|
||||
`[resendMessageThunk] Queueing task for message ${resetMsg.id} with model ${assistantConfigForThisRegen.model?.id}`
|
||||
)
|
||||
queue.add(async () => {
|
||||
await fetchAndProcessAssistantResponseImpl(dispatch, getState, topicId, assistantConfigForThisRegen, resetMsg)
|
||||
})
|
||||
}
|
||||
console.log(`[resendMessageThunk] Successfully queued ${resetDataList.length} regeneration tasks.`)
|
||||
} catch (error) {
|
||||
console.error(`[resendMessageThunk] Error resending user message ${userMessageToResend.id}:`, error)
|
||||
} finally {
|
||||
console.log('sendMessage finally', topicId)
|
||||
handleChangeLoadingOfTopic(topicId)
|
||||
}
|
||||
}
|
||||
@ -977,22 +907,16 @@ export const resendUserMessageWithEditThunk =
|
||||
assistant: Assistant
|
||||
) =>
|
||||
async (dispatch: AppDispatch) => {
|
||||
console.log(
|
||||
`[resendUserMessageWithEditThunk] Updating block ${mainTextBlockId} for message ${originalMessage.id} and triggering regeneration.`
|
||||
)
|
||||
const blockChanges = {
|
||||
content: editedContent,
|
||||
updatedAt: new Date().toISOString()
|
||||
}
|
||||
console.log('[resendUserMessageWithEditThunk] Updating edited block...')
|
||||
// Update block in Redux and DB
|
||||
dispatch(updateOneBlock({ id: mainTextBlockId, changes: blockChanges }))
|
||||
await db.message_blocks.update(mainTextBlockId, blockChanges)
|
||||
console.log('[resendUserMessageWithEditThunk] Edited block updated successfully.')
|
||||
|
||||
// Trigger the regeneration logic for associated assistant messages
|
||||
dispatch(resendMessageThunk(topicId, originalMessage, assistant))
|
||||
console.log('[resendUserMessageWithEditThunk] Regeneration process initiated by resendMessageThunk dispatch.')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1001,9 +925,6 @@ export const resendUserMessageWithEditThunk =
|
||||
export const regenerateAssistantResponseThunk =
|
||||
(topicId: Topic['id'], assistantMessageToRegenerate: Message, assistant: Assistant) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
console.log(
|
||||
`[regenerateAssistantResponseThunk] Regenerating response for assistant message ${assistantMessageToRegenerate.id} in topic ${topicId}`
|
||||
)
|
||||
try {
|
||||
const state = getState()
|
||||
|
||||
@ -1036,7 +957,6 @@ export const regenerateAssistantResponseThunk =
|
||||
const resetAssistantMsg = resetAssistantMessage(messageToResetEntity, {
|
||||
status: AssistantMessageStatus.PENDING
|
||||
})
|
||||
console.log('resetAssistantMsg', resetAssistantMsg)
|
||||
dispatch(
|
||||
newMessagesActions.updateMessage({
|
||||
topicId,
|
||||
@ -1047,7 +967,6 @@ export const regenerateAssistantResponseThunk =
|
||||
|
||||
// 6. Remove old blocks from Redux
|
||||
if (blockIdsToDelete.length > 0) {
|
||||
console.log(`[regenerateAssistantResponseThunk] Removing ${blockIdsToDelete.length} old blocks from Redux.`)
|
||||
dispatch(removeManyBlocks(blockIdsToDelete))
|
||||
}
|
||||
|
||||
@ -1063,7 +982,6 @@ export const regenerateAssistantResponseThunk =
|
||||
await db.message_blocks.bulkDelete(blockIdsToDelete)
|
||||
}
|
||||
})
|
||||
console.log('[regenerateAssistantResponseThunk] Updated DB with reset message and removed old blocks.')
|
||||
|
||||
// 8. Add fetch/process call to the queue
|
||||
const queue = getTopicQueue(topicId)
|
||||
@ -1071,9 +989,6 @@ export const regenerateAssistantResponseThunk =
|
||||
...assistant,
|
||||
...(resetAssistantMsg.model ? { model: resetAssistantMsg.model } : {})
|
||||
}
|
||||
console.log(
|
||||
`[regenerateAssistantResponseThunk] Queueing task for message ${resetAssistantMsg.id} with model ${assistantConfigForRegen.model?.id}`
|
||||
)
|
||||
queue.add(async () => {
|
||||
await fetchAndProcessAssistantResponseImpl(
|
||||
dispatch,
|
||||
@ -1090,7 +1005,6 @@ export const regenerateAssistantResponseThunk =
|
||||
)
|
||||
dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false }))
|
||||
} finally {
|
||||
console.log('sendMessage finally', topicId)
|
||||
handleChangeLoadingOfTopic(topicId)
|
||||
}
|
||||
}
|
||||
@ -1106,7 +1020,6 @@ export const initiateTranslationThunk =
|
||||
) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState): Promise<string | undefined> => {
|
||||
// Return the new block ID
|
||||
console.log(`[initiateTranslationThunk] Initiating translation block for message ${messageId}`)
|
||||
try {
|
||||
const state = getState()
|
||||
const originalMessage = state.messages.entities[messageId]
|
||||
@ -1147,9 +1060,6 @@ export const initiateTranslationThunk =
|
||||
await db.message_blocks.put(newBlock) // Save the initial block
|
||||
await db.topics.update(topicId, { messages: finalMessagesToSave }) // Save updated message list
|
||||
})
|
||||
console.log(
|
||||
`[initiateTranslationThunk] Successfully initiated translation block ${newBlock.id} for message ${messageId}.`
|
||||
)
|
||||
return newBlock.id // Return the ID
|
||||
} catch (error) {
|
||||
console.error(`[initiateTranslationThunk] Failed for message ${messageId}:`, error)
|
||||
@ -1170,9 +1080,6 @@ export const appendAssistantResponseThunk =
|
||||
assistant: Assistant // Base assistant configuration
|
||||
) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
console.log(
|
||||
`[appendAssistantResponseThunk] Appending response for topic ${topicId} based on message ${existingAssistantMessageId} with new model ${newModel.id}`
|
||||
)
|
||||
try {
|
||||
const state = getState()
|
||||
|
||||
@ -1207,9 +1114,6 @@ export const appendAssistantResponseThunk =
|
||||
}
|
||||
|
||||
// 2. Create the new assistant message stub
|
||||
console.log(
|
||||
`[appendAssistantResponseThunk] Creating new assistant message stub for askId ${askId} with model ${newModel.id}`
|
||||
)
|
||||
const newAssistantStub = createAssistantMessage(assistant.id, topicId, {
|
||||
askId: askId, // Crucial: Use the original askId
|
||||
model: newModel,
|
||||
@ -1217,11 +1121,9 @@ export const appendAssistantResponseThunk =
|
||||
})
|
||||
|
||||
// 3. Update Redux Store
|
||||
console.log(`[appendAssistantResponseThunk] Adding new stub ${newAssistantStub.id} to Redux.`)
|
||||
dispatch(newMessagesActions.addMessage({ topicId, message: newAssistantStub }))
|
||||
|
||||
// 4. Update Database (Save the stub to the topic's message list)
|
||||
console.log(`[appendAssistantResponseThunk] Saving new stub ${newAssistantStub.id} to DB.`)
|
||||
await saveMessageAndBlocksToDB(newAssistantStub, [])
|
||||
|
||||
// 5. Prepare and queue the processing task
|
||||
@ -1230,7 +1132,6 @@ export const appendAssistantResponseThunk =
|
||||
model: newModel
|
||||
}
|
||||
const queue = getTopicQueue(topicId)
|
||||
console.log(`[appendAssistantResponseThunk] Adding task to queue for new stub ${newAssistantStub.id}`)
|
||||
queue.add(async () => {
|
||||
await fetchAndProcessAssistantResponseImpl(
|
||||
dispatch,
|
||||
@ -1240,16 +1141,11 @@ export const appendAssistantResponseThunk =
|
||||
newAssistantStub // Pass the newly created stub
|
||||
)
|
||||
})
|
||||
|
||||
console.log(
|
||||
`[appendAssistantResponseThunk] Successfully queued processing for new assistant message ${newAssistantStub.id}`
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(`[appendAssistantResponseThunk] Error appending assistant response:`, error)
|
||||
// Optionally dispatch an error action or notification
|
||||
// Resetting loading state should be handled by the underlying fetchAndProcessAssistantResponseImpl
|
||||
} finally {
|
||||
console.log('sendMessage finally', topicId)
|
||||
handleChangeLoadingOfTopic(topicId)
|
||||
}
|
||||
}
|
||||
@ -1270,9 +1166,6 @@ export const cloneMessagesToNewTopicThunk =
|
||||
newTopic: Topic // Receive newTopic object
|
||||
) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState): Promise<boolean> => {
|
||||
console.log(
|
||||
`[cloneMessagesToNewTopicThunk] Cloning messages from topic ${sourceTopicId} to new topic ${newTopic.id} up to index ${branchPointIndex}`
|
||||
)
|
||||
if (!newTopic || !newTopic.id) {
|
||||
console.error(`[cloneMessagesToNewTopicThunk] Invalid newTopic provided.`)
|
||||
return false
|
||||
@ -1310,7 +1203,6 @@ export const cloneMessagesToNewTopicThunk =
|
||||
const mappedNewAskId = originalToNewMsgIdMap.get(oldMessage.askId)
|
||||
if (mappedNewAskId) {
|
||||
newAskId = mappedNewAskId // Use the new ID
|
||||
console.log(`[cloneMessages] Mapped askId ${oldMessage.askId} to ${newAskId} for new message ${newMsgId}`)
|
||||
} else {
|
||||
// This happens if the user message corresponding to askId was *before* the branch point index
|
||||
// and thus wasn't included in messagesToClone or the map.
|
||||
@ -1365,9 +1257,6 @@ export const cloneMessagesToNewTopicThunk =
|
||||
}
|
||||
|
||||
// 4. Update Database (Atomic Transaction)
|
||||
console.log(
|
||||
`[cloneMessagesToNewTopicThunk] Saving ${clonedMessages.length} cloned messages and ${clonedBlocks.length} blocks to DB for topic ${newTopic.id}`
|
||||
)
|
||||
await db.transaction('rw', db.topics, db.message_blocks, db.files, async () => {
|
||||
// Update the NEW topic with the cloned messages
|
||||
// Assumes topic entry was added by caller, so we UPDATE.
|
||||
@ -1391,16 +1280,13 @@ export const cloneMessagesToNewTopicThunk =
|
||||
})
|
||||
}
|
||||
})
|
||||
console.log(`[cloneMessagesToNewTopicThunk] DB update complete for topic ${newTopic.id}.`)
|
||||
|
||||
// --- Update Redux State ---
|
||||
console.log(`[cloneMessages] Updating Redux message/block state for new topic ${newTopic.id}.`)
|
||||
dispatch(newMessagesActions.messagesReceived({ topicId: newTopic.id, messages: clonedMessages }))
|
||||
if (clonedBlocks.length > 0) {
|
||||
dispatch(upsertManyBlocks(clonedBlocks))
|
||||
}
|
||||
|
||||
console.log(`[cloneMessagesToNewTopicThunk] Message cloning successful for topic ${newTopic.id}`)
|
||||
return true // Indicate success
|
||||
} catch (error) {
|
||||
console.error(`[cloneMessagesToNewTopicThunk] Failed to clone messages:`, error)
|
||||
@ -1422,12 +1308,6 @@ export const updateMessageAndBlocksThunk =
|
||||
) =>
|
||||
async (dispatch: AppDispatch): Promise<boolean> => {
|
||||
const messageId = messageUpdates?.id
|
||||
console.log(
|
||||
`[updateMessageAndBlocksThunk] Updating message ${messageId} context in topic ${topicId}. MessageUpdates:`,
|
||||
messageUpdates,
|
||||
`BlockUpdates:`,
|
||||
blockUpdatesList
|
||||
)
|
||||
|
||||
if (messageUpdates && !messageId) {
|
||||
console.error('[updateMessageAndBlocksThunk] Message ID is required.')
|
||||
@ -1443,11 +1323,6 @@ export const updateMessageAndBlocksThunk =
|
||||
// Only dispatch message update if there are actual changes beyond the ID
|
||||
if (Object.keys(actualMessageChanges).length > 0) {
|
||||
dispatch(newMessagesActions.updateMessage({ topicId, messageId, updates: actualMessageChanges }))
|
||||
console.log(`[updateMessageAndBlocksThunk] Dispatched message property updates for ${messageId} in Redux.`)
|
||||
} else {
|
||||
console.log(
|
||||
`[updateMessageAndBlocksThunk] No message property updates for ${messageId} in Redux, only processing blocks.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1460,7 +1335,6 @@ export const updateMessageAndBlocksThunk =
|
||||
console.warn('[updateMessageAndBlocksThunk] Skipping block update due to missing block ID:', blockUpdate)
|
||||
}
|
||||
})
|
||||
console.log(`[updateMessageAndBlocksThunk] Dispatched ${blockUpdatesList.length} block update(s) in Redux.`)
|
||||
}
|
||||
|
||||
// 2. 更新数据库 (在事务中)
|
||||
@ -1473,9 +1347,6 @@ export const updateMessageAndBlocksThunk =
|
||||
if (messageIndex !== -1) {
|
||||
Object.assign(topic.messages[messageIndex], messageUpdates)
|
||||
await db.topics.update(topicId, { messages: topic.messages })
|
||||
console.log(
|
||||
`[updateMessageAndBlocksThunk] Updated message properties for ${messageId} in DB topic ${topicId}.`
|
||||
)
|
||||
} else {
|
||||
console.error(
|
||||
`[updateMessageAndBlocksThunk] Message ${messageId} not found in DB topic ${topicId} for property update.`
|
||||
@ -1504,12 +1375,10 @@ export const updateMessageAndBlocksThunk =
|
||||
|
||||
if (validBlockUpdatesForDb.length > 0) {
|
||||
await db.message_blocks.bulkUpdate(validBlockUpdatesForDb)
|
||||
console.log(`[updateMessageAndBlocksThunk] Updated ${validBlockUpdatesForDb.length} block(s) in DB.`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`[updateMessageAndBlocksThunk] Successfully processed updates for message ${messageId} context.`)
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error(`[updateMessageAndBlocksThunk] Failed to process updates for message ${messageId}:`, error)
|
||||
|
||||
@ -9,15 +9,7 @@ const requestQueues: { [topicId: string]: PQueue } = {}
|
||||
* @returns A PQueue instance for the topic
|
||||
*/
|
||||
export const getTopicQueue = (topicId: string, options = {}): PQueue => {
|
||||
console.log(`[DEBUG] getTopicQueue called for topic ${topicId}`)
|
||||
if (!requestQueues[topicId]) {
|
||||
console.log(`[DEBUG] Creating new queue for topic ${topicId}`)
|
||||
requestQueues[topicId] = new PQueue(options)
|
||||
} else {
|
||||
console.log(
|
||||
`[DEBUG] Using existing queue for topic ${topicId}, size: ${requestQueues[topicId].size}, pending: ${requestQueues[topicId].pending}`
|
||||
)
|
||||
}
|
||||
if (!requestQueues[topicId]) requestQueues[topicId] = new PQueue(options)
|
||||
return requestQueues[topicId]
|
||||
}
|
||||
|
||||
@ -68,7 +60,6 @@ export const getTopicPendingRequestCount = (topicId: string): number => {
|
||||
* @param topicId The ID of the topic
|
||||
*/
|
||||
export const waitForTopicQueue = async (topicId: string): Promise<void> => {
|
||||
console.log('waitForTopicQueue', requestQueues[topicId])
|
||||
if (requestQueues[topicId]) {
|
||||
await requestQueues[topicId].onIdle()
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user