refactor(assistant): replace useAgents with useAssistants across components, streamline assistant management and enhance template handling

This commit is contained in:
suyao 2025-06-13 05:14:53 +08:00
parent 09fe2aa67b
commit 509632030b
No known key found for this signature in database
19 changed files with 168 additions and 152 deletions

View File

@ -1,5 +1,4 @@
import { TopView } from '@renderer/components/TopView'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
import { useSystemAgents } from '@renderer/pages/agents'
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
@ -24,7 +23,7 @@ interface Props {
const PopupContainer: React.FC<Props> = ({ resolve }) => {
const [open, setOpen] = useState(true)
const { t } = useTranslation()
const { agents: userAgents } = useAgents()
const { assistants: userAgents } = useAssistants()
const [searchText, setSearchText] = useState('')
const { defaultAssistant } = useDefaultAssistant()
const { assistants, addAssistant } = useAssistants()

View File

@ -1,28 +0,0 @@
import { useAppDispatch, useAppSelector } from '@renderer/store'
import { addAgent, removeAgent, updateAgent, updateAgents, updateAgentSettings } from '@renderer/store/agents'
import { Agent, AssistantSettings } from '@renderer/types'
export function useAgents() {
const agents = useAppSelector((state) => state.agents.agents)
const dispatch = useAppDispatch()
return {
agents,
updateAgents: (agents: Agent[]) => dispatch(updateAgents(agents)),
addAgent: (agent: Agent) => dispatch(addAgent(agent)),
removeAgent: (id: string) => dispatch(removeAgent({ id }))
}
}
export function useAgent(id: string) {
const agent = useAppSelector((state) => state.agents.agents.find((a) => a.id === id) as Agent)
const dispatch = useAppDispatch()
return {
agent,
updateAgent: (agent: Agent) => dispatch(updateAgent(agent)),
updateAgentSettings: (settings: Partial<AssistantSettings>) => {
dispatch(updateAgentSettings({ assistantId: agent.id, settings }))
}
}
}

View File

@ -2,7 +2,10 @@ import { db } from '@renderer/databases'
import { useAppDispatch, useAppSelector } from '@renderer/store'
import {
addAssistant,
createAssistantFromTemplate,
removeAssistant,
selectActiveAssistants,
selectTemplates,
setModel,
updateAssistant,
updateAssistants,
@ -15,20 +18,32 @@ import { Assistant, AssistantSettings, Model, Topic } from '@renderer/types'
import { useCallback, useMemo } from 'react'
export function useAssistants() {
const { assistants } = useAppSelector((state) => state.assistants)
const assistants = useAppSelector(selectActiveAssistants)
const templates = useAppSelector(selectTemplates)
const dispatch = useAppDispatch()
const getAssistantById = useCallback((id: string) => assistants.find((a) => a.id === id), [assistants])
return {
assistants,
templates,
getAssistantById,
updateAssistants: (assistants: Assistant[]) => dispatch(updateAssistants(assistants)),
addAssistant: (assistant: Assistant) => {
dispatch(addAssistant(assistant))
dispatch(addAssistant({ ...assistant, isTemplate: false }))
dispatch(topicsActions.addDefaultTopic({ assistantId: assistant.id }))
},
addTemplate: (template: Assistant) => {
dispatch(addAssistant({ ...template, isTemplate: true }))
},
removeAssistant: (id: string) => {
dispatch(removeAssistant({ id }))
// Remove all topics for this assistant
dispatch(topicsActions.removeAllTopics({ assistantId: id }))
},
createAssistantFromTemplate: (templateId: string, assistantId: string) => {
dispatch(createAssistantFromTemplate({ templateId, assistantId }))
dispatch(topicsActions.addDefaultTopic({ assistantId }))
}
}
}

View File

@ -26,7 +26,6 @@ import { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { v4 as uuidv4 } from 'uuid'
import { useAgents } from './useAgents'
import { useAssistants } from './useAssistant'
export const useKnowledge = (baseId: string) => {
@ -319,7 +318,6 @@ export const useKnowledgeBases = () => {
const dispatch = useDispatch()
const bases = useSelector((state: RootState) => state.knowledge.bases)
const { assistants, updateAssistants } = useAssistants()
const { agents, updateAgents } = useAgents()
const addKnowledgeBase = (base: KnowledgeBase) => {
dispatch(addBase(base))
@ -343,19 +341,7 @@ export const useKnowledgeBases = () => {
return assistant
})
// remove agent knowledge_base
const _agents = agents.map((agent) => {
if (agent.knowledge_bases?.find((kb) => kb.id === baseId)) {
return {
...agent,
knowledge_bases: agent.knowledge_bases.filter((kb) => kb.id !== baseId)
}
}
return agent
})
updateAssistants(_assistants)
updateAgents(_agents)
}
const updateKnowledgeBases = (bases: KnowledgeBase[]) => {

View File

@ -3,7 +3,7 @@ import { NavbarCenter, NavbarMain } from '@renderer/components/app/Navbar'
import CustomTag from '@renderer/components/CustomTag'
import ListItem from '@renderer/components/ListItem'
import Scrollbar from '@renderer/components/Scrollbar'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
import { Agent } from '@renderer/types'
import { uuid } from '@renderer/utils'
@ -28,7 +28,7 @@ const AgentsPage: FC = () => {
const [activeGroup, setActiveGroup] = useState('我的')
const [agentGroups, setAgentGroups] = useState<Record<string, Agent[]>>({})
const systemAgents = useSystemAgents()
const { agents: userAgents } = useAgents()
const { templates: userAgents } = useAssistants()
useEffect(() => {
const systemAgentsGroupList = groupByCategories(systemAgents)

View File

@ -4,7 +4,7 @@ import { CheckOutlined, LoadingOutlined, RollbackOutlined, ThunderboltOutlined }
import EmojiPicker from '@renderer/components/EmojiPicker'
import { TopView } from '@renderer/components/TopView'
import { AGENT_PROMPT } from '@renderer/config/prompts'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
import { fetchGenerate } from '@renderer/services/ApiService'
import { getDefaultModel } from '@renderer/services/AssistantService'
@ -34,7 +34,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
const [open, setOpen] = useState(true)
const [form] = Form.useForm()
const { t } = useTranslation()
const { addAgent } = useAgents()
const { addTemplate } = useAssistants()
const formRef = useRef<FormInstance>(null)
const [emoji, setEmoji] = useState('')
const [loading, setLoading] = useState(false)
@ -82,12 +82,12 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
emoji: _emoji,
prompt: values.prompt,
defaultModel: getDefaultModel(),
type: 'agent',
topics: [],
messages: []
messages: [],
isTemplate: true
}
addAgent(_agent)
addTemplate(_agent)
resolve(_agent)
setOpen(false)
}

View File

@ -7,7 +7,7 @@ import {
SortAscendingOutlined
} from '@ant-design/icons'
import CustomTag from '@renderer/components/CustomTag'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
import type { Agent } from '@renderer/types'
@ -27,7 +27,7 @@ interface Props {
}
const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupName }) => {
const { removeAgent } = useAgents()
const { removeAssistant: removeAgent } = useAssistants()
const [isVisible, setIsVisible] = useState(false)
const cardRef = useRef<HTMLDivElement>(null)

View File

@ -1,5 +1,5 @@
import { TopView } from '@renderer/components/TopView'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { getDefaultModel } from '@renderer/services/AssistantService'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { Agent } from '@renderer/types'
@ -16,7 +16,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
const [open, setOpen] = useState(true)
const [form] = Form.useForm()
const { t } = useTranslation()
const { addAgent } = useAgents()
const { addTemplate: addAgent } = useAssistants()
const [importType, setImportType] = useState<'url' | 'file'>('url')
const [loading, setLoading] = useState(false)

View File

@ -2,7 +2,7 @@ import { MenuOutlined } from '@ant-design/icons'
import DragableList from '@renderer/components/DragableList'
import { Box, HStack } from '@renderer/components/Layout'
import { TopView } from '@renderer/components/TopView'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { Empty, Modal } from 'antd'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -11,7 +11,8 @@ import styled from 'styled-components'
const PopupContainer: React.FC = () => {
const [open, setOpen] = useState(true)
const { t } = useTranslation()
const { agents, updateAgents } = useAgents()
const { assistants, updateAssistants: updateAgents } = useAssistants()
const agents = assistants.filter((a) => a.isTemplate)
const onOk = () => {
setOpen(false)

View File

@ -2,7 +2,6 @@ import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
import UserPopup from '@renderer/components/Popups/UserPopup'
import { AppLogo, UserAvatar } from '@renderer/config/env'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useAssistants } from '@renderer/hooks/useAssistant'
import useAvatar from '@renderer/hooks/useAvatar'
import { useChat } from '@renderer/hooks/useChat'
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
@ -11,6 +10,7 @@ import { useShortcut } from '@renderer/hooks/useShortcuts'
import { useShowAssistants } from '@renderer/hooks/useStore'
import i18n from '@renderer/i18n'
import AssistantItem from '@renderer/pages/home/Tabs/components/AssistantItem'
import { getAssistantById } from '@renderer/services/AssistantService'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { ThemeMode } from '@renderer/types'
import { isEmoji } from '@renderer/utils'
@ -57,7 +57,6 @@ import PinnedApps from './PinnedApps'
type Tab = 'assistants' | 'topic'
const MainSidebar: FC = () => {
const { assistants } = useAssistants()
const navigate = useNavigate()
const [tab, setTab] = useState<Tab>('assistants')
const avatar = useAvatar()
@ -92,7 +91,7 @@ const MainSidebar: FC = () => {
useEffect(() => {
const unsubscribes = [
EventEmitter.on(EVENT_NAMES.SWITCH_ASSISTANT, (assistantId: string) => {
const newAssistant = assistants.find((a) => a.id === assistantId)
const newAssistant = getAssistantById(assistantId)
if (newAssistant) {
setActiveAssistant(newAssistant)
}
@ -104,7 +103,7 @@ const MainSidebar: FC = () => {
]
return () => unsubscribes.forEach((unsubscribe) => unsubscribe())
}, [assistants, setActiveAssistant, tab])
}, [setActiveAssistant, tab])
useEffect(() => {
const canMinimize = !showAssistants && !showTopics
@ -204,7 +203,6 @@ const MainSidebar: FC = () => {
sortBy="list"
onSwitch={() => {}}
onDelete={() => {}}
addAgent={() => {}}
addAssistant={() => {}}
onCreateDefaultAssistant={() => {}}
handleSortByChange={() => {}}

View File

@ -2,7 +2,6 @@ import { DownOutlined, PlusOutlined, RightOutlined } from '@ant-design/icons'
import { Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
import DragableList from '@renderer/components/DragableList'
import Scrollbar from '@renderer/components/Scrollbar'
import { useAgents } from '@renderer/hooks/useAgents'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { useAssistantsTabSortType } from '@renderer/hooks/useStore'
import { useTags } from '@renderer/hooks/useTags'
@ -29,7 +28,6 @@ const Assistants: FC<AssistantsTabProps> = ({
const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants()
const [dragging, setDragging] = useState(false)
const [collapsedTags, setCollapsedTags] = useState<Record<string, boolean>>({})
const { addAgent } = useAgents()
const { t } = useTranslation()
const { getGroupedAssistants, allTags, updateTagsOrder } = useTags()
const { assistantsTabSortType = 'list', setAssistantsTabSortType } = useAssistantsTabSortType()
@ -206,7 +204,6 @@ const Assistants: FC<AssistantsTabProps> = ({
isActive={assistant?.id === activeAssistant.id}
onSwitch={setActiveAssistant}
onDelete={onDelete}
addAgent={addAgent}
addAssistant={addAssistant}
onCreateDefaultAssistant={() => {}}
/>
@ -249,7 +246,6 @@ const Assistants: FC<AssistantsTabProps> = ({
sortBy={assistantsTabSortType}
onSwitch={setActiveAssistant}
onDelete={onDelete}
addAgent={addAgent}
addAssistant={addAssistant}
onCreateDefaultAssistant={onCreateDefaultAssistant}
handleSortByChange={handleSortByChange}

View File

@ -39,7 +39,6 @@ interface AssistantItemProps {
onSwitch: (assistant: Assistant) => void
onDelete: (assistant: Assistant) => void
onCreateDefaultAssistant: () => void
addAgent: (agent: any) => void
addAssistant: (assistant: Assistant) => void
onTagClick?: (tag: string) => void
handleSortByChange?: (sortType: AssistantsSortType) => void
@ -52,7 +51,6 @@ const AssistantItem: FC<AssistantItemProps> = ({
sortBy,
onSwitch,
onDelete,
addAgent,
addAssistant,
handleSortByChange,
singleLine = false
@ -95,7 +93,6 @@ const AssistantItem: FC<AssistantItemProps> = ({
allTags,
assistants,
updateAssistants,
addAgent,
addAssistant,
onSwitch,
onDelete,
@ -112,7 +109,6 @@ const AssistantItem: FC<AssistantItemProps> = ({
allTags,
assistants,
updateAssistants,
addAgent,
addAssistant,
onSwitch,
onDelete,
@ -280,7 +276,6 @@ function getMenuItems({
allTags,
assistants,
updateAssistants,
addAgent,
addAssistant,
onSwitch,
onDelete,
@ -329,8 +324,8 @@ function getMenuItems({
onClick: async () => {
const agent = omit(assistant, ['model', 'emoji'])
agent.id = uuid()
agent.type = 'agent'
addAgent(agent)
agent.isTemplate = true
addAssistant(agent)
window.message.success({
content: t('assistants.save.success'),
key: 'save-to-agent'

View File

@ -1,6 +1,5 @@
import { HStack } from '@renderer/components/Layout'
import { TopView } from '@renderer/components/TopView'
import { useAgent } from '@renderer/hooks/useAgents'
import { useAssistant } from '@renderer/hooks/useAssistant'
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
import { Assistant } from '@renderer/types'
@ -31,13 +30,7 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
const { t } = useTranslation()
const [menu, setMenu] = useState<AssistantSettingPopupTab>(tab || 'prompt')
const _useAssistant = useAssistant(props.assistant.id)
const _useAgent = useAgent(props.assistant.id)
const isAgent = props.assistant.type === 'agent'
const assistant = isAgent ? _useAgent.agent : _useAssistant.assistant
const updateAssistant = isAgent ? _useAgent.updateAgent : _useAssistant.updateAssistant
const updateAssistantSettings = isAgent ? _useAgent.updateAgentSettings : _useAssistant.updateAssistantSettings
const { updateAssistant, updateAssistantSettings } = useAssistant(props.assistant.id)
const showKnowledgeIcon = useSidebarIconShow('knowledge')
@ -50,7 +43,7 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
}
const afterClose = () => {
resolve(assistant)
resolve(props.assistant)
}
const items = [
@ -84,7 +77,7 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
onCancel={onCancel}
afterClose={afterClose}
footer={null}
title={assistant.name}
title={props.assistant.name}
transitionName="animation-move-down"
styles={{
content: {
@ -112,34 +105,34 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
<Settings>
{menu === 'prompt' && (
<AssistantPromptSettings
assistant={assistant}
assistant={props.assistant}
updateAssistant={updateAssistant}
updateAssistantSettings={updateAssistantSettings}
/>
)}
{menu === 'model' && (
<AssistantModelSettings
assistant={assistant}
assistant={props.assistant}
updateAssistant={updateAssistant}
updateAssistantSettings={updateAssistantSettings}
/>
)}
{menu === 'knowledge_base' && showKnowledgeIcon && (
<AssistantKnowledgeBaseSettings
assistant={assistant}
assistant={props.assistant}
updateAssistant={updateAssistant}
updateAssistantSettings={updateAssistantSettings}
/>
)}
{menu === 'mcp' && (
<AssistantMCPSettings
assistant={assistant}
assistant={props.assistant}
updateAssistant={updateAssistant}
updateAssistantSettings={updateAssistantSettings}
/>
)}
{menu === 'regular_phrases' && (
<AssistantRegularPromptsSettings assistant={assistant} updateAssistant={updateAssistant} />
<AssistantRegularPromptsSettings assistant={props.assistant} updateAssistant={updateAssistant} />
)}
</Settings>
</HStack>

View File

@ -14,8 +14,8 @@ export function getDefaultAssistant(): Assistant {
prompt: '',
topics: [],
messages: [],
type: 'assistant',
regularPhrases: [] // Added regularPhrases
regularPhrases: [],
isTemplate: false
}
}
@ -126,8 +126,8 @@ export async function createAssistantFromAgent(agent: Agent) {
name: agent.name,
emoji: agent.emoji,
model: agent.defaultModel,
type: 'assistant',
regularPhrases: agent.regularPhrases || [] // Ensured regularPhrases
isTemplate: false,
regularPhrases: agent.regularPhrases || []
}
store.dispatch(addAssistant(assistant))
@ -140,3 +140,17 @@ export async function createAssistantFromAgent(agent: Agent) {
return assistant
}
export function createTemplate(templateData: Partial<Assistant>): Assistant {
return {
id: uuid(),
name: templateData.name || 'New Template',
prompt: templateData.prompt || '',
topics: [],
messages: [],
type: 'assistant',
isTemplate: true,
regularPhrases: [],
...templateData
}
}

View File

@ -1,8 +1,13 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { DEFAULT_CONTEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
import { Agent, AssistantSettings } from '@renderer/types'
import { createSlice } from '@reduxjs/toolkit'
import { Agent } from '@renderer/types'
/**
* @deprecated use assistants instead
*/
export interface AgentsState {
/**
* @deprecated use assistants instead
*/
agents: Agent[]
}
@ -13,44 +18,7 @@ const initialState: AgentsState = {
const assistantsSlice = createSlice({
name: 'agents',
initialState,
reducers: {
updateAgents: (state, action: PayloadAction<Agent[]>) => {
state.agents = action.payload
},
addAgent: (state, action: PayloadAction<Agent>) => {
state.agents.push(action.payload)
},
removeAgent: (state, action: PayloadAction<{ id: string }>) => {
state.agents = state.agents.filter((c) => c.id !== action.payload.id)
},
updateAgent: (state, action: PayloadAction<Agent>) => {
state.agents = state.agents.map((c) => (c.id === action.payload.id ? action.payload : c))
},
updateAgentSettings: (
state,
action: PayloadAction<{ assistantId: string; settings: Partial<AssistantSettings> }>
) => {
for (const agent of state.agents) {
const settings = action.payload.settings
if (agent.id === action.payload.assistantId) {
for (const key in settings) {
if (!agent.settings) {
agent.settings = {
temperature: DEFAULT_TEMPERATURE,
contextCount: DEFAULT_CONTEXTCOUNT,
enableMaxTokens: false,
maxTokens: 0,
streamOutput: true
}
}
agent.settings[key] = settings[key]
}
}
}
}
}
reducers: {}
})
export const { updateAgents, addAgent, removeAgent, updateAgent, updateAgentSettings } = assistantsSlice.actions
export default assistantsSlice.reducer

View File

@ -1,4 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { createSelector } from '@reduxjs/toolkit'
import { DEFAULT_CONTEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
import { getDefaultAssistant } from '@renderer/services/AssistantService'
import { Assistant, AssistantSettings, Model } from '@renderer/types'
@ -15,6 +16,30 @@ const initialState: AssistantsState = {
tagsOrder: []
}
// ----------- selectors -----------
// 基础selector
export const selectAssistantsState = (state: { assistants: AssistantsState }) => state.assistants
// 获取所有助手(不含模板)
export const selectActiveAssistants = createSelector(selectAssistantsState, (state) =>
state.assistants.filter((a) => !a.isTemplate)
)
// 获取所有模板
export const selectTemplates = createSelector(selectAssistantsState, (state) =>
state.assistants.filter((a) => a.isTemplate)
)
// 通过id查找助手不含模板
export const selectAssistantById = (id: string) =>
createSelector(selectActiveAssistants, (assistants) => assistants.find((a) => a.id === id))
// 通过id查找模板
export const selectTemplateById = (id: string) =>
createSelector(selectTemplates, (templates) => templates.find((a) => a.id === id))
// ----------- end selectors -----------
const assistantsSlice = createSlice({
name: 'assistants',
initialState,
@ -24,7 +49,14 @@ const assistantsSlice = createSlice({
state.defaultAssistant = assistant
},
updateAssistants: (state, action: PayloadAction<Assistant[]>) => {
state.assistants = action.payload
const assistants = action.payload
const templates = assistants.filter((a) => a.isTemplate)
state.assistants = [...assistants.filter((a) => !a.isTemplate), ...templates]
},
updateTemplates: (state, action: PayloadAction<Assistant[]>) => {
const templates = action.payload
const assistants = state.assistants.filter((a) => !a.isTemplate)
state.assistants = [...assistants, ...templates]
},
addAssistant: (state, action: PayloadAction<Assistant>) => {
state.assistants.push(action.payload)
@ -40,9 +72,9 @@ const assistantsSlice = createSlice({
state,
action: PayloadAction<{ assistantId: string; settings: Partial<AssistantSettings> }>
) => {
const { assistantId, settings } = action.payload
for (const assistant of state.assistants) {
const settings = action.payload.settings
if (assistant.id === action.payload.assistantId) {
if (assistant.id === assistantId) {
for (const key in settings) {
if (!assistant.settings) {
assistant.settings = {
@ -58,17 +90,30 @@ const assistantsSlice = createSlice({
}
}
},
setModel: (state, action: PayloadAction<{ assistantId: string; model: Model }>) => {
const { assistantId, model } = action.payload
state.assistants = state.assistants.map((assistant) =>
assistant.id === assistantId
? {
...assistant,
model: model
}
: assistant
)
for (let i = 0; i < state.assistants.length; i++) {
if (state.assistants[i].id === assistantId) {
state.assistants[i] = {
...state.assistants[i],
model: model
}
break
}
}
},
// 从模板创建助手
createAssistantFromTemplate: (state, action: PayloadAction<{ templateId: string; assistantId: string }>) => {
const { templateId, assistantId } = action.payload
const template = state.assistants.find((t) => t.id === templateId && t.isTemplate)
if (template) {
const newAssistant: Assistant = {
...template,
id: assistantId,
isTemplate: false
}
state.assistants.push(newAssistant)
}
},
setTagsOrder: (state, action: PayloadAction<string[]>) => {
state.tagsOrder = action.payload
@ -82,6 +127,7 @@ export const {
addAssistant,
removeAssistant,
updateAssistant,
createAssistantFromTemplate,
setModel,
setTagsOrder,
updateAssistantSettings

View File

@ -52,7 +52,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 113,
version: 114,
blacklist: ['runtime', 'messages', 'messageBlocks'],
migrate
},

View File

@ -1658,6 +1658,37 @@ const migrateConfig = {
topicIdsByAssistant
}
return state
} catch (error) {
return state
}
},
'114': (state: RootState) => {
try {
if (
state.assistants &&
state.assistants.defaultAssistant &&
state.assistants.defaultAssistant.isTemplate === undefined
) {
state.assistants.defaultAssistant.isTemplate = false
}
if (state.assistants && state.assistants.assistants.length > 0) {
state.assistants.assistants
.filter((assistant) => assistant.isTemplate !== undefined)
.forEach((assistant) => {
assistant.isTemplate = false
})
}
if (state.agents && state.agents.agents.length > 0) {
state.agents.agents.forEach((agent) => {
agent.isTemplate = true
state.assistants.assistants.push(agent)
})
}
// @ts-ignore eslint-disable-next-line
delete state.agents
return state
} catch (error) {
return state

View File

@ -12,7 +12,8 @@ export type Assistant = {
knowledge_bases?: KnowledgeBase[]
/** @deprecated 话题现在通过独立的 topics slice 管理,请使用 selectTopicsForAssistant selector */
topics: Topic[]
type: string
/** @deprecated 助手类型已废弃,请使用 isTemplate 字段 */
type?: string
emoji?: string
description?: string
model?: Model
@ -27,6 +28,8 @@ export type Assistant = {
knowledgeRecognition?: 'off' | 'on'
regularPhrases?: QuickPhrase[] // Added for regular phrase
tags?: string[] // 助手标签
isTemplate?: boolean
group?: string[]
}
export type AssistantsSortType = 'tags' | 'list'
@ -66,9 +69,8 @@ export type AssistantSettings = {
toolUseMode?: 'function' | 'prompt'
}
export type Agent = Omit<Assistant, 'model'> & {
group?: string[]
}
// 为了兼容性保留Agent类型别名
export type Agent = Assistant
/**
* @deprecated