mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-07 22:10:21 +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 { loggerService } from '@logger'
|
||||||
import type { Topic } from '@renderer/types'
|
|
||||||
import type { AgentPersistedMessage } from '@renderer/types/agent'
|
import type { AgentPersistedMessage } from '@renderer/types/agent'
|
||||||
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
||||||
import { IpcChannel } from '@shared/IpcChannel'
|
import { IpcChannel } from '@shared/IpcChannel'
|
||||||
|
|
||||||
import type { MessageDataSource, MessageExchange } from './types'
|
import type { MessageDataSource } from './types'
|
||||||
import { extractSessionId } from './types'
|
import { extractSessionId } from './types'
|
||||||
|
|
||||||
const logger = loggerService.withContext('AgentMessageDataSource')
|
const logger = loggerService.withContext('AgentMessageDataSource')
|
||||||
@ -60,51 +59,7 @@ export class AgentMessageDataSource implements MessageDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============ Write Operations ============
|
// ============ Write Operations ============
|
||||||
|
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], _insertIndex?: number): Promise<void> {
|
||||||
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> {
|
|
||||||
// For agent sessions, we need to save messages immediately
|
// For agent sessions, we need to save messages immediately
|
||||||
// Don't wait for persistExchange which happens after response completion
|
// Don't wait for persistExchange which happens after response completion
|
||||||
const sessionId = extractSessionId(topicId)
|
const sessionId = extractSessionId(topicId)
|
||||||
@ -239,12 +194,12 @@ export class AgentMessageDataSource implements MessageDataSource {
|
|||||||
|
|
||||||
// ============ Block Operations ============
|
// ============ Block Operations ============
|
||||||
|
|
||||||
async updateBlocks(blocks: MessageBlock[]): Promise<void> {
|
async updateBlocks(_blocks: MessageBlock[]): Promise<void> {
|
||||||
// Blocks are updated through persistExchange for agent sessions
|
// Blocks are updated through persistExchange for agent sessions
|
||||||
logger.warn('updateBlocks called for agent session, operation not supported individually')
|
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
|
// Blocks cannot be deleted individually for agent sessions
|
||||||
logger.warn('deleteBlocks called for agent session, operation not supported')
|
logger.warn('deleteBlocks called for agent session, operation not supported')
|
||||||
}
|
}
|
||||||
@ -277,11 +232,7 @@ export class AgentMessageDataSource implements MessageDataSource {
|
|||||||
if (!window.electron?.ipcRenderer) {
|
if (!window.electron?.ipcRenderer) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return sessionId != null
|
||||||
// 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
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -294,26 +245,6 @@ export class AgentMessageDataSource implements MessageDataSource {
|
|||||||
logger.info(`ensureTopic called for agent session ${sessionId}, no action needed`)
|
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> {
|
async getRawTopic(topicId: string): Promise<{ id: string; messages: Message[] } | undefined> {
|
||||||
try {
|
try {
|
||||||
// For agent sessions, fetch messages from backend and return in raw topic format
|
// 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 ============
|
// ============ 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
|
// Agent session blocks are immutable once persisted
|
||||||
logger.warn(`updateSingleBlock called for agent session block ${blockId}, operation not supported`)
|
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
|
// Agent session blocks are added through persistExchange
|
||||||
logger.warn(`bulkAddBlocks called for agent session, operation not supported individually`)
|
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
|
// Agent sessions don't manage file reference counts locally
|
||||||
logger.warn(`updateFileCount called for agent session file ${fileId}, operation not supported`)
|
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
|
// Agent sessions don't manage file reference counts locally
|
||||||
logger.warn(`updateFileCounts called for agent session, operation not supported`)
|
logger.warn(`updateFileCounts called for agent session, operation not supported`)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import type { Topic } from '@renderer/types'
|
|
||||||
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
import type { Message, MessageBlock } from '@renderer/types/newMessage'
|
||||||
|
|
||||||
import { AgentMessageDataSource } from './AgentMessageDataSource'
|
import { AgentMessageDataSource } from './AgentMessageDataSource'
|
||||||
import { DexieMessageDataSource } from './DexieMessageDataSource'
|
import { DexieMessageDataSource } from './DexieMessageDataSource'
|
||||||
import type { MessageDataSource, MessageExchange } from './types'
|
import type { MessageDataSource } from './types'
|
||||||
import { isAgentSessionTopicId } from './types'
|
import { isAgentSessionTopicId } from './types'
|
||||||
|
|
||||||
const logger = loggerService.withContext('DbService')
|
const logger = loggerService.withContext('DbService')
|
||||||
@ -62,18 +61,7 @@ class DbService implements MessageDataSource {
|
|||||||
return source.fetchMessages(topicId, forceReload)
|
return source.fetchMessages(topicId, forceReload)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchTopic(topicId: string): Promise<Topic | undefined> {
|
|
||||||
const source = this.getDataSource(topicId)
|
|
||||||
return source.fetchTopic(topicId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============ Write Operations ============
|
// ============ 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> {
|
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], insertIndex?: number): Promise<void> {
|
||||||
const source = this.getDataSource(topicId)
|
const source = this.getDataSource(topicId)
|
||||||
return source.appendMessage(topicId, message, blocks, insertIndex)
|
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> {
|
async getRawTopic(topicId: string): Promise<{ id: string; messages: Message[] } | undefined> {
|
||||||
const source = this.getDataSource(topicId)
|
const source = this.getDataSource(topicId)
|
||||||
if (source.getRawTopic) {
|
return source.getRawTopic(topicId)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateSingleBlock(blockId: string, updates: Partial<MessageBlock>): Promise<void> {
|
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 type { Message, MessageBlock } from '@renderer/types/newMessage'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
|
|
||||||
import type { MessageDataSource, MessageExchange } from './types'
|
import type { MessageDataSource } from './types'
|
||||||
|
|
||||||
const logger = loggerService.withContext('DexieMessageDataSource')
|
const logger = loggerService.withContext('DexieMessageDataSource')
|
||||||
|
|
||||||
@ -58,61 +58,6 @@ export class DexieMessageDataSource implements MessageDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============ Write Operations ============
|
// ============ 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> {
|
async appendMessage(topicId: string, message: Message, blocks: MessageBlock[], insertIndex?: number): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await db.transaction('rw', db.topics, db.message_blocks, async () => {
|
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)
|
* 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 ============
|
// ============ Write Operations ============
|
||||||
/**
|
|
||||||
* Persist a complete message exchange (user + assistant)
|
|
||||||
*/
|
|
||||||
persistExchange(topicId: string, exchange: MessageExchange): Promise<void>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a single message with its blocks
|
* 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
|
// Note: sendMessageV2 would be implemented here but it's more complex
|
||||||
// and would require more of the supporting code from messageThunk.ts
|
// and would require more of the supporting code from messageThunk.ts
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user