From a298c7bf4941c0ea47cc6a5f7d480afc9457260c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9C=A3=E8=BE=BE=E7=94=9F=E7=89=A9=E5=A4=9A?= Date: Mon, 13 Jul 2026 23:52:05 +0800 Subject: [PATCH] feat: import and export personas (#4532) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Feature] 人格设定支持导出/导入。 Fixes #4409 - 导出的json * 导入(dev * 稍微进化 * 改为直接导出文件 * 删除未使用的i18n键值 * fix:仅白名单字段可以作为文件名 * PersonaForm.vue - savePersona 方法添加了白名单字段过滤 * update * [Feature] 人格设定支持导出/导入。 Fixes #4409 * 再次完成 * 修复bug 405 * 移除导入和导出按钮的本地化文本(上一次修改的 * 移动到 persona 的 i18n JSON * [Feature] 人格设定支持导出/导入。 Fixes #4409 找回需要的i18n * 写错地方了,更正i18n * 保证相同的i18n * 在导出时说明不包含tools Skills * 修改导出格式 * 新格式导入 * 重复检查 * [Bug]当 LLM 的回复本身包含类似 JSON 的格式的时候消息的 content 字段可能被错误地多次序列化 Fixes #4363 * [Bug]当 LLM 的回复本身包含类似 JSON 的格式的时候消息的 content 字段可能被错误地多次序列化 Fixes #4363 * [Bug]当 LLM 的回复本身包含类似 JSON 的格式的时候消息的 content 字段可能被错误地多次序列化 Fixes #4363 提取_parse_image_url_part 处理base64 * - 当原始数据是字符串时(`raw_data` 不为 None):返回 `{"type": "json", "data": {"content": "..."}}` 包装形式 - 当原始数据是字典时:直接返回 `{"type": "json", "data": {...原始字典...}}`,不使用 content 包装 * 像其他组件一样使用 self.type * 在 Json.__init__ 中 传入 self.raw_data * 在 Json.to_dict 中 使用 self.type.lower() 来推导 * [Bug]当 LLM 的回复本身包含类似 JSON 的格式的时候消息的 content 字段可能被错误地多次序列化 Fixes #4363 * [Bug]当 LLM 的回复本身包含类似 JSON 的格式的时候消息的 content 字段可能被错误地多次序列化 Fixes #4363 * [Bug]当 LLM 的回复本身包含类似 JSON 的格式的时候消息的 content 字段可能被错误地多次序列化 Fixes #4363 提取_parse_image_url_part 处理base64 * - 当原始数据是字符串时(`raw_data` 不为 None):返回 `{"type": "json", "data": {"content": "..."}}` 包装形式 - 当原始数据是字典时:直接返回 `{"type": "json", "data": {...原始字典...}}`,不使用 content 包装 * 像其他组件一样使用 self.type * 在 Json.__init__ 中 传入 self.raw_data * 在 Json.to_dict 中 使用 self.type.lower() 来推导 * [Feature] 人格设定支持导出/导入。 Fixes #4409 * 同步 * feat(persona): 添加导入和导出功能,增强用户体验 --- .../i18n/locales/en-US/features/persona.json | 14 ++- .../i18n/locales/ru-RU/features/persona.json | 14 ++- .../i18n/locales/zh-CN/features/persona.json | 14 ++- dashboard/src/views/persona/PersonaCard.vue | 50 +++++++++- .../src/views/persona/PersonaManager.vue | 93 ++++++++++++++++++- 5 files changed, 176 insertions(+), 9 deletions(-) diff --git a/dashboard/src/i18n/locales/en-US/features/persona.json b/dashboard/src/i18n/locales/en-US/features/persona.json index 3dc865c02..301747be9 100644 --- a/dashboard/src/i18n/locales/en-US/features/persona.json +++ b/dashboard/src/i18n/locales/en-US/features/persona.json @@ -10,7 +10,9 @@ "cancel": "Cancel", "save": "Save", "move": "Move", - "addDialogPair": "Add Dialog Pair" + "addDialogPair": "Add Dialog Pair", + "export": "Export", + "import": "Import Persona" }, "labels": { "presetDialogs": "Preset Dialogs ({count} pairs)", @@ -83,7 +85,15 @@ "saveError": "Save failed", "deleteConfirm": "Are you sure you want to delete persona \"{id}\"? This action cannot be undone.", "deleteSuccess": "Deleted successfully", - "deleteError": "Delete failed" + "deleteError": "Delete failed", + "exportConfirm": "Export only includes system prompt and preset dialogs, not tools and Skills config. Continue?", + "exportSuccess": "Exported successfully", + "exportError": "Export failed: {error}", + "importSuccess": "Persona imported successfully, please configure tools and Skills manually", + "importError": "Import failed: {error}", + "importFormatError": "Invalid file format, please select a valid persona export file", + "importMissingPrompt": "Incomplete file content, missing system prompt", + "importIdExists": "Persona name already exists, renamed to \"{id}\"" }, "persona": { "personasTitle": "Personas", diff --git a/dashboard/src/i18n/locales/ru-RU/features/persona.json b/dashboard/src/i18n/locales/ru-RU/features/persona.json index f7e0aff25..78db7156d 100644 --- a/dashboard/src/i18n/locales/ru-RU/features/persona.json +++ b/dashboard/src/i18n/locales/ru-RU/features/persona.json @@ -10,7 +10,9 @@ "cancel": "Отмена", "save": "Сохранить", "move": "Переместить", - "addDialogPair": "Добавить пример диалога" + "addDialogPair": "Добавить пример диалога", + "export": "Экспорт", + "import": "Импорт персонажа" }, "labels": { "presetDialogs": "Примеры диалогов ({count})", @@ -83,7 +85,15 @@ "saveError": "Ошибка сохранения", "deleteConfirm": "Вы уверены, что хотите удалить персонажа «{id}»? Это действие необратимо.", "deleteSuccess": "Удалено", - "deleteError": "Ошибка удаления" + "deleteError": "Ошибка удаления", + "exportConfirm": "Экспорт содержит только системный промпт и примеры диалогов, без инструментов и навыков. Продолжить?", + "exportSuccess": "Экспортировано", + "exportError": "Ошибка экспорта: {error}", + "importSuccess": "Персонаж импортирован, настройте инструменты и навыки вручную", + "importError": "Ошибка импорта: {error}", + "importFormatError": "Неверный формат файла, выберите корректный файл экспорта", + "importMissingPrompt": "Неполное содержимое файла, отсутствует системный промпт", + "importIdExists": "Имя персонажа уже существует, переименовано в «{id}»" }, "persona": { "personasTitle": "Персонаж", diff --git a/dashboard/src/i18n/locales/zh-CN/features/persona.json b/dashboard/src/i18n/locales/zh-CN/features/persona.json index e707a5d62..12a4fce4f 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/persona.json +++ b/dashboard/src/i18n/locales/zh-CN/features/persona.json @@ -10,7 +10,9 @@ "cancel": "取消", "save": "保存", "move": "移动", - "addDialogPair": "添加对话对" + "addDialogPair": "添加对话对", + "export": "导出", + "import": "导入人格" }, "labels": { "presetDialogs": "预设对话 ({count} 对)", @@ -83,7 +85,15 @@ "saveError": "保存失败", "deleteConfirm": "确定要删除人格 \"{id}\" 吗?此操作不可撤销。", "deleteSuccess": "删除成功", - "deleteError": "删除失败" + "deleteError": "删除失败", + "exportConfirm": "导出仅包含系统提示词和预设对话,不包含工具和 Skills 配置。是否继续导出?", + "exportSuccess": "导出成功", + "exportError": "导出失败:{error}", + "importSuccess": "人格导入成功,请手动配置工具和 Skills", + "importError": "导入失败:{error}", + "importFormatError": "文件格式错误,请选择有效的人格导出文件", + "importMissingPrompt": "文件内容不完整,缺少系统提示词", + "importIdExists": "人格名称已存在,已重命名为 \"{id}\"" }, "persona": { "personasTitle": "人格", diff --git a/dashboard/src/views/persona/PersonaCard.vue b/dashboard/src/views/persona/PersonaCard.vue index 7cebb26a9..69e218ca9 100644 --- a/dashboard/src/views/persona/PersonaCard.vue +++ b/dashboard/src/views/persona/PersonaCard.vue @@ -20,6 +20,12 @@ {{ tm('persona.contextMenu.moveTo') }} + + + {{ tm('buttons.export') }} +