diff --git a/src/renderer/src/hooks/useAssistant.ts b/src/renderer/src/hooks/useAssistant.ts index 02a327c345..9527764f81 100644 --- a/src/renderer/src/hooks/useAssistant.ts +++ b/src/renderer/src/hooks/useAssistant.ts @@ -7,10 +7,10 @@ import { MODEL_SUPPORTED_REASONING_EFFORT } from '@renderer/config/models' import { db } from '@renderer/databases' -import { getDefaultTopic } from '@renderer/services/AssistantService' +import { getDefaultAssistant, getDefaultTopic } from '@renderer/services/AssistantService' import { useAppDispatch, useAppSelector } from '@renderer/store' import { - addAssistant, + addAssistant as _addAssistant, addTopic, insertAssistant, removeAllTopics, @@ -27,6 +27,7 @@ import { import { setDefaultModel, setQuickModel, setTranslateModel } from '@renderer/store/llm' import { Assistant, AssistantSettings, Model, ThinkingOption, Topic } from '@renderer/types' import { uuid } from '@renderer/utils' +import { formatErrorMessage } from '@renderer/utils/error' import { useCallback, useEffect, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' @@ -38,10 +39,25 @@ export function useAssistants() { const dispatch = useAppDispatch() const logger = loggerService.withContext('useAssistants') + /** + * 添加一个新的助手 + * @param assistant - 要添加的助手对象 + * @throws {Error} 如果添加助手失败会抛出错误 + */ + const addAssistant = (assistant: Assistant) => { + try { + dispatch(_addAssistant(assistant)) + } catch (e) { + logger.error('Failed to add assistant', e as Error) + window.message.error(t('assistants.error.add' + ': ' + formatErrorMessage(e))) + throw e + } + } + return { assistants, updateAssistants: (assistants: Assistant[]) => dispatch(updateAssistants(assistants)), - addAssistant: (assistant: Assistant) => dispatch(addAssistant(assistant)), + addAssistant, insertAssistant: (index: number, assistant: Assistant) => dispatch(insertAssistant({ index, assistant })), copyAssistant: (assistant: Assistant): Assistant | undefined => { if (!assistant) { @@ -52,7 +68,7 @@ export function useAssistants() { 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)) + addAssistant(_assistant) } else { // 插入到后面 try { @@ -74,7 +90,22 @@ export function useAssistants() { } export function useAssistant(id: string) { - const assistant = useAppSelector((state) => state.assistants.assistants.find((a) => a.id === id) as Assistant) + let assistant = useAppSelector((state) => state.assistants.assistants.find((a) => a.id === id)) + const { addAssistant } = useAssistants() + const { t } = useTranslation() + + if (!assistant) { + window.message.warning(t('warning.missing_assistant')) + const newAssistant = { ...getDefaultAssistant(), id } + try { + addAssistant(newAssistant) + assistant = newAssistant + } catch (e) { + window.message.warning(t('warning.fallback.deafult_assistant')) + assistant = getDefaultAssistant() + } + } + const dispatch = useAppDispatch() const { defaultModel } = useDefaultModel() @@ -88,7 +119,7 @@ export function useAssistant(id: string) { const settingsRef = useRef(assistant?.settings) useEffect(() => { - settingsRef.current = assistant.settings + settingsRef.current = assistant?.settings }, [assistant?.settings]) const updateAssistantSettings = useCallback( diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 0a6ffbf92f..b440f49282 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -148,6 +148,9 @@ "edit": { "title": "Edit Assistant" }, + "error": { + "add": "Failed to add assistant" + }, "icon": { "type": "Assistant Icon" }, @@ -3787,6 +3790,10 @@ "title": "Update" }, "warning": { + "fallback": { + "deafult_assistant": "Reverted to default assistant, which may cause issues" + }, + "missing_assistant": "Assistant does not exist", "missing_provider": "The supplier does not exist; reverted to the default supplier {{provider}}. This may cause issues." }, "words": { diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index f35e31231a..1b68659cf5 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -148,6 +148,9 @@ "edit": { "title": "アシスタントを編集" }, + "error": { + "add": "アシスタントの追加に失敗しました" + }, "icon": { "type": "アシスタントアイコン" }, @@ -3787,6 +3790,10 @@ "title": "更新" }, "warning": { + "fallback": { + "deafult_assistant": "既定のアシスタントに戻されました。これにより問題が発生する可能性があります。" + }, + "missing_assistant": "アシスタントが存在しません", "missing_provider": "サプライヤーが存在しないため、デフォルトのサプライヤー {{provider}} にロールバックされました。これにより問題が発生する可能性があります。" }, "words": { diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 69b64ce26f..d2fa9a969a 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -148,6 +148,9 @@ "edit": { "title": "Редактировать ассистента" }, + "error": { + "add": "Не удалось добавить помощника" + }, "icon": { "type": "Иконка ассистента" }, @@ -3787,6 +3790,10 @@ "title": "Обновление" }, "warning": { + "fallback": { + "deafult_assistant": "Возвращено к помощнику по умолчанию, что может привести к проблемам" + }, + "missing_assistant": "Ассистент не существует", "missing_provider": "Поставщик не существует, возвращение к поставщику по умолчанию {{provider}}. Это может привести к проблемам." }, "words": { diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 3164f068ab..816343ea89 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -148,6 +148,9 @@ "edit": { "title": "编辑助手" }, + "error": { + "add": "添加助手失败" + }, "icon": { "type": "助手图标" }, @@ -3787,6 +3790,10 @@ "title": "更新提示" }, "warning": { + "fallback": { + "deafult_assistant": "已回退到默认助手,这可能导致问题" + }, + "missing_assistant": "助手不存在", "missing_provider": "供应商不存在,已回退到默认供应商 {{provider}}。这可能导致问题。" }, "words": { diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index df5500fc71..8825bbce7c 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -148,6 +148,9 @@ "edit": { "title": "編輯助手" }, + "error": { + "add": "添加助手失敗" + }, "icon": { "type": "助手圖示" }, @@ -3787,6 +3790,10 @@ "title": "更新提示" }, "warning": { + "fallback": { + "deafult_assistant": "已回退到預設助手,這可能導致問題" + }, + "missing_assistant": "助手不存在", "missing_provider": "供應商不存在,已回退到預設供應商 {{provider}}。這可能導致問題。" }, "words": { diff --git a/src/renderer/src/i18n/translate/el-gr.json b/src/renderer/src/i18n/translate/el-gr.json index 9cbbda52c1..985544229b 100644 --- a/src/renderer/src/i18n/translate/el-gr.json +++ b/src/renderer/src/i18n/translate/el-gr.json @@ -148,6 +148,9 @@ "edit": { "title": "Επεξεργασία βοηθού" }, + "error": { + "add": "Αποτυχία προσθήκης βοηθού" + }, "icon": { "type": "Εικόνα Βοηθού" }, @@ -2679,6 +2682,7 @@ "title": "Αυτόματη ενημέρωση" }, "avatar": { + "builtin": "ενσωματωμένο avatar", "reset": "Επαναφορά εικονιδίου" }, "backup": { @@ -3783,6 +3787,10 @@ "title": "Ενημέρωση" }, "warning": { + "fallback": { + "deafult_assistant": "Επαναφέρθηκε στον προεπιλεγμένο βοηθό, γεγονός που ενδέχεται να προκαλέσει προβλήματα" + }, + "missing_assistant": "Ο βοηθός δεν υπάρχει", "missing_provider": "Ο προμηθευτής δεν υπάρχει, έγινε επαναφορά στον προεπιλεγμένο προμηθευτή {{provider}}. Αυτό μπορεί να προκαλέσει προβλήματα." }, "words": { diff --git a/src/renderer/src/i18n/translate/es-es.json b/src/renderer/src/i18n/translate/es-es.json index 25e186c567..d0cd6bd565 100644 --- a/src/renderer/src/i18n/translate/es-es.json +++ b/src/renderer/src/i18n/translate/es-es.json @@ -148,6 +148,9 @@ "edit": { "title": "Editar Asistente" }, + "error": { + "add": "Error al agregar asistente" + }, "icon": { "type": "Ícono del Asistente" }, @@ -2679,6 +2682,7 @@ "title": "Actualización automática" }, "avatar": { + "builtin": "Avatares integrados", "reset": "Restablecer avatar" }, "backup": { @@ -3783,6 +3787,10 @@ "title": "Actualización" }, "warning": { + "fallback": { + "deafult_assistant": "Se ha revertido al asistente predeterminado, lo que podría causar problemas" + }, + "missing_assistant": "El asistente no existe", "missing_provider": "El proveedor no existe, se ha revertido al proveedor predeterminado {{provider}}. Esto podría causar problemas." }, "words": { diff --git a/src/renderer/src/i18n/translate/fr-fr.json b/src/renderer/src/i18n/translate/fr-fr.json index 266985c94b..d91c04abe2 100644 --- a/src/renderer/src/i18n/translate/fr-fr.json +++ b/src/renderer/src/i18n/translate/fr-fr.json @@ -148,6 +148,9 @@ "edit": { "title": "Modifier l'Aide" }, + "error": { + "add": "Échec de l'ajout de l'assistant" + }, "icon": { "type": "Icône de l'assistant" }, @@ -2679,6 +2682,7 @@ "title": "Mise à jour automatique" }, "avatar": { + "builtin": "Avatar intégré", "reset": "Réinitialiser l'avatar" }, "backup": { @@ -3783,6 +3787,10 @@ "title": "Mise à jour" }, "warning": { + "fallback": { + "deafult_assistant": "Revenu à l'assistant par défaut, ce qui pourrait entraîner des problèmes" + }, + "missing_assistant": "L'assistant n'existe pas", "missing_provider": "Le fournisseur n’existe pas, retour au fournisseur par défaut {{provider}}. Cela peut entraîner des problèmes." }, "words": { diff --git a/src/renderer/src/i18n/translate/pt-pt.json b/src/renderer/src/i18n/translate/pt-pt.json index def1ee8900..b66907dfaa 100644 --- a/src/renderer/src/i18n/translate/pt-pt.json +++ b/src/renderer/src/i18n/translate/pt-pt.json @@ -148,6 +148,9 @@ "edit": { "title": "Editar Assistente" }, + "error": { + "add": "Falha ao adicionar assistente" + }, "icon": { "type": "Ícone do Assistente" }, @@ -2679,6 +2682,7 @@ "title": "Atualização automática" }, "avatar": { + "builtin": "Avatares integrados", "reset": "Redefinir avatar" }, "backup": { @@ -3783,6 +3787,10 @@ "title": "Atualização" }, "warning": { + "fallback": { + "deafult_assistant": "Voltou ao assistente padrão, o que pode causar problemas" + }, + "missing_assistant": "O assistente não existe", "missing_provider": "O fornecedor não existe; foi revertido para o fornecedor predefinido {{provider}}. Isto pode causar problemas." }, "words": { diff --git a/src/renderer/src/store/assistants.ts b/src/renderer/src/store/assistants.ts index 15a735bc7f..d6108ff7b4 100644 --- a/src/renderer/src/store/assistants.ts +++ b/src/renderer/src/store/assistants.ts @@ -32,7 +32,13 @@ const assistantsSlice = createSlice({ state.assistants = action.payload }, addAssistant: (state, action: PayloadAction) => { - state.assistants.push(action.payload) + const newAssistant = action.payload + const existing = state.assistants.find((item) => item.id === newAssistant.id) + if (!existing) { + state.assistants.push(action.payload) + } else { + throw new Error('Assistant with this ID already exists') + } }, insertAssistant: (state, action: PayloadAction<{ index: number; assistant: Assistant }>) => { const { index, assistant } = action.payload