mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-24 10:40:07 +08:00
Remove persistExchange functionality and simplify agent session handling
- Delete persistExchange method from all data sources and DbService - Remove unused Topic import and MessageExchange type dependencies - Simplify agent session existence check to validate sessionId directly - Make getRawTopic required in MessageDataSource interface
This commit is contained in:
parent
15f216b050
commit
8645fe4ab1
@ -1,10 +1,9 @@
|
||||
import { loggerService } from '@logger'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import type { AgentPersistedMessage } from '@renderer/types/agent'
|
||||
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
|
||||
import type { MessageDataSource, MessageExchange } from './types'
|
||||
import type { MessageDataSource } from './types'
|
||||
import { extractSessionId } from './types'
|
||||
|
||||
const logger = loggerService.withContext('AgentMessageDataSource')
|
||||
@ -60,51 +59,7 @@ export class AgentMessageDataSource implements MessageDataSource {
|
||||
}
|
||||
|
||||
// ============ Write Operations ============
|
||||
|
||||
async persistExchange(topicId: string, exchange: MessageExchange): Promise<void> {
|
||||
try {
|
||||
const sessionId = extractSessionId(topicId)
|
||||
|
||||
if (!window.electron?.ipcRenderer) {
|
||||
logger.warn('IPC renderer not available for persist exchange')
|
||||
return
|
||||
}
|
||||
|
||||
const payload: any = {
|
||||
sessionId,
|
||||
agentSessionId: exchange.agentSessionId || ''
|
||||
}
|
||||
|
||||
// Prepare user payload
|
||||
if (exchange.user) {
|
||||
payload.user = {
|
||||
payload: {
|
||||
message: exchange.user.message,
|
||||
blocks: exchange.user.blocks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare assistant payload
|
||||
if (exchange.assistant) {
|
||||
payload.assistant = {
|
||||
payload: {
|
||||
message: exchange.assistant.message,
|
||||
blocks: exchange.assistant.blocks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await window.electron.ipcRenderer.invoke(IpcChannel.AgentMessage_PersistExchange, payload)
|
||||
|
||||
logger.info(`Persisted exchange for agent session ${sessionId}`)
|
||||
} catch (error) {
|
||||
logger.error(`Failed to persist exchange for agent session ${topicId}:`, error as Error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], insertIndex?: number): Promise<void> {
|
||||
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], _insertIndex?: number): Promise<void> {
|
||||
// For agent sessions, we need to save messages immediately
|
||||
// Don't wait for persistExchange which happens after response completion
|
||||
const sessionId = extractSessionId(topicId)
|
||||
@ -239,12 +194,12 @@ export class AgentMessageDataSource implements MessageDataSource {
|
||||
|
||||
// ============ Block Operations ============
|
||||
|
||||
async updateBlocks(blocks: MessageBlock[]): Promise<void> {
|
||||
async updateBlocks(_blocks: MessageBlock[]): Promise<void> {
|
||||
// Blocks are updated through persistExchange for agent sessions
|
||||
logger.warn('updateBlocks called for agent session, operation not supported individually')
|
||||
}
|
||||
|
||||
async deleteBlocks(blockIds: string[]): Promise<void> {
|
||||
async deleteBlocks(_blockIds: string[]): Promise<void> {
|
||||
// Blocks cannot be deleted individually for agent sessions
|
||||
logger.warn('deleteBlocks called for agent session, operation not supported')
|
||||
}
|
||||
@ -277,11 +232,7 @@ export class AgentMessageDataSource implements MessageDataSource {
|
||||
if (!window.electron?.ipcRenderer) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if session exists by trying to fetch messages
|
||||
// In a full implementation, you'd have a dedicated endpoint
|
||||
const messages = await this.fetchMessages(topicId)
|
||||
return true // If no error thrown, session exists
|
||||
return sessionId != null
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
@ -294,26 +245,6 @@ export class AgentMessageDataSource implements MessageDataSource {
|
||||
logger.info(`ensureTopic called for agent session ${sessionId}, no action needed`)
|
||||
}
|
||||
|
||||
async fetchTopic(topicId: string): Promise<Topic | undefined> {
|
||||
try {
|
||||
const sessionId = extractSessionId(topicId)
|
||||
|
||||
// For agent sessions, we construct a synthetic topic
|
||||
// In a real implementation, you might fetch session metadata from backend
|
||||
return {
|
||||
id: topicId,
|
||||
name: `Session ${sessionId}`,
|
||||
assistantId: 'agent',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
messages: [] // Messages are fetched separately
|
||||
} as Topic
|
||||
} catch (error) {
|
||||
logger.error(`Failed to fetch topic for agent session ${topicId}:`, error as Error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async getRawTopic(topicId: string): Promise<{ id: string; messages: Message[] } | undefined> {
|
||||
try {
|
||||
// For agent sessions, fetch messages from backend and return in raw topic format
|
||||
@ -330,22 +261,22 @@ export class AgentMessageDataSource implements MessageDataSource {
|
||||
|
||||
// ============ Additional Methods for Interface Compatibility ============
|
||||
|
||||
async updateSingleBlock(blockId: string, updates: Partial<MessageBlock>): Promise<void> {
|
||||
async updateSingleBlock(blockId: string, _updates: Partial<MessageBlock>): Promise<void> {
|
||||
// Agent session blocks are immutable once persisted
|
||||
logger.warn(`updateSingleBlock called for agent session block ${blockId}, operation not supported`)
|
||||
}
|
||||
|
||||
async bulkAddBlocks(blocks: MessageBlock[]): Promise<void> {
|
||||
async bulkAddBlocks(_blocks: MessageBlock[]): Promise<void> {
|
||||
// Agent session blocks are added through persistExchange
|
||||
logger.warn(`bulkAddBlocks called for agent session, operation not supported individually`)
|
||||
}
|
||||
|
||||
async updateFileCount(fileId: string, delta: number): Promise<void> {
|
||||
async updateFileCount(fileId: string, _delta: number): Promise<void> {
|
||||
// Agent sessions don't manage file reference counts locally
|
||||
logger.warn(`updateFileCount called for agent session file ${fileId}, operation not supported`)
|
||||
}
|
||||
|
||||
async updateFileCounts(files: Array<{ id: string; delta: number }>): Promise<void> {
|
||||
async updateFileCounts(_files: Array<{ id: string; delta: number }>): Promise<void> {
|
||||
// Agent sessions don't manage file reference counts locally
|
||||
logger.warn(`updateFileCounts called for agent session, operation not supported`)
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { loggerService } from '@logger'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
||||
|
||||
import { AgentMessageDataSource } from './AgentMessageDataSource'
|
||||
import { DexieMessageDataSource } from './DexieMessageDataSource'
|
||||
import type { MessageDataSource, MessageExchange } from './types'
|
||||
import type { MessageDataSource } from './types'
|
||||
import { isAgentSessionTopicId } from './types'
|
||||
|
||||
const logger = loggerService.withContext('DbService')
|
||||
@ -62,18 +61,7 @@ class DbService implements MessageDataSource {
|
||||
return source.fetchMessages(topicId, forceReload)
|
||||
}
|
||||
|
||||
async fetchTopic(topicId: string): Promise<Topic | undefined> {
|
||||
const source = this.getDataSource(topicId)
|
||||
return source.fetchTopic(topicId)
|
||||
}
|
||||
|
||||
// ============ Write Operations ============
|
||||
|
||||
async persistExchange(topicId: string, exchange: MessageExchange): Promise<void> {
|
||||
const source = this.getDataSource(topicId)
|
||||
return source.persistExchange(topicId, exchange)
|
||||
}
|
||||
|
||||
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], insertIndex?: number): Promise<void> {
|
||||
const source = this.getDataSource(topicId)
|
||||
return source.appendMessage(topicId, message, blocks, insertIndex)
|
||||
@ -141,12 +129,7 @@ class DbService implements MessageDataSource {
|
||||
|
||||
async getRawTopic(topicId: string): Promise<{ id: string; messages: Message[] } | undefined> {
|
||||
const source = this.getDataSource(topicId)
|
||||
if (source.getRawTopic) {
|
||||
return source.getRawTopic(topicId)
|
||||
}
|
||||
// Fallback: fetch using fetchTopic and extract messages
|
||||
const topic = await source.fetchTopic(topicId)
|
||||
return topic ? { id: topic.id, messages: topic.messages } : undefined
|
||||
return source.getRawTopic(topicId)
|
||||
}
|
||||
|
||||
async updateSingleBlock(blockId: string, updates: Partial<MessageBlock>): Promise<void> {
|
||||
|
||||
@ -6,7 +6,7 @@ import { updateTopicUpdatedAt } from '@renderer/store/assistants'
|
||||
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
import type { MessageDataSource, MessageExchange } from './types'
|
||||
import type { MessageDataSource } from './types'
|
||||
|
||||
const logger = loggerService.withContext('DexieMessageDataSource')
|
||||
|
||||
@ -58,61 +58,6 @@ export class DexieMessageDataSource implements MessageDataSource {
|
||||
}
|
||||
|
||||
// ============ Write Operations ============
|
||||
|
||||
async persistExchange(topicId: string, exchange: MessageExchange): Promise<void> {
|
||||
try {
|
||||
await db.transaction('rw', db.topics, db.message_blocks, async () => {
|
||||
const topic = await db.topics.get(topicId)
|
||||
if (!topic) {
|
||||
throw new Error(`Topic ${topicId} not found`)
|
||||
}
|
||||
|
||||
const updatedMessages = [...topic.messages]
|
||||
const blocksToSave: MessageBlock[] = []
|
||||
|
||||
// Handle user message
|
||||
if (exchange.user) {
|
||||
const userIndex = updatedMessages.findIndex((m) => m.id === exchange.user!.message.id)
|
||||
if (userIndex !== -1) {
|
||||
updatedMessages[userIndex] = exchange.user.message
|
||||
} else {
|
||||
updatedMessages.push(exchange.user.message)
|
||||
}
|
||||
if (exchange.user.blocks.length > 0) {
|
||||
blocksToSave.push(...exchange.user.blocks)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle assistant message
|
||||
if (exchange.assistant) {
|
||||
const assistantIndex = updatedMessages.findIndex((m) => m.id === exchange.assistant!.message.id)
|
||||
if (assistantIndex !== -1) {
|
||||
updatedMessages[assistantIndex] = exchange.assistant.message
|
||||
} else {
|
||||
updatedMessages.push(exchange.assistant.message)
|
||||
}
|
||||
if (exchange.assistant.blocks.length > 0) {
|
||||
blocksToSave.push(...exchange.assistant.blocks)
|
||||
}
|
||||
}
|
||||
|
||||
// Save blocks
|
||||
if (blocksToSave.length > 0) {
|
||||
await db.message_blocks.bulkPut(blocksToSave)
|
||||
}
|
||||
|
||||
// Update topic with new messages
|
||||
await db.topics.update(topicId, { messages: updatedMessages })
|
||||
})
|
||||
|
||||
// Update Redux state
|
||||
store.dispatch(updateTopicUpdatedAt({ topicId }))
|
||||
} catch (error) {
|
||||
logger.error(`Failed to persist exchange for topic ${topicId}:`, error as Error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], insertIndex?: number): Promise<void> {
|
||||
try {
|
||||
await db.transaction('rw', db.topics, db.message_blocks, async () => {
|
||||
|
||||
@ -36,14 +36,9 @@ export interface MessageDataSource {
|
||||
/**
|
||||
* Get raw topic data (just id and messages)
|
||||
*/
|
||||
getRawTopic?(topicId: string): Promise<{ id: string; messages: Message[] } | undefined>
|
||||
getRawTopic(topicId: string): Promise<{ id: string; messages: Message[] } | undefined>
|
||||
|
||||
// ============ Write Operations ============
|
||||
/**
|
||||
* Persist a complete message exchange (user + assistant)
|
||||
*/
|
||||
persistExchange(topicId: string, exchange: MessageExchange): Promise<void>
|
||||
|
||||
/**
|
||||
* Append a single message with its blocks
|
||||
*/
|
||||
|
||||
@ -204,29 +204,6 @@ export const saveMessageAndBlocksToDBV2 = async (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist a message exchange (user + assistant messages)
|
||||
*/
|
||||
export const persistExchangeV2 = async (
|
||||
topicId: string,
|
||||
exchange: {
|
||||
user?: { message: Message; blocks: MessageBlock[] }
|
||||
assistant?: { message: Message; blocks: MessageBlock[] }
|
||||
}
|
||||
): Promise<void> => {
|
||||
try {
|
||||
await dbService.persistExchange(topicId, exchange)
|
||||
logger.info('Persisted exchange via DbService', {
|
||||
topicId,
|
||||
hasUser: !!exchange.user,
|
||||
hasAssistant: !!exchange.assistant
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('Failed to persist exchange:', { topicId, 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
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user