mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-09 14:59:27 +08:00
refactor: merge messageThunk.v2.ts into messageThunk.ts
Remove the confusing V2 naming from message thunk functions to avoid conflicts with the upcoming real V2 data refactoring. Changes: - Inline V2 function implementations directly into messageThunk.ts - Replace V2 function calls with direct dbService calls - Remove messageThunk.v2.ts file - Remove misleading "V2 DATA&UI REFACTORING" header comments The V2 suffix was originally added for agent session support, not for a data layer refactoring. This cleanup clears the naming space for the actual V2 refactoring work.
This commit is contained in:
parent
078cf39313
commit
ca2b0ac28d
@ -81,9 +81,7 @@ const AgentSessionMessages: React.FC<Props> = ({ agentId, sessionId }) => {
|
|||||||
|
|
||||||
// Listen for send message events to auto-scroll to bottom
|
// Listen for send message events to auto-scroll to bottom
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribes = [
|
const unsubscribes = [EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, scrollToBottom)]
|
||||||
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, scrollToBottom)
|
|
||||||
]
|
|
||||||
return () => unsubscribes.forEach((unsub) => unsub())
|
return () => unsubscribes.forEach((unsub) => unsub())
|
||||||
}, [scrollToBottom])
|
}, [scrollToBottom])
|
||||||
|
|
||||||
|
|||||||
@ -162,7 +162,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic, o
|
|||||||
|
|
||||||
const { message: clearMessage } = getUserMessage({ assistant, topic, type: 'clear' })
|
const { message: clearMessage } = getUserMessage({ assistant, topic, type: 'clear' })
|
||||||
dispatch(newMessagesActions.addMessage({ topicId: topic.id, message: clearMessage }))
|
dispatch(newMessagesActions.addMessage({ topicId: topic.id, message: clearMessage }))
|
||||||
await saveMessageAndBlocksToDB(clearMessage, [])
|
await saveMessageAndBlocksToDB(topic.id, clearMessage, [])
|
||||||
|
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import { AiSdkToChunkAdapter } from '@renderer/aiCore/chunk/AiSdkToChunkAdapter'
|
|||||||
import { AgentApiClient } from '@renderer/api/agent'
|
import { AgentApiClient } from '@renderer/api/agent'
|
||||||
import db from '@renderer/databases'
|
import db from '@renderer/databases'
|
||||||
import { fetchMessagesSummary, transformMessagesAndFetch } from '@renderer/services/ApiService'
|
import { fetchMessagesSummary, transformMessagesAndFetch } from '@renderer/services/ApiService'
|
||||||
|
import { dbService } from '@renderer/services/db'
|
||||||
import { DbService } from '@renderer/services/db/DbService'
|
import { DbService } from '@renderer/services/db/DbService'
|
||||||
import FileManager from '@renderer/services/FileManager'
|
import FileManager from '@renderer/services/FileManager'
|
||||||
import { BlockManager } from '@renderer/services/messageStreaming/BlockManager'
|
import { BlockManager } from '@renderer/services/messageStreaming/BlockManager'
|
||||||
@ -57,18 +58,18 @@ import { mutate } from 'swr'
|
|||||||
import type { AppDispatch, RootState } from '../index'
|
import type { AppDispatch, RootState } from '../index'
|
||||||
import { removeManyBlocks, updateOneBlock, upsertManyBlocks, upsertOneBlock } from '../messageBlock'
|
import { removeManyBlocks, updateOneBlock, upsertManyBlocks, upsertOneBlock } from '../messageBlock'
|
||||||
import { newMessagesActions, selectMessagesForTopic } from '../newMessage'
|
import { newMessagesActions, selectMessagesForTopic } from '../newMessage'
|
||||||
import {
|
// import {
|
||||||
bulkAddBlocksV2,
|
// bulkAddBlocksV2,
|
||||||
clearMessagesFromDBV2,
|
// clearMessagesFromDBV2,
|
||||||
deleteMessageFromDBV2,
|
// deleteMessageFromDBV2,
|
||||||
deleteMessagesFromDBV2,
|
// deleteMessagesFromDBV2,
|
||||||
loadTopicMessagesThunkV2,
|
// loadTopicMessagesThunkV2,
|
||||||
saveMessageAndBlocksToDBV2,
|
// saveMessageAndBlocksToDBV2,
|
||||||
updateBlocksV2,
|
// updateBlocksV2,
|
||||||
updateFileCountV2,
|
// updateFileCountV2,
|
||||||
updateMessageV2,
|
// updateMessageV2,
|
||||||
updateSingleBlockV2
|
// updateSingleBlockV2
|
||||||
} from './messageThunk.v2'
|
// } from './messageThunk.v2'
|
||||||
|
|
||||||
const logger = loggerService.withContext('MessageThunk')
|
const logger = loggerService.withContext('MessageThunk')
|
||||||
|
|
||||||
@ -363,9 +364,9 @@ const createAgentMessageStream = async (
|
|||||||
return createSSEReadableStream(response.body, signal)
|
return createSSEReadableStream(response.body, signal)
|
||||||
}
|
}
|
||||||
// TODO: 后续可以将db操作移到Listener Middleware中
|
// TODO: 后续可以将db操作移到Listener Middleware中
|
||||||
export const saveMessageAndBlocksToDB = async (message: Message, blocks: MessageBlock[], messageIndex: number = -1) => {
|
// export const saveMessageAndBlocksToDB = async (message: Message, blocks: MessageBlock[], messageIndex: number = -1) => {
|
||||||
return saveMessageAndBlocksToDBV2(message.topicId, message, blocks, messageIndex)
|
// return saveMessageAndBlocksToDBV2(message.topicId, message, blocks, messageIndex)
|
||||||
}
|
// }
|
||||||
|
|
||||||
const updateExistingMessageAndBlocksInDB = async (
|
const updateExistingMessageAndBlocksInDB = async (
|
||||||
updatedMessage: Partial<Message> & Pick<Message, 'id' | 'topicId'>,
|
updatedMessage: Partial<Message> & Pick<Message, 'id' | 'topicId'>,
|
||||||
@ -374,7 +375,7 @@ const updateExistingMessageAndBlocksInDB = async (
|
|||||||
try {
|
try {
|
||||||
// Always update blocks if provided
|
// Always update blocks if provided
|
||||||
if (updatedBlocks.length > 0) {
|
if (updatedBlocks.length > 0) {
|
||||||
await updateBlocksV2(updatedBlocks)
|
await updateBlocks(updatedBlocks)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there are message properties to update beyond id and topicId
|
// Check if there are message properties to update beyond id and topicId
|
||||||
@ -386,7 +387,7 @@ const updateExistingMessageAndBlocksInDB = async (
|
|||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
await updateMessageV2(updatedMessage.topicId, updatedMessage.id, messageUpdatesPayload)
|
await updateMessage(updatedMessage.topicId, updatedMessage.id, messageUpdatesPayload)
|
||||||
|
|
||||||
store.dispatch(updateTopicUpdatedAt({ topicId: updatedMessage.topicId }))
|
store.dispatch(updateTopicUpdatedAt({ topicId: updatedMessage.topicId }))
|
||||||
}
|
}
|
||||||
@ -432,7 +433,7 @@ const getBlockThrottler = (id: string) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
blockUpdateRafs.set(id, rafId)
|
blockUpdateRafs.set(id, rafId)
|
||||||
await updateSingleBlockV2(id, blockUpdate)
|
await updateSingleBlock(id, blockUpdate)
|
||||||
}, 150)
|
}, 150)
|
||||||
|
|
||||||
blockUpdateThrottlers.set(id, throttler)
|
blockUpdateThrottlers.set(id, throttler)
|
||||||
@ -893,7 +894,7 @@ export const sendMessage =
|
|||||||
userMessage.agentSessionId = activeAgentSession.agentSessionId
|
userMessage.agentSessionId = activeAgentSession.agentSessionId
|
||||||
}
|
}
|
||||||
|
|
||||||
await saveMessageAndBlocksToDB(userMessage, userMessageBlocks)
|
await saveMessageAndBlocksToDB(topicId, userMessage, userMessageBlocks)
|
||||||
dispatch(newMessagesActions.addMessage({ topicId, message: userMessage }))
|
dispatch(newMessagesActions.addMessage({ topicId, message: userMessage }))
|
||||||
if (userMessageBlocks.length > 0) {
|
if (userMessageBlocks.length > 0) {
|
||||||
dispatch(upsertManyBlocks(userMessageBlocks))
|
dispatch(upsertManyBlocks(userMessageBlocks))
|
||||||
@ -911,7 +912,7 @@ export const sendMessage =
|
|||||||
if (activeAgentSession.agentSessionId && !assistantMessage.agentSessionId) {
|
if (activeAgentSession.agentSessionId && !assistantMessage.agentSessionId) {
|
||||||
assistantMessage.agentSessionId = activeAgentSession.agentSessionId
|
assistantMessage.agentSessionId = activeAgentSession.agentSessionId
|
||||||
}
|
}
|
||||||
await saveMessageAndBlocksToDB(assistantMessage, [])
|
await saveMessageAndBlocksToDB(topicId, assistantMessage, [])
|
||||||
dispatch(newMessagesActions.addMessage({ topicId, message: assistantMessage }))
|
dispatch(newMessagesActions.addMessage({ topicId, message: assistantMessage }))
|
||||||
|
|
||||||
queue.add(async () => {
|
queue.add(async () => {
|
||||||
@ -934,7 +935,7 @@ export const sendMessage =
|
|||||||
model: assistant.model,
|
model: assistant.model,
|
||||||
traceId: userMessage.traceId
|
traceId: userMessage.traceId
|
||||||
})
|
})
|
||||||
await saveMessageAndBlocksToDB(assistantMessage, [])
|
await saveMessageAndBlocksToDB(topicId, assistantMessage, [])
|
||||||
dispatch(newMessagesActions.addMessage({ topicId, message: assistantMessage }))
|
dispatch(newMessagesActions.addMessage({ topicId, message: assistantMessage }))
|
||||||
|
|
||||||
queue.add(async () => {
|
queue.add(async () => {
|
||||||
@ -1000,11 +1001,11 @@ export const loadAgentSessionMessagesThunk =
|
|||||||
* Loads messages and their blocks for a specific topic from the database
|
* Loads messages and their blocks for a specific topic from the database
|
||||||
* and updates the Redux store.
|
* and updates the Redux store.
|
||||||
*/
|
*/
|
||||||
export const loadTopicMessagesThunk =
|
// export const loadTopicMessagesThunk =
|
||||||
(topicId: string, forceReload: boolean = false) =>
|
// (topicId: string, forceReload: boolean = false) =>
|
||||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
// async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
return loadTopicMessagesThunkV2(topicId, forceReload)(dispatch, getState)
|
// return loadTopicMessagesThunkV2(topicId, forceReload)(dispatch, getState)
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thunk to delete a single message and its associated blocks.
|
* Thunk to delete a single message and its associated blocks.
|
||||||
@ -1023,7 +1024,7 @@ export const deleteSingleMessageThunk =
|
|||||||
try {
|
try {
|
||||||
dispatch(newMessagesActions.removeMessage({ topicId, messageId }))
|
dispatch(newMessagesActions.removeMessage({ topicId, messageId }))
|
||||||
cleanupMultipleBlocks(dispatch, blockIdsToDelete)
|
cleanupMultipleBlocks(dispatch, blockIdsToDelete)
|
||||||
await deleteMessageFromDBV2(topicId, messageId)
|
await deleteMessageFromDB(topicId, messageId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[deleteSingleMessage] Failed to delete message ${messageId}:`, error as Error)
|
logger.error(`[deleteSingleMessage] Failed to delete message ${messageId}:`, error as Error)
|
||||||
}
|
}
|
||||||
@ -1062,7 +1063,7 @@ export const deleteMessageGroupThunk =
|
|||||||
try {
|
try {
|
||||||
dispatch(newMessagesActions.removeMessagesByAskId({ topicId, askId }))
|
dispatch(newMessagesActions.removeMessagesByAskId({ topicId, askId }))
|
||||||
cleanupMultipleBlocks(dispatch, blockIdsToDelete)
|
cleanupMultipleBlocks(dispatch, blockIdsToDelete)
|
||||||
await deleteMessagesFromDBV2(topicId, messageIdsToDelete)
|
await deleteMessagesFromDB(topicId, messageIdsToDelete)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[deleteMessageGroup] Failed to delete messages with askId ${askId}:`, error as Error)
|
logger.error(`[deleteMessageGroup] Failed to delete messages with askId ${askId}:`, error as Error)
|
||||||
}
|
}
|
||||||
@ -1087,7 +1088,7 @@ export const clearTopicMessagesThunk =
|
|||||||
|
|
||||||
dispatch(newMessagesActions.clearTopicMessages(topicId))
|
dispatch(newMessagesActions.clearTopicMessages(topicId))
|
||||||
cleanupMultipleBlocks(dispatch, blockIdsToDelete)
|
cleanupMultipleBlocks(dispatch, blockIdsToDelete)
|
||||||
await clearMessagesFromDBV2(topicId)
|
await clearMessagesFromDB(topicId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[clearTopicMessagesThunk] Failed to clear messages for topic ${topicId}:`, error as Error)
|
logger.error(`[clearTopicMessagesThunk] Failed to clear messages for topic ${topicId}:`, error as Error)
|
||||||
}
|
}
|
||||||
@ -1408,7 +1409,7 @@ export const updateTranslationBlockThunk =
|
|||||||
// 更新Redux状态
|
// 更新Redux状态
|
||||||
dispatch(updateOneBlock({ id: blockId, changes }))
|
dispatch(updateOneBlock({ id: blockId, changes }))
|
||||||
|
|
||||||
await updateSingleBlockV2(blockId, changes)
|
await updateSingleBlock(blockId, changes)
|
||||||
// Logger.log(`[updateTranslationBlockThunk] Successfully updated translation block ${blockId}.`)
|
// Logger.log(`[updateTranslationBlockThunk] Successfully updated translation block ${blockId}.`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[updateTranslationBlockThunk] Failed to update translation block ${blockId}:`, error as Error)
|
logger.error(`[updateTranslationBlockThunk] Failed to update translation block ${blockId}:`, error as Error)
|
||||||
@ -1479,7 +1480,7 @@ export const appendAssistantResponseThunk =
|
|||||||
const insertAtIndex = existingMessageIndex !== -1 ? existingMessageIndex + 1 : currentTopicMessageIds.length
|
const insertAtIndex = existingMessageIndex !== -1 ? existingMessageIndex + 1 : currentTopicMessageIds.length
|
||||||
|
|
||||||
// 4. Update Database (Save the stub to the topic's message list)
|
// 4. Update Database (Save the stub to the topic's message list)
|
||||||
await saveMessageAndBlocksToDB(newAssistantMessageStub, [], insertAtIndex)
|
await saveMessageAndBlocksToDB(topicId, newAssistantMessageStub, [], insertAtIndex)
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
newMessagesActions.insertMessageAtIndex({ topicId, message: newAssistantMessageStub, index: insertAtIndex })
|
newMessagesActions.insertMessageAtIndex({ topicId, message: newAssistantMessageStub, index: insertAtIndex })
|
||||||
@ -1631,12 +1632,12 @@ export const cloneMessagesToNewTopicThunk =
|
|||||||
|
|
||||||
// Add the NEW blocks
|
// Add the NEW blocks
|
||||||
if (clonedBlocks.length > 0) {
|
if (clonedBlocks.length > 0) {
|
||||||
await bulkAddBlocksV2(clonedBlocks)
|
await bulkAddBlocks(clonedBlocks)
|
||||||
}
|
}
|
||||||
// Update file counts
|
// Update file counts
|
||||||
const uniqueFiles = [...new Map(filesToUpdateCount.map((f) => [f.id, f])).values()]
|
const uniqueFiles = [...new Map(filesToUpdateCount.map((f) => [f.id, f])).values()]
|
||||||
for (const file of uniqueFiles) {
|
for (const file of uniqueFiles) {
|
||||||
await updateFileCountV2(file.id, 1, false)
|
await updateFileCount(file.id, 1, false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1690,11 +1691,11 @@ export const updateMessageAndBlocksThunk =
|
|||||||
}
|
}
|
||||||
// Update message properties if provided
|
// Update message properties if provided
|
||||||
if (messageUpdates && Object.keys(messageUpdates).length > 0 && messageId) {
|
if (messageUpdates && Object.keys(messageUpdates).length > 0 && messageId) {
|
||||||
await updateMessageV2(topicId, messageId, messageUpdates)
|
await updateMessage(topicId, messageId, messageUpdates)
|
||||||
}
|
}
|
||||||
// Update blocks if provided
|
// Update blocks if provided
|
||||||
if (blockUpdatesList.length > 0) {
|
if (blockUpdatesList.length > 0) {
|
||||||
await updateBlocksV2(blockUpdatesList)
|
await updateBlocks(blockUpdatesList)
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(updateTopicUpdatedAt({ topicId }))
|
dispatch(updateTopicUpdatedAt({ topicId }))
|
||||||
@ -1748,3 +1749,197 @@ export const removeBlocksThunk =
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//以下内容从原 messageThunk.v2.ts 迁移过来,原文件已经删除
|
||||||
|
//原因:v2.ts并不是v2数据重构的一部分,而相关命名对v2重构造成重大误解,故两文件合并,以消除误解
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load messages for a topic using unified DbService
|
||||||
|
*/
|
||||||
|
export const loadTopicMessagesThunk =
|
||||||
|
(topicId: string, forceReload: boolean = false) =>
|
||||||
|
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
|
const state = getState()
|
||||||
|
|
||||||
|
dispatch(newMessagesActions.setCurrentTopicId(topicId))
|
||||||
|
|
||||||
|
// Skip if already cached and not forcing reload
|
||||||
|
if (!forceReload && state.messages.messageIdsByTopic[topicId]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(newMessagesActions.setTopicLoading({ topicId, loading: true }))
|
||||||
|
|
||||||
|
// Unified call - no need to check isAgentSessionTopicId
|
||||||
|
const { messages, blocks } = await dbService.fetchMessages(topicId)
|
||||||
|
|
||||||
|
logger.silly('Loaded messages via DbService', {
|
||||||
|
topicId,
|
||||||
|
messageCount: messages.length,
|
||||||
|
blockCount: blocks.length
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update Redux state with fetched data
|
||||||
|
if (blocks.length > 0) {
|
||||||
|
dispatch(upsertManyBlocks(blocks))
|
||||||
|
}
|
||||||
|
dispatch(newMessagesActions.messagesReceived({ topicId, messages }))
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`Failed to load messages for topic ${topicId}:`, error as Error)
|
||||||
|
// Could dispatch an error action here if needed
|
||||||
|
} finally {
|
||||||
|
dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get raw topic data using unified DbService
|
||||||
|
* Returns topic with messages array
|
||||||
|
*/
|
||||||
|
export const getRawTopic = async (topicId: string): Promise<{ id: string; messages: Message[] } | undefined> => {
|
||||||
|
try {
|
||||||
|
const rawTopic = await dbService.getRawTopic(topicId)
|
||||||
|
logger.silly('Retrieved raw topic via DbService', { topicId, found: !!rawTopic })
|
||||||
|
return rawTopic
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to get raw topic:', { topicId, error })
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update file reference count
|
||||||
|
* Only applies to Dexie data source, no-op for agent sessions
|
||||||
|
*/
|
||||||
|
export const updateFileCount = async (fileId: string, delta: number, deleteIfZero: boolean = false): Promise<void> => {
|
||||||
|
try {
|
||||||
|
// Pass all parameters to dbService, including deleteIfZero
|
||||||
|
await dbService.updateFileCount(fileId, delta, deleteIfZero)
|
||||||
|
logger.silly('Updated file count', { fileId, delta, deleteIfZero })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to update file count:', { fileId, delta, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a single message from database
|
||||||
|
*/
|
||||||
|
export const deleteMessageFromDB = async (topicId: string, messageId: string): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.deleteMessage(topicId, messageId)
|
||||||
|
logger.silly('Deleted message via DbService', { topicId, messageId })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to delete message:', { topicId, messageId, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete multiple messages from database
|
||||||
|
*/
|
||||||
|
export const deleteMessagesFromDB = async (topicId: string, messageIds: string[]): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.deleteMessages(topicId, messageIds)
|
||||||
|
logger.silly('Deleted messages via DbService', { topicId, count: messageIds.length })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to delete messages:', { topicId, messageIds, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all messages from a topic
|
||||||
|
*/
|
||||||
|
export const clearMessagesFromDB = async (topicId: string): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.clearMessages(topicId)
|
||||||
|
logger.silly('Cleared all messages via DbService', { topicId })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to clear messages:', { topicId, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a message and its blocks to database
|
||||||
|
* Uses unified interface, no need for isAgentSessionTopicId check
|
||||||
|
*/
|
||||||
|
export const saveMessageAndBlocksToDB = async (
|
||||||
|
topicId: string,
|
||||||
|
message: Message,
|
||||||
|
blocks: MessageBlock[],
|
||||||
|
messageIndex: number = -1
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const blockIds = blocks.map((block) => block.id)
|
||||||
|
const shouldSyncBlocks =
|
||||||
|
blockIds.length > 0 && (!message.blocks || blockIds.some((id, index) => message.blocks?.[index] !== id))
|
||||||
|
|
||||||
|
const messageWithBlocks = shouldSyncBlocks ? { ...message, blocks: blockIds } : message
|
||||||
|
// Direct call without conditional logic, now with messageIndex
|
||||||
|
await dbService.appendMessage(topicId, messageWithBlocks, blocks, messageIndex)
|
||||||
|
logger.silly('Saved message and blocks via DbService', {
|
||||||
|
topicId,
|
||||||
|
messageId: message.id,
|
||||||
|
blockCount: blocks.length,
|
||||||
|
messageIndex
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to save message and blocks:', { topicId, messageId: message.id, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a message in the database
|
||||||
|
*/
|
||||||
|
export const updateMessage = async (topicId: string, messageId: string, updates: Partial<Message>): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.updateMessage(topicId, messageId, updates)
|
||||||
|
logger.silly('Updated message via DbService', { topicId, messageId })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to update message:', { topicId, messageId, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a single message block
|
||||||
|
*/
|
||||||
|
export const updateSingleBlock = async (blockId: string, updates: Partial<MessageBlock>): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.updateSingleBlock(blockId, updates)
|
||||||
|
logger.silly('Updated single block via DbService', { blockId })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to update single block:', { blockId, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk add message blocks (for new blocks)
|
||||||
|
*/
|
||||||
|
export const bulkAddBlocks = async (blocks: MessageBlock[]): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.bulkAddBlocks(blocks)
|
||||||
|
logger.silly('Bulk added blocks via DbService', { count: blocks.length })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to bulk add blocks:', { count: blocks.length, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update multiple message blocks (upsert operation)
|
||||||
|
*/
|
||||||
|
export const updateBlocks = async (blocks: MessageBlock[]): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await dbService.updateBlocks(blocks)
|
||||||
|
logger.silly('Updated blocks via DbService', { count: blocks.length })
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Failed to update blocks:', { count: blocks.length, error })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,249 +0,0 @@
|
|||||||
/**
|
|
||||||
* @deprecated Scheduled for removal in v2.0.0
|
|
||||||
* --------------------------------------------------------------------------
|
|
||||||
* ⚠️ NOTICE: V2 DATA&UI REFACTORING (by 0xfullex)
|
|
||||||
* --------------------------------------------------------------------------
|
|
||||||
* STOP: Feature PRs affecting this file are currently BLOCKED.
|
|
||||||
* Only critical bug fixes are accepted during this migration phase.
|
|
||||||
*
|
|
||||||
* This file is being refactored to v2 standards.
|
|
||||||
* Any non-critical changes will conflict with the ongoing work.
|
|
||||||
*
|
|
||||||
* 🔗 Context & Status:
|
|
||||||
* - Contribution Hold: https://github.com/CherryHQ/cherry-studio/issues/10954
|
|
||||||
* - v2 Refactor PR : https://github.com/CherryHQ/cherry-studio/pull/10162
|
|
||||||
* --------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* V2 implementations of message thunk functions using the unified DbService
|
|
||||||
* These implementations will be gradually rolled out using feature flags
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { loggerService } from '@logger'
|
|
||||||
import { dbService } from '@renderer/services/db'
|
|
||||||
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
|
||||||
|
|
||||||
import type { AppDispatch, RootState } from '../index'
|
|
||||||
import { upsertManyBlocks } from '../messageBlock'
|
|
||||||
import { newMessagesActions } from '../newMessage'
|
|
||||||
|
|
||||||
const logger = loggerService.withContext('MessageThunkV2')
|
|
||||||
|
|
||||||
// =================================================================
|
|
||||||
// Phase 2.1 - Batch 1: Read-only operations (lowest risk)
|
|
||||||
// =================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load messages for a topic using unified DbService
|
|
||||||
* This is the V2 implementation that will replace the original
|
|
||||||
*/
|
|
||||||
export const loadTopicMessagesThunkV2 =
|
|
||||||
(topicId: string, forceReload: boolean = false) =>
|
|
||||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
|
||||||
const state = getState()
|
|
||||||
|
|
||||||
dispatch(newMessagesActions.setCurrentTopicId(topicId))
|
|
||||||
|
|
||||||
// Skip if already cached and not forcing reload
|
|
||||||
if (!forceReload && state.messages.messageIdsByTopic[topicId]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
dispatch(newMessagesActions.setTopicLoading({ topicId, loading: true }))
|
|
||||||
|
|
||||||
// Unified call - no need to check isAgentSessionTopicId
|
|
||||||
const { messages, blocks } = await dbService.fetchMessages(topicId)
|
|
||||||
|
|
||||||
logger.silly('Loaded messages via DbService', {
|
|
||||||
topicId,
|
|
||||||
messageCount: messages.length,
|
|
||||||
blockCount: blocks.length
|
|
||||||
})
|
|
||||||
|
|
||||||
// Update Redux state with fetched data
|
|
||||||
if (blocks.length > 0) {
|
|
||||||
dispatch(upsertManyBlocks(blocks))
|
|
||||||
}
|
|
||||||
dispatch(newMessagesActions.messagesReceived({ topicId, messages }))
|
|
||||||
} catch (error) {
|
|
||||||
logger.error(`Failed to load messages for topic ${topicId}:`, error as Error)
|
|
||||||
// Could dispatch an error action here if needed
|
|
||||||
} finally {
|
|
||||||
dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get raw topic data using unified DbService
|
|
||||||
* Returns topic with messages array
|
|
||||||
*/
|
|
||||||
export const getRawTopicV2 = async (topicId: string): Promise<{ id: string; messages: Message[] } | undefined> => {
|
|
||||||
try {
|
|
||||||
const rawTopic = await dbService.getRawTopic(topicId)
|
|
||||||
logger.silly('Retrieved raw topic via DbService', { topicId, found: !!rawTopic })
|
|
||||||
return rawTopic
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to get raw topic:', { topicId, error })
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =================================================================
|
|
||||||
// Phase 2.2 - Batch 2: Helper functions
|
|
||||||
// =================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update file reference count
|
|
||||||
* Only applies to Dexie data source, no-op for agent sessions
|
|
||||||
*/
|
|
||||||
export const updateFileCountV2 = async (
|
|
||||||
fileId: string,
|
|
||||||
delta: number,
|
|
||||||
deleteIfZero: boolean = false
|
|
||||||
): Promise<void> => {
|
|
||||||
try {
|
|
||||||
// Pass all parameters to dbService, including deleteIfZero
|
|
||||||
await dbService.updateFileCount(fileId, delta, deleteIfZero)
|
|
||||||
logger.silly('Updated file count', { fileId, delta, deleteIfZero })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to update file count:', { fileId, delta, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =================================================================
|
|
||||||
// Phase 2.3 - Batch 3: Delete operations
|
|
||||||
// =================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a single message from database
|
|
||||||
*/
|
|
||||||
export const deleteMessageFromDBV2 = async (topicId: string, messageId: string): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.deleteMessage(topicId, messageId)
|
|
||||||
logger.silly('Deleted message via DbService', { topicId, messageId })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to delete message:', { topicId, messageId, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete multiple messages from database
|
|
||||||
*/
|
|
||||||
export const deleteMessagesFromDBV2 = async (topicId: string, messageIds: string[]): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.deleteMessages(topicId, messageIds)
|
|
||||||
logger.silly('Deleted messages via DbService', { topicId, count: messageIds.length })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to delete messages:', { topicId, messageIds, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all messages from a topic
|
|
||||||
*/
|
|
||||||
export const clearMessagesFromDBV2 = async (topicId: string): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.clearMessages(topicId)
|
|
||||||
logger.silly('Cleared all messages via DbService', { topicId })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to clear messages:', { topicId, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =================================================================
|
|
||||||
// Phase 2.4 - Batch 4: Complex write operations
|
|
||||||
// =================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save a message and its blocks to database
|
|
||||||
* Uses unified interface, no need for isAgentSessionTopicId check
|
|
||||||
*/
|
|
||||||
export const saveMessageAndBlocksToDBV2 = async (
|
|
||||||
topicId: string,
|
|
||||||
message: Message,
|
|
||||||
blocks: MessageBlock[],
|
|
||||||
messageIndex: number = -1
|
|
||||||
): Promise<void> => {
|
|
||||||
try {
|
|
||||||
const blockIds = blocks.map((block) => block.id)
|
|
||||||
const shouldSyncBlocks =
|
|
||||||
blockIds.length > 0 && (!message.blocks || blockIds.some((id, index) => message.blocks?.[index] !== id))
|
|
||||||
|
|
||||||
const messageWithBlocks = shouldSyncBlocks ? { ...message, blocks: blockIds } : message
|
|
||||||
// Direct call without conditional logic, now with messageIndex
|
|
||||||
await dbService.appendMessage(topicId, messageWithBlocks, blocks, messageIndex)
|
|
||||||
logger.silly('Saved message and blocks via DbService', {
|
|
||||||
topicId,
|
|
||||||
messageId: message.id,
|
|
||||||
blockCount: blocks.length,
|
|
||||||
messageIndex
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to save message and blocks:', { topicId, messageId: message.id, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: sendMessageV2 would be implemented here but it's more complex
|
|
||||||
// and would require more of the supporting code from messageThunk.ts
|
|
||||||
|
|
||||||
// =================================================================
|
|
||||||
// Phase 2.5 - Batch 5: Update operations
|
|
||||||
// =================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a message in the database
|
|
||||||
*/
|
|
||||||
export const updateMessageV2 = async (topicId: string, messageId: string, updates: Partial<Message>): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.updateMessage(topicId, messageId, updates)
|
|
||||||
logger.silly('Updated message via DbService', { topicId, messageId })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to update message:', { topicId, messageId, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a single message block
|
|
||||||
*/
|
|
||||||
export const updateSingleBlockV2 = async (blockId: string, updates: Partial<MessageBlock>): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.updateSingleBlock(blockId, updates)
|
|
||||||
logger.silly('Updated single block via DbService', { blockId })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to update single block:', { blockId, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk add message blocks (for new blocks)
|
|
||||||
*/
|
|
||||||
export const bulkAddBlocksV2 = async (blocks: MessageBlock[]): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.bulkAddBlocks(blocks)
|
|
||||||
logger.silly('Bulk added blocks via DbService', { count: blocks.length })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to bulk add blocks:', { count: blocks.length, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update multiple message blocks (upsert operation)
|
|
||||||
*/
|
|
||||||
export const updateBlocksV2 = async (blocks: MessageBlock[]): Promise<void> => {
|
|
||||||
try {
|
|
||||||
await dbService.updateBlocks(blocks)
|
|
||||||
logger.silly('Updated blocks via DbService', { count: blocks.length })
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to update blocks:', { count: blocks.length, error })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user