mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 05:09:09 +08:00
feat(assistants): place copied assistant after the original one (#8557)
* feat(assistants): 复制助手功能插入到原助手后 添加 insertAssistant 方法用于在指定位置插入助手 实现 copyAssistant 功能用于复制助手并插入到原助手后面 更新相关组件以使用新的复制功能 * fix(useAssistant): 修复助手索引检查逻辑错误 原条件判断错误导致未找到索引时仍执行更新操作,现修正为仅在索引存在时更新 * fix(useAssistant): 添加错误处理及国际化支持 捕获插入助手时的异常并显示错误提示 添加react-i18next的翻译功能用于错误消息
This commit is contained in:
parent
dfceed8751
commit
46d98c2b22
@ -1,9 +1,11 @@
|
||||
import { db } from '@renderer/databases'
|
||||
import { getDefaultTopic } from '@renderer/services/AssistantService'
|
||||
import { loggerService } from '@renderer/services/LoggerService'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import {
|
||||
addAssistant,
|
||||
addTopic,
|
||||
insertAssistant,
|
||||
removeAllTopics,
|
||||
removeAssistant,
|
||||
removeTopic,
|
||||
@ -17,18 +19,44 @@ import {
|
||||
} from '@renderer/store/assistants'
|
||||
import { setDefaultModel, setTopicNamingModel, setTranslateModel } from '@renderer/store/llm'
|
||||
import { Assistant, AssistantSettings, Model, Topic } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { TopicManager } from './useTopic'
|
||||
|
||||
export function useAssistants() {
|
||||
const { t } = useTranslation()
|
||||
const { assistants } = useAppSelector((state) => state.assistants)
|
||||
const dispatch = useAppDispatch()
|
||||
const logger = loggerService.withContext('useAssistants')
|
||||
|
||||
return {
|
||||
assistants,
|
||||
updateAssistants: (assistants: Assistant[]) => dispatch(updateAssistants(assistants)),
|
||||
addAssistant: (assistant: Assistant) => dispatch(addAssistant(assistant)),
|
||||
insertAssistant: (index: number, assistant: Assistant) => dispatch(insertAssistant({ index, assistant })),
|
||||
copyAssistant: (assistant: Assistant): Assistant | undefined => {
|
||||
if (!assistant) {
|
||||
logger.error("assistant doesn't exists.")
|
||||
return
|
||||
}
|
||||
const index = assistants.findIndex((_assistant) => _assistant.id === assistant.id)
|
||||
const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic(assistant.id)] }
|
||||
if (index === -1) {
|
||||
logger.warn("Origin assistant's id not found. Fallback to addAssistant.")
|
||||
dispatch(addAssistant(_assistant))
|
||||
} else {
|
||||
// 插入到后面
|
||||
try {
|
||||
dispatch(insertAssistant({ index: index + 1, assistant: _assistant }))
|
||||
} catch (e) {
|
||||
logger.error('Failed to insert assistant', e as Error)
|
||||
window.message.error(t('message.error.copy'))
|
||||
}
|
||||
}
|
||||
return _assistant
|
||||
},
|
||||
removeAssistant: (id: string) => {
|
||||
dispatch(removeAssistant({ id }))
|
||||
const assistant = assistants.find((a) => a.id === id)
|
||||
|
||||
@ -25,7 +25,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
onCreateAssistant,
|
||||
onCreateDefaultAssistant
|
||||
}) => {
|
||||
const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants()
|
||||
const { assistants, removeAssistant, copyAssistant, updateAssistants } = useAssistants()
|
||||
const [dragging, setDragging] = useState(false)
|
||||
const { addAgent } = useAgents()
|
||||
const { t } = useTranslation()
|
||||
@ -106,7 +106,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
onSwitch={setActiveAssistant}
|
||||
onDelete={onDelete}
|
||||
addAgent={addAgent}
|
||||
addAssistant={addAssistant}
|
||||
copyAssistant={copyAssistant}
|
||||
onCreateDefaultAssistant={onCreateDefaultAssistant}
|
||||
handleSortByChange={handleSortByChange}
|
||||
/>
|
||||
@ -143,7 +143,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
onSwitch={setActiveAssistant}
|
||||
onDelete={onDelete}
|
||||
addAgent={addAgent}
|
||||
addAssistant={addAssistant}
|
||||
copyAssistant={copyAssistant}
|
||||
onCreateDefaultAssistant={onCreateDefaultAssistant}
|
||||
handleSortByChange={handleSortByChange}
|
||||
/>
|
||||
|
||||
@ -17,7 +17,7 @@ import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useTags } from '@renderer/hooks/useTags'
|
||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import { getDefaultModel, getDefaultTopic } from '@renderer/services/AssistantService'
|
||||
import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import { Assistant, AssistantsSortType } from '@renderer/types'
|
||||
import { getLeadingEmoji, uuid } from '@renderer/utils'
|
||||
@ -40,7 +40,7 @@ interface AssistantItemProps {
|
||||
onDelete: (assistant: Assistant) => void
|
||||
onCreateDefaultAssistant: () => void
|
||||
addAgent: (agent: any) => void
|
||||
addAssistant: (assistant: Assistant) => void
|
||||
copyAssistant: (assistant: Assistant) => void
|
||||
onTagClick?: (tag: string) => void
|
||||
handleSortByChange?: (sortType: AssistantsSortType) => void
|
||||
}
|
||||
@ -52,7 +52,7 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
onSwitch,
|
||||
onDelete,
|
||||
addAgent,
|
||||
addAssistant,
|
||||
copyAssistant,
|
||||
handleSortByChange
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
@ -91,7 +91,7 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
assistants,
|
||||
updateAssistants,
|
||||
addAgent,
|
||||
addAssistant,
|
||||
copyAssistant,
|
||||
onSwitch,
|
||||
onDelete,
|
||||
removeAllTopics,
|
||||
@ -108,7 +108,7 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
assistants,
|
||||
updateAssistants,
|
||||
addAgent,
|
||||
addAssistant,
|
||||
copyAssistant,
|
||||
onSwitch,
|
||||
onDelete,
|
||||
removeAllTopics,
|
||||
@ -246,7 +246,7 @@ function getMenuItems({
|
||||
assistants,
|
||||
updateAssistants,
|
||||
addAgent,
|
||||
addAssistant,
|
||||
copyAssistant,
|
||||
onSwitch,
|
||||
onDelete,
|
||||
removeAllTopics,
|
||||
@ -268,9 +268,10 @@ function getMenuItems({
|
||||
key: 'duplicate',
|
||||
icon: <CopyIcon />,
|
||||
onClick: async () => {
|
||||
const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic(assistant.id)] }
|
||||
addAssistant(_assistant)
|
||||
onSwitch(_assistant)
|
||||
const _assistant = copyAssistant(assistant)
|
||||
if (_assistant) {
|
||||
onSwitch(_assistant)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -32,6 +32,15 @@ const assistantsSlice = createSlice({
|
||||
addAssistant: (state, action: PayloadAction<Assistant>) => {
|
||||
state.assistants.push(action.payload)
|
||||
},
|
||||
insertAssistant: (state, action: PayloadAction<{ index: number; assistant: Assistant }>) => {
|
||||
const { index, assistant } = action.payload
|
||||
|
||||
if (index < 0 || index > state.assistants.length) {
|
||||
throw new Error(`InsertAssistant: index ${index} is out of bounds [0, ${state.assistants.length}]`)
|
||||
}
|
||||
|
||||
state.assistants.splice(index, 0, assistant)
|
||||
},
|
||||
removeAssistant: (state, action: PayloadAction<{ id: string }>) => {
|
||||
state.assistants = state.assistants.filter((c) => c.id !== action.payload.id)
|
||||
},
|
||||
@ -170,6 +179,7 @@ export const {
|
||||
updateDefaultAssistant,
|
||||
updateAssistants,
|
||||
addAssistant,
|
||||
insertAssistant,
|
||||
removeAssistant,
|
||||
updateAssistant,
|
||||
addTopic,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user