From d41f175a0554650d38698d2368ceea8b7ca09ea1 Mon Sep 17 00:00:00 2001 From: suyao Date: Thu, 12 Jun 2025 21:03:17 +0800 Subject: [PATCH] refactor(assistant): enhance assistant creation by automatically adding default topics; streamline default assistant handling --- src/renderer/src/hooks/useAssistant.ts | 23 ++++------- src/renderer/src/services/AssistantService.ts | 5 ++- src/renderer/src/store/assistants.ts | 34 +---------------- src/renderer/src/store/migrate.ts | 38 +++++-------------- src/renderer/src/store/topics.ts | 10 +++-- 5 files changed, 29 insertions(+), 81 deletions(-) diff --git a/src/renderer/src/hooks/useAssistant.ts b/src/renderer/src/hooks/useAssistant.ts index bc9a55fbd2..130c3282a8 100644 --- a/src/renderer/src/hooks/useAssistant.ts +++ b/src/renderer/src/hooks/useAssistant.ts @@ -1,5 +1,4 @@ import { db } from '@renderer/databases' -import { getDefaultTopic } from '@renderer/services/AssistantService' import { useAppDispatch, useAppSelector } from '@renderer/store' import { addAssistant, @@ -22,7 +21,10 @@ export function useAssistants() { return { assistants, updateAssistants: (assistants: Assistant[]) => dispatch(updateAssistants(assistants)), - addAssistant: (assistant: Assistant) => dispatch(addAssistant(assistant)), + addAssistant: (assistant: Assistant) => { + dispatch(addAssistant(assistant)) + dispatch(topicsActions.addDefaultTopic({ assistantId: assistant.id })) + }, removeAssistant: (id: string) => { dispatch(removeAssistant({ id })) // Remove all topics for this assistant @@ -85,24 +87,15 @@ export function useTopicsForAssistant(assistantId: string) { return useAppSelector((state) => selectTopicsForAssistant(state, assistantId)) } +/** + * 默认助手模板 + */ export function useDefaultAssistant() { const defaultAssistant = useAppSelector((state) => state.assistants.defaultAssistant) - const topics = useTopicsForAssistant(defaultAssistant.id) const dispatch = useAppDispatch() - // Ensure default assistant has at least one topic - const finalTopics = useMemo(() => { - if (topics.length > 0) { - return topics - } - return [getDefaultTopic(defaultAssistant.id)] - }, [topics, defaultAssistant.id]) - return { - defaultAssistant: { - ...defaultAssistant, - topics: finalTopics - }, + defaultAssistant, updateDefaultAssistant: (assistant: Assistant) => dispatch(updateDefaultAssistant({ assistant })) } } diff --git a/src/renderer/src/services/AssistantService.ts b/src/renderer/src/services/AssistantService.ts index 7619e0e3b4..db5f3322b6 100644 --- a/src/renderer/src/services/AssistantService.ts +++ b/src/renderer/src/services/AssistantService.ts @@ -2,6 +2,7 @@ import { DEFAULT_CONTEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@ import i18n from '@renderer/i18n' import store from '@renderer/store' import { addAssistant } from '@renderer/store/assistants' +import { topicsActions } from '@renderer/store/topics' import type { Agent, Assistant, AssistantSettings, Model, Provider, Topic } from '@renderer/types' import { uuid } from '@renderer/utils' @@ -11,7 +12,7 @@ export function getDefaultAssistant(): Assistant { name: i18n.t('chat.default.name'), emoji: '😀', prompt: '', - topics: [getDefaultTopic('default')], + topics: [], messages: [], type: 'assistant', regularPhrases: [] // Added regularPhrases @@ -124,13 +125,13 @@ export async function createAssistantFromAgent(agent: Agent) { id: assistantId, name: agent.name, emoji: agent.emoji, - topics: [topic], model: agent.defaultModel, type: 'assistant', regularPhrases: agent.regularPhrases || [] // Ensured regularPhrases } store.dispatch(addAssistant(assistant)) + store.dispatch(topicsActions.addTopic({ assistantId, topic })) window.message.success({ content: i18n.t('message.assistant.added.content'), diff --git a/src/renderer/src/store/assistants.ts b/src/renderer/src/store/assistants.ts index 855008b4cd..f2f41a1935 100644 --- a/src/renderer/src/store/assistants.ts +++ b/src/renderer/src/store/assistants.ts @@ -9,14 +9,9 @@ export interface AssistantsState { tagsOrder: string[] } -// 之前的两个实例会导致两个助手不一致的问题 -// FIXME: 更彻底的办法在这次重构就直接把二者合并了 -// Create a single default assistant instance to ensure consistency -const defaultAssistant = getDefaultAssistant() - const initialState: AssistantsState = { - defaultAssistant: defaultAssistant, - assistants: [defaultAssistant], // Share the same reference + defaultAssistant: getDefaultAssistant(), // 这个是模型设置的默认助手 + assistants: [getDefaultAssistant()], // 这个是主页列表的默认助手 tagsOrder: [] } @@ -27,21 +22,9 @@ const assistantsSlice = createSlice({ updateDefaultAssistant: (state, action: PayloadAction<{ assistant: Assistant }>) => { const assistant = action.payload.assistant state.defaultAssistant = assistant - - // Also update the corresponding assistant in the array - const index = state.assistants.findIndex((a) => a.id === assistant.id) - if (index !== -1) { - state.assistants[index] = assistant - } }, updateAssistants: (state, action: PayloadAction) => { state.assistants = action.payload - - // Update defaultAssistant if it exists in the new array - const defaultInArray = action.payload.find((a) => a.id === state.defaultAssistant.id) - if (defaultInArray) { - state.defaultAssistant = defaultInArray - } }, addAssistant: (state, action: PayloadAction) => { state.assistants.push(action.payload) @@ -52,11 +35,6 @@ const assistantsSlice = createSlice({ updateAssistant: (state, action: PayloadAction) => { const assistant = action.payload state.assistants = state.assistants.map((c) => (c.id === assistant.id ? assistant : c)) - - // Also update defaultAssistant if it's the same assistant - if (state.defaultAssistant.id === assistant.id) { - state.defaultAssistant = assistant - } }, updateAssistantSettings: ( state, @@ -91,14 +69,6 @@ const assistantsSlice = createSlice({ } : assistant ) - - // Also update defaultAssistant if it's the same assistant - if (state.defaultAssistant.id === assistantId) { - state.defaultAssistant = { - ...state.defaultAssistant, - model: model - } - } }, setTagsOrder: (state, action: PayloadAction) => { state.tagsOrder = action.payload diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts index 21dc198c35..a2d53d80e7 100644 --- a/src/renderer/src/store/migrate.ts +++ b/src/renderer/src/store/migrate.ts @@ -1570,26 +1570,21 @@ const migrateConfig = { }, '113': (state: RootState) => { try { - // Step 1: Merge defaultAssistant and assistants[0] topics to ensure consistency - // This fixes any inconsistencies from backup restores or previous versions + // Step 1: 把默认助手模板下面的话题合并到主页列表的默认助手Id下面,保持默认助手模板的纯粹性 if (state.assistants?.defaultAssistant && state.assistants?.assistants?.length > 0) { - const defaultAssistantId = state.assistants.defaultAssistant.id + const defaultAssistantId = state['assistants'].defaultAssistant.id const defaultAssistantInArray = state.assistants.assistants.find((a) => a.id === defaultAssistantId) if (defaultAssistantInArray) { - // Merge topics from both defaultAssistant and assistants[0] - const defaultTopics = state.assistants.defaultAssistant.topics || [] + const defaultTopics = state['assistants'].defaultAssistant.topics || [] const arrayTopics = defaultAssistantInArray.topics || [] - // Create a map to avoid duplicates (by topic id) const topicsMap = new Map() - // Add topics from both sources - const allTopics = [...defaultTopics, ...arrayTopics] + const allTopics = [...arrayTopics, ...defaultTopics] allTopics.forEach((topic) => { if (topic && topic.id) { - // Keep the one with more recent updatedAt, or prefer the one from assistants array const existing = topicsMap.get(topic.id) if ( !existing || @@ -1603,19 +1598,14 @@ const migrateConfig = { const mergedTopics = Array.from(topicsMap.values()) - // Update both defaultAssistant and the assistant in array - state.assistants.defaultAssistant.topics = mergedTopics + state['assistants'].defaultAssistant.topics = [] defaultAssistantInArray.topics = mergedTopics } else { - // defaultAssistant not found in array, add it - state.assistants.assistants.unshift(state.assistants.defaultAssistant) + // 如果默认助手不存在,说明被用户删掉了 } } - // Step 2: Migrate from nested topic structure to flattened topic structure - // This should run after v112 which ensures defaultAssistant and assistants[0] consistency - - // Initialize the new topics slice if it doesn't exist + // Step 2: 迁移话题结构,从嵌套结构迁移到扁平结构 if (!state.topics) { state.topics = { ids: [], @@ -1632,8 +1622,8 @@ const migrateConfig = { const topicIdsByAssistant: Record = {} // Process regular assistants - if (state.assistants?.assistants) { - state.assistants.assistants.forEach((assistant) => { + if (state['assistants'].assistants && state['assistants'].assistants.length > 0) { + state['assistants'].assistants.forEach((assistant) => { const legacyAssistant = assistant as LegacyAssistant if (legacyAssistant.topics && Array.isArray(legacyAssistant.topics) && legacyAssistant.topics.length > 0) { allTopics.push(...legacyAssistant.topics) @@ -1653,14 +1643,6 @@ const migrateConfig = { }) } - // Process default assistant - should already be consistent after v112 - if (state.assistants?.defaultAssistant) { - const legacyDefaultAssistant = state.assistants.defaultAssistant as LegacyAssistant - - // Since v112 already ensured consistency, just clear the deprecated field - legacyDefaultAssistant.topics = [] - } - // Populate the new topics slice const topicEntities: Record = {} const topicIds: string[] = [] @@ -1670,7 +1652,6 @@ const migrateConfig = { topicIds.push(topic.id) }) - // Update topics slice state.topics = { ids: topicIds, entities: topicEntities, @@ -1679,7 +1660,6 @@ const migrateConfig = { return state } catch (error) { - console.error('Migration 112 failed:', error) return state } } diff --git a/src/renderer/src/store/topics.ts b/src/renderer/src/store/topics.ts index 3a623315e0..b8847f3177 100644 --- a/src/renderer/src/store/topics.ts +++ b/src/renderer/src/store/topics.ts @@ -130,9 +130,7 @@ const topicsSlice = createSlice({ topicsAdapter.removeMany(state, topicIds) // Create default topic - const defaultTopic = getDefaultTopic(assistantId) - topicsAdapter.addOne(state, defaultTopic) - state.topicIdsByAssistant[assistantId] = [defaultTopic.id] + topicsActions.addDefaultTopic({ assistantId }) }, moveTopic(state, action: PayloadAction) { const { fromAssistantId, toAssistantId, topicId } = action.payload @@ -154,6 +152,12 @@ const topicsSlice = createSlice({ state.topicIdsByAssistant[toAssistantId] = [] } state.topicIdsByAssistant[toAssistantId].unshift(topicId) + }, + addDefaultTopic(state, action: PayloadAction<{ assistantId: string }>) { + const { assistantId } = action.payload + const defaultTopic = getDefaultTopic(assistantId) + topicsAdapter.addOne(state, defaultTopic) + state.topicIdsByAssistant[assistantId] = [defaultTopic.id] } } })