From 653e5d82ed14e2d2726473eb4fe059cb8b6cb507 Mon Sep 17 00:00:00 2001 From: Neal_Tan <425088158@qq.com> Date: Mon, 17 Feb 2025 00:12:40 +0000 Subject: [PATCH 01/39] docs: optimize issues (#1790) --- .github/ISSUE_TEMPLATE/#0_bug_report.yml | 17 +++++----- .github/ISSUE_TEMPLATE/#1_feature_request.yml | 15 ++++++--- .github/ISSUE_TEMPLATE/#2_question.yml | 10 +++--- .github/ISSUE_TEMPLATE/0_bug_report.yml | 17 +++++----- .github/ISSUE_TEMPLATE/1_feature_request.yml | 31 +++++++++++-------- .github/ISSUE_TEMPLATE/2_question.yml | 20 ++++++------ 6 files changed, 63 insertions(+), 47 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/#0_bug_report.yml b/.github/ISSUE_TEMPLATE/#0_bug_report.yml index e94faa9b..9e33cc57 100644 --- a/.github/ISSUE_TEMPLATE/#0_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/#0_bug_report.yml @@ -1,4 +1,4 @@ -name: 🐛 错误报告 +name: 🐛 错误报告 (中文) description: 创建一个报告以帮助我们改进 title: '[错误]: ' labels: ['bug'] @@ -7,17 +7,20 @@ body: attributes: value: | 感谢您花时间填写此错误报告! + 在提交此问题之前,请确保您已经了解了[常见问题](https://docs.cherry-ai.com/question-contact/questions)和[知识科普](https://docs.cherry-ai.com/question-contact/knowledge) - type: checkboxes id: checklist attributes: - label: Issue 检查清单 + label: 提交前检查 description: | 在提交 Issue 前请确保您已经完成了以下所有步骤 options: - - label: 我已经查看了置顶 Issue 并搜索了现有的 Issue,但没有找到类似的问题。 + - label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决。 required: true - - label: 正确填写了 Issue 标题。 + - label: 我已经查看了置顶 Issue 并搜索了现有的 [开放Issue](https://github.com/CherryHQ/cherry-studio/issues)和[已关闭Issue](https://github.com/CherryHQ/cherry-studio/issues?q=is%3Aissue%20state%3Aclosed%20),没有找到类似的问题。 + required: true + - label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等。 required: true - type: dropdown @@ -45,7 +48,7 @@ body: id: description attributes: label: 错误描述 - description: 清晰简洁地描述错误是什么 + description: 描述问题时请尽可能详细 placeholder: 告诉我们发生了什么... validations: required: true @@ -54,7 +57,7 @@ body: id: reproduction attributes: label: 重现步骤 - description: 重现行为的步骤 + description: 提供详细的重现步骤,以便于我们可以准确地重现问题 placeholder: | 1. 转到 '...' 2. 点击 '....' @@ -82,4 +85,4 @@ body: id: additional attributes: label: 附加信息 - description: 在此添加有关问题的任何其他上下文 + description: 任何能让我们对你所遇到的问题有更多了解的东西 diff --git a/.github/ISSUE_TEMPLATE/#1_feature_request.yml b/.github/ISSUE_TEMPLATE/#1_feature_request.yml index 5c26d7d8..00aae56f 100644 --- a/.github/ISSUE_TEMPLATE/#1_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/#1_feature_request.yml @@ -1,4 +1,4 @@ -name: 💡 功能建议 +name: 💡 功能建议 (中文) description: 为项目提出新的想法 title: '[功能]: ' labels: ['enhancement'] @@ -7,17 +7,22 @@ body: attributes: value: | 感谢您花时间提出新的功能建议! + 在提交此问题之前,请确保您已经了解了[项目规划](https://docs.cherry-ai.com/cherrystudio/planning)和[功能介绍](https://docs.cherry-ai.com/cherrystudio/preview) - type: checkboxes id: checklist attributes: - label: Issue 检查清单 + label: 提交前检查 description: | 在提交 Issue 前请确保您已经完成了以下所有步骤 options: - - label: 我已经查看了置顶 Issue 并搜索了现有的 Issue,但没有找到类似的问题。 + - label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决。 required: true - - label: 正确填写了 Issue 标题。 + - label: 我已经查看了置顶 Issue 并搜索了现有的 [开放Issue](https://github.com/CherryHQ/cherry-studio/issues)和[已关闭Issue](https://github.com/CherryHQ/cherry-studio/issues?q=is%3Aissue%20state%3Aclosed%20),没有找到类似的建议。 + required: true + - label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等。 + required: true + - label: 最新的 Cherry Studio 版本没有实现我所提出的功能。 required: true - type: dropdown @@ -44,7 +49,7 @@ body: - type: textarea id: problem attributes: - label: 您的功能建议是否与某个问题相关? + label: 您的功能建议是否与某个问题/issue相关? description: 请简明扼要地描述您遇到的问题 placeholder: 我总是感到沮丧,因为... validations: diff --git a/.github/ISSUE_TEMPLATE/#2_question.yml b/.github/ISSUE_TEMPLATE/#2_question.yml index faff6806..f3566ce6 100644 --- a/.github/ISSUE_TEMPLATE/#2_question.yml +++ b/.github/ISSUE_TEMPLATE/#2_question.yml @@ -1,6 +1,6 @@ -name: ❓ 提问 -description: 提出一个问题或寻求帮助 -title: '[问题]: ' +name: ❓ 讨论 & 提问 (中文) +description: 寻求帮助、讨论问题、提出疑问等... +title: '[讨论]: ' labels: ['question'] body: - type: markdown @@ -15,9 +15,9 @@ body: description: | 在提交 Issue 前请确保您已经完成了以下所有步骤 options: - - label: 我已经查看了置顶 Issue 并搜索了现有的 Issue,但没有找到类似的问题。 + - label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决。 required: true - - label: 正确填写了 Issue 标题。 + - label: 我确认自己需要的是提出问题并且讨论问题,而不是 Bug 反馈或需求建议。 required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/0_bug_report.yml b/.github/ISSUE_TEMPLATE/0_bug_report.yml index 268f5a98..13a08edd 100644 --- a/.github/ISSUE_TEMPLATE/0_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/0_bug_report.yml @@ -1,4 +1,4 @@ -name: 🐛 Bug Report +name: 🐛 Bug Report (English) description: Create a report to help us improve title: '[Bug]: ' labels: ['bug'] @@ -6,7 +6,8 @@ body: - type: markdown attributes: value: | - Thanks for taking the time to fill out this bug report! + Thank you for taking the time to fill out this bug report! + Before submitting this issue, please make sure that you have understood the [FAQ](https://docs.cherry-ai.com/question-contact/questions) and [Knowledge Science](https://docs.cherry-ai.com/question-contact/knowledge) - type: checkboxes id: checklist @@ -15,9 +16,11 @@ body: description: | Before submitting an issue, please make sure you have completed the following steps options: - - label: I have viewed the pinned issues and searched existing issues but couldn't find anything similar. + - label: I understand that issues are for feedback and problem solving, not for complaining in the comment section, and will provide as much information as possible to help solve the problem. required: true - - label: I have filled out the issue title correctly. + - label: I've looked at pinned issues and searched for existing [Open Issues](https://github.com/CherryHQ/cherry-studio/issues) and [Closed Issues]( https://github.com/CherryHQ/cherry-studio/issues?q=is%3Aissue%20state%3Aclosed%20), no similar issue was found. + required: true + - label: I've filled in short, clear headings so that developers can quickly identify a rough idea of what to expect when flipping through the list of issues. And not "a suggestion", "stuck", etc. required: true - type: dropdown @@ -45,7 +48,7 @@ body: id: description attributes: label: Bug Description - description: A clear and concise description of what the bug is + description: Please be as detailed as possible when describing the problem placeholder: Tell us what happened... validations: required: true @@ -54,7 +57,7 @@ body: id: reproduction attributes: label: Steps To Reproduce - description: Steps to reproduce the behavior + description: Provide detailed steps to reproduce the issue so that our developers can reproduce the issue accurately placeholder: | 1. Go to '...' 2. Click on '....' @@ -82,4 +85,4 @@ body: id: additional attributes: label: Additional Context - description: Add any other context about the problem here + description: Anything that gives us a better understanding of the problem you're experiencing diff --git a/.github/ISSUE_TEMPLATE/1_feature_request.yml b/.github/ISSUE_TEMPLATE/1_feature_request.yml index be3beff4..e0fe9836 100644 --- a/.github/ISSUE_TEMPLATE/1_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/1_feature_request.yml @@ -1,4 +1,4 @@ -name: 💡 Feature Request +name: 💡 Feature Request (English) description: Suggest an idea for this project title: '[Feature]: ' labels: ['enhancement'] @@ -6,7 +6,8 @@ body: - type: markdown attributes: value: | - Thanks for taking the time to suggest a new feature! + Thank you for taking the time to submit a feature request! + Before submitting this issue, please make sure you have reviewed the [Project Roadmap](https://docs.cherry-ai.com/cherrystudio/planning) and the [Feature Overview](https://docs.cherry-ai.com/cherrystudio/preview). - type: checkboxes id: checklist @@ -15,9 +16,13 @@ body: description: | Before submitting an issue, please make sure you have completed the following steps options: - - label: I have viewed the pinned issues and searched existing issues but couldn't find anything similar. + - label: I understand that issues are for reporting problems and requesting features, not for off-topic comments, and I will provide as much detail as possible to help resolve the issue. required: true - - label: I have filled out the issue title correctly. + - label: I have checked the pinned issues and searched through the existing [open issues](https://github.com/CherryHQ/cherry-studio/issues) and [closed issues](https://github.com/CherryHQ/cherry-studio/issues?q=is%3Aissue%20state%3Aclosed) and did not find a similar suggestion. + required: true + - label: I have provided a short and descriptive title so that developers can quickly understand the issue when browsing the issue list, rather than vague titles like "A suggestion" or "Stuck." + required: true + - label: The latest version of Cherry Studio does not include the feature I am suggesting. required: true - type: dropdown @@ -44,28 +49,28 @@ body: - type: textarea id: problem attributes: - label: Is your feature request related to a problem? - description: A clear and concise description of what the problem is - placeholder: I'm always frustrated when... + label: Is your feature request related to an existing issue? + description: Please briefly describe the problem you are experiencing. + placeholder: I often feel frustrated because... validations: required: true - type: textarea id: solution attributes: - label: Describe the solution you'd like - description: A clear and concise description of what you want to happen + label: Desired Solution + description: Please briefly describe what you would like to happen. validations: required: true - type: textarea id: alternatives attributes: - label: Describe alternatives you've considered - description: A clear and concise description of any alternative solutions or features you've considered + label: Alternative Solutions + description: Please briefly describe any alternative solutions or features you have considered. - type: textarea id: additional attributes: - label: Additional Context - description: Add any other context or screenshots about the feature request here + label: Additional Information + description: Add any other context or screenshots related to your feature request. diff --git a/.github/ISSUE_TEMPLATE/2_question.yml b/.github/ISSUE_TEMPLATE/2_question.yml index 20a751ac..d191daf7 100644 --- a/.github/ISSUE_TEMPLATE/2_question.yml +++ b/.github/ISSUE_TEMPLATE/2_question.yml @@ -1,12 +1,12 @@ -name: ❓ Question -description: Ask a question or seek help -title: '[Question]: ' +name: ❓ Discussion & Questions +description: Seeking help, discussing issues, asking questions, etc... +title: '[Discussion]: ' labels: ['question'] body: - type: markdown attributes: value: | - Thanks for asking a question! Please provide as much detail as possible so we can better assist you. + Thank you for your question! Please describe your issue in as much detail as possible so that we can better assist you. - type: checkboxes id: checklist @@ -15,9 +15,9 @@ body: description: | Before submitting an issue, please make sure you have completed the following steps options: - - label: I have viewed the pinned issues and searched existing issues but couldn't find anything similar. + - label: I understand that issues are meant for feedback and problem-solving, not for venting, and I will provide as much detail as possible to help resolve the issue. required: true - - label: I have filled out the issue title correctly. + - label: I confirm that I am here to ask questions and discuss issues, not to report bugs or request features. required: true - type: dropdown @@ -45,8 +45,8 @@ body: id: question attributes: label: Your Question - description: Please describe your question in detail - placeholder: Please explain your question as clearly as possible... + description: Please describe your issue in detail. + placeholder: Please explain your issue as clearly as possible... validations: required: true @@ -68,9 +68,9 @@ body: id: priority attributes: label: Priority - description: How urgent is this question for you? + description: How urgent is this issue for you? options: - - Low (Can wait) + - Low (Review when available) - Medium (Would like a response soon) - High (Blocking progress) validations: From 1a2861e81ae75fcead31f92ac3c4bfaa2da6d61b Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 02:04:09 +0800 Subject: [PATCH 02/39] fix: Fix the miniapp sorting problem, resolve #1725 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复小程序拖动排序不生效的问题 - 修复小程序拖动排序时列表滚动排序不生效的问题 --- .../DisplaySettings/MiniAppIconsManager.tsx | 134 +++++++----------- 1 file changed, 54 insertions(+), 80 deletions(-) diff --git a/src/renderer/src/pages/settings/DisplaySettings/MiniAppIconsManager.tsx b/src/renderer/src/pages/settings/DisplaySettings/MiniAppIconsManager.tsx index e2d5dae7..1fad12fb 100644 --- a/src/renderer/src/pages/settings/DisplaySettings/MiniAppIconsManager.tsx +++ b/src/renderer/src/pages/settings/DisplaySettings/MiniAppIconsManager.tsx @@ -23,50 +23,6 @@ interface MiniAppManagerProps { type ListType = 'visible' | 'disabled' -// 添加 reorderLists 函数的接口定义 -interface ReorderListsParams { - sourceList: MinAppType[] - destList: MinAppType[] - sourceIndex: number - destIndex: number - isSameList: boolean -} - -interface ReorderListsResult { - sourceList: MinAppType[] - destList: MinAppType[] -} - -// 添加 reorderLists 函数 -const reorderLists = ({ - sourceList, - destList, - sourceIndex, - destIndex, - isSameList -}: ReorderListsParams): ReorderListsResult => { - if (isSameList) { - // 在同一列表内重新排序 - const newList = [...sourceList] - const [removed] = newList.splice(sourceIndex, 1) - newList.splice(destIndex, 0, removed) - return { - sourceList: newList, - destList: destList - } - } else { - // 在不同列表间移动 - const newSourceList = [...sourceList] - const [removed] = newSourceList.splice(sourceIndex, 1) - const newDestList = [...destList] - newDestList.splice(destIndex, 0, removed) - return { - sourceList: newSourceList, - destList: newDestList - } - } -} - const MiniAppIconsManager: FC = ({ visibleMiniApps, disabledMiniApps, @@ -92,25 +48,35 @@ const MiniAppIconsManager: FC = ({ if (!result.destination) return const { source, destination } = result - const sourceList = source.droppableId as ListType - const destList = destination.droppableId as ListType - if (source.droppableId === destination.droppableId) return + if (source.droppableId === destination.droppableId) { + // 在同一列表内重新排序 + const list = source.droppableId === 'visible' ? [...visibleMiniApps] : [...disabledMiniApps] + const [removed] = list.splice(source.index, 1) + list.splice(destination.index, 0, removed) - const newLists = reorderLists({ - sourceList: sourceList === 'visible' ? visibleMiniApps : disabledMiniApps, - destList: destList === 'visible' ? visibleMiniApps : disabledMiniApps, - sourceIndex: source.index, - destIndex: destination.index, - isSameList: sourceList === destList - }) + if (source.droppableId === 'visible') { + handleListUpdate(list, disabledMiniApps) + } else { + handleListUpdate(visibleMiniApps, list) + } + return + } - handleListUpdate( - sourceList === 'visible' ? newLists.sourceList : newLists.destList, - sourceList === 'visible' ? newLists.destList : newLists.sourceList - ) + // 在不同列表间移动 + const sourceList = source.droppableId === 'visible' ? [...visibleMiniApps] : [...disabledMiniApps] + const destList = destination.droppableId === 'visible' ? [...visibleMiniApps] : [...disabledMiniApps] + + const [removed] = sourceList.splice(source.index, 1) + const targetList = destList.filter((app) => app.id !== removed.id) + targetList.splice(destination.index, 0, removed) + + const newVisibleMiniApps = destination.droppableId === 'visible' ? targetList : sourceList + const newDisabledMiniApps = destination.droppableId === 'disabled' ? targetList : sourceList + + handleListUpdate(newVisibleMiniApps, newDisabledMiniApps) }, - [disabledMiniApps, handleListUpdate, visibleMiniApps] + [visibleMiniApps, disabledMiniApps, handleListUpdate] ) const onMoveMiniApp = useCallback( @@ -153,17 +119,15 @@ const MiniAppIconsManager: FC = ({ {(provided: DroppableProvided) => ( - - {(listType === 'visible' ? visibleMiniApps : disabledMiniApps).map((program, index) => ( - - {(provided: DraggableProvided) => renderProgramItem(program, provided, listType)} - - ))} - {disabledMiniApps.length === 0 && listType === 'disabled' && ( - {t('settings.display.minApp.empty')} - )} - {provided.placeholder} - + {(listType === 'visible' ? visibleMiniApps : disabledMiniApps).map((program, index) => ( + + {(provided: DraggableProvided) => renderProgramItem(program, provided, listType)} + + ))} + {disabledMiniApps.length === 0 && listType === 'disabled' && ( + {t('settings.display.minApp.empty')} + )} + {provided.placeholder} )} @@ -181,12 +145,6 @@ const AppLogo = styled.img` object-fit: contain; ` -const ScrollContainer = styled.div` - overflow-y: auto; - height: 100%; - padding-right: 5px; -` - const ProgramSection = styled.div` display: flex; gap: 20px; @@ -208,13 +166,29 @@ const ProgramList = styled.div` height: 365px; min-height: 365px; padding: 10px; - padding-right: 5px; background: var(--color-background-soft); border-radius: 8px; border: 1px solid var(--color-border); - display: flex; - flex-direction: column; - overflow-y: hidden; + overflow-y: auto; + + scroll-behavior: smooth; + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: var(--color-border); + border-radius: 3px; + } + + &::-webkit-scrollbar-thumb:hover { + background: var(--color-border-hover); + } ` const ProgramItem = styled.div` From 30e8cef9cc291d0e522b0c7357d9da7d4ca31813 Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 02:36:49 +0800 Subject: [PATCH 03/39] fix: correction of the capitalization of Perplexity names --- src/renderer/src/config/minapps.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/config/minapps.ts b/src/renderer/src/config/minapps.ts index 186b66f5..e7ab6c71 100644 --- a/src/renderer/src/config/minapps.ts +++ b/src/renderer/src/config/minapps.ts @@ -3,6 +3,7 @@ import AIStudioLogo from '@renderer/assets/images/apps/aistudio.svg?url' import BaiduAiAppLogo from '@renderer/assets/images/apps/baidu-ai.png?url' import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp?url' import BoltAppLogo from '@renderer/assets/images/apps/bolt.svg?url' +import CozeAppLogo from '@renderer/assets/images/apps/coze.webp?url' import DevvAppLogo from '@renderer/assets/images/apps/devv.png?url' import DoubaoAppLogo from '@renderer/assets/images/apps/doubao.png?url' import DuckDuckGoAppLogo from '@renderer/assets/images/apps/duckduckgo.webp?url' @@ -18,6 +19,7 @@ import KimiAppLogo from '@renderer/assets/images/apps/kimi.jpg?url' import MetasoAppLogo from '@renderer/assets/images/apps/metaso.webp?url' import NamiAiLogo from '@renderer/assets/images/apps/nm.png?url' import NamiAiSearchLogo from '@renderer/assets/images/apps/nm-search.webp?url' +import NotebookLMAppLogo from '@renderer/assets/images/apps/notebooklm.svg?url' import PerplexityAppLogo from '@renderer/assets/images/apps/perplexity.webp?url' import PoeAppLogo from '@renderer/assets/images/apps/poe.webp?url' import ZhipuProviderLogo from '@renderer/assets/images/apps/qingyan.png?url' @@ -29,10 +31,8 @@ import TiangongAiLogo from '@renderer/assets/images/apps/tiangong.png?url' import WanZhiAppLogo from '@renderer/assets/images/apps/wanzhi.jpg?url' import XiaoYiAppLogo from '@renderer/assets/images/apps/xiaoyi.webp?url' import TencentYuanbaoAppLogo from '@renderer/assets/images/apps/yuanbao.png?url' -import NotebookLMAppLogo from '@renderer/assets/images/apps/notebooklm.svg?url' import YuewenAppLogo from '@renderer/assets/images/apps/yuewen.png?url' import ZhihuAppLogo from '@renderer/assets/images/apps/zhihu.png?url' -import CozeAppLogo from '@renderer/assets/images/apps/coze.webp?url' import ClaudeAppLogo from '@renderer/assets/images/models/claude.png?url' import HailuoModelLogo from '@renderer/assets/images/models/hailuo.png?url' import QwenModelLogo from '@renderer/assets/images/models/qwen.png?url' @@ -171,7 +171,7 @@ export const DEFAULT_MIN_APPS: MinAppType[] = [ }, { id: 'perplexity', - name: 'perplexity', + name: 'Perplexity', logo: PerplexityAppLogo, url: 'https://www.perplexity.ai/' }, @@ -306,7 +306,7 @@ export const DEFAULT_MIN_APPS: MinAppType[] = [ id: 'notebooklm', name: 'NotebookLM', logo: NotebookLMAppLogo, - url: 'https://notebooklm.google.com/', + url: 'https://notebooklm.google.com/' }, { id: 'coze', From fa8bf61532fdc5a1104d999c71c773b9f227f23c Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 03:48:42 +0800 Subject: [PATCH 04/39] fix: sidebar navigation and active state handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 当固定在侧边栏的小程序被打开时,对应图标显示为被选中 - 修复点击两次主题切换按钮会导致当前 Webview 被错误关闭的问题 - 修复当 Webview 处于打开状态,点击侧边栏按钮无法立即跳转到对应界面的问题 - 修复打开帮助文档,其按钮没有显示为被选中的问题 - 修复在设置界面时打开帮助文档,设置按钮继续显示为被选中的问题 --- src/renderer/src/components/app/Sidebar.tsx | 33 ++++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index 355a30a5..94cd5610 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -77,9 +77,11 @@ const Sidebar: FC = () => { )} - + - + @@ -93,8 +95,14 @@ const Sidebar: FC = () => { - to(isLocalAi ? '/settings/assistant' : '/settings/provider')}> - + { + if (minappShow) { + await MinApp.close() + } + await to(isLocalAi ? '/settings/assistant' : '/settings/provider') + }}> + @@ -108,10 +116,11 @@ const MainMenus: FC = () => { const { t } = useTranslation() const { pathname } = useLocation() const { sidebarIcons } = useSettings() + const { minappShow } = useRuntime() const navigate = useNavigate() - const isRoute = (path: string): string => (pathname === path ? 'active' : '') - const isRoutes = (path: string): string => (pathname.startsWith(path) ? 'active' : '') + const isRoute = (path: string): string => (pathname === path && !minappShow ? 'active' : '') + const isRoutes = (path: string): string => (pathname.startsWith(path) && !minappShow ? 'active' : '') const iconMap = { assistants: , @@ -139,7 +148,13 @@ const MainMenus: FC = () => { return ( - navigate(path)}> + { + if (minappShow) { + await MinApp.close() + } + navigate(path) + }}> {iconMap[icon]} @@ -150,6 +165,7 @@ const MainMenus: FC = () => { const PinnedApps: FC = () => { const { pinned, updatePinnedMinapps } = useMinapps() const { t } = useTranslation() + const { minappShow } = useRuntime() return ( @@ -164,11 +180,12 @@ const PinnedApps: FC = () => { } } ] + const isActive = minappShow && MinApp.app?.id === app.id return ( - MinApp.start(app)}> + MinApp.start(app)} className={isActive ? 'active' : ''}> From 7764507d74aa5b108f8048c051d4cbfb8b1ab019 Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 03:25:40 +0800 Subject: [PATCH 05/39] feat: Expand reasoning model regex to include 'thinking' keyword --- src/renderer/src/config/models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 9adf43f8..fc338076 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -161,7 +161,7 @@ export const VISION_REGEX = new RegExp( ) export const TEXT_TO_IMAGE_REGEX = /flux|diffusion|stabilityai|sd-|dall|cogview|janus/i -export const REASONING_REGEX = /^(o\d+(?:-[\w-]+)?|.*\breasoner\b.*|.*-[rR]\d+.*)$/i +export const REASONING_REGEX = /^(o\d+(?:-[\w-]+)?|.*\b(?:reasoner|thinking)\b.*|.*-[rR]\d+.*)$/i export const EMBEDDING_REGEX = /(?:^text-|embed|rerank|davinci|babbage|bge-|e5-|LLM2Vec|retrieval|uae-|gte-|jina-clip|jina-embeddings)/i From 574d02a8c9bb5b9e500949dc4ba9495432c5ec88 Mon Sep 17 00:00:00 2001 From: Wenwei Lin <75592450+wenwei-lin@users.noreply.github.com> Date: Mon, 17 Feb 2025 08:25:07 +0800 Subject: [PATCH 06/39] feat: support json and draftsExport file in knowledge base (#1717) --- packages/shared/config/constant.ts | 1 + src/main/loader/draftsExportLoader.ts | 22 ++++++++++++++ src/main/loader/index.ts | 29 +++++++++++++++++-- .../src/pages/knowledge/KnowledgeContent.tsx | 4 +-- 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/main/loader/draftsExportLoader.ts diff --git a/packages/shared/config/constant.ts b/packages/shared/config/constant.ts index c39b1370..1c7b5758 100644 --- a/packages/shared/config/constant.ts +++ b/packages/shared/config/constant.ts @@ -2,6 +2,7 @@ export const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'] export const videoExts = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv'] export const audioExts = ['.mp3', '.wav', '.ogg', '.flac', '.aac'] export const documentExts = ['.pdf', '.docx', '.pptx', '.xlsx', '.odt', '.odp', '.ods'] +export const thirdPartyApplicationExts = ['.draftsExport'] export const bookExts = ['.epub'] export const textExts = [ '.txt', // 普通文本文件 diff --git a/src/main/loader/draftsExportLoader.ts b/src/main/loader/draftsExportLoader.ts new file mode 100644 index 00000000..4ad1806b --- /dev/null +++ b/src/main/loader/draftsExportLoader.ts @@ -0,0 +1,22 @@ +import * as fs from 'node:fs' + +import { JsonLoader } from '@llm-tools/embedjs' + +/** + * Drafts 应用导出的笔记文件加载器 + * 原始文件是一个 JSON 数组。每条笔记只保留 content、tags、modified_at 三个字段 + */ +export class DraftsExportLoader extends JsonLoader { + constructor(filePath: string) { + const fileContent = fs.readFileSync(filePath, 'utf-8') + const rawJson = JSON.parse(fileContent) as any[] + const json = rawJson.map((item) => { + return { + content: item.content?.replace(/\n/g, '
'), + tags: item.tags, + modified_at: item.created_at + } + }) + super({ object: json }) + } +} diff --git a/src/main/loader/index.ts b/src/main/loader/index.ts index 3cc1d1af..f23c58b1 100644 --- a/src/main/loader/index.ts +++ b/src/main/loader/index.ts @@ -1,17 +1,18 @@ import * as fs from 'node:fs' -import { LocalPathLoader, RAGApplication, TextLoader } from '@llm-tools/embedjs' +import { JsonLoader, LocalPathLoader, RAGApplication, TextLoader } from '@llm-tools/embedjs' import type { AddLoaderReturn } from '@llm-tools/embedjs-interfaces' import { WebLoader } from '@llm-tools/embedjs-loader-web' import { LoaderReturn } from '@shared/config/types' import { FileType, KnowledgeBaseParams } from '@types' import Logger from 'electron-log' +import { DraftsExportLoader } from './draftsExportLoader' import { EpubLoader } from './epubLoader' import { OdLoader, OdType } from './odLoader' // embedjs内置loader类型 -const commonExts = ['.pdf', '.csv', '.json', '.docx', '.pptx', '.xlsx', '.md'] +const commonExts = ['.pdf', '.csv', '.docx', '.pptx', '.xlsx', '.md'] export async function addOdLoader( ragApplication: RAGApplication, @@ -89,7 +90,19 @@ export async function addFileLoader( } as LoaderReturn } + // DraftsExport类型 (file.ext会自动转换成小写) + if (['.draftsexport'].includes(file.ext)) { + const loaderReturn = await ragApplication.addLoader(new DraftsExportLoader(file.path) as any, forceReload) + return { + entriesAdded: loaderReturn.entriesAdded, + uniqueId: loaderReturn.uniqueId, + uniqueIds: [loaderReturn.uniqueId], + loaderType: loaderReturn.loaderType + } + } + const fileContent = fs.readFileSync(file.path, 'utf-8') + // HTML类型 if (['.html', '.htm'].includes(file.ext)) { const loaderReturn = await ragApplication.addLoader( @@ -108,6 +121,18 @@ export async function addFileLoader( } } + // JSON类型 + if (['.json'].includes(file.ext)) { + const jsonObject = JSON.parse(fileContent) + const loaderReturn = await ragApplication.addLoader(new JsonLoader({ object: jsonObject })) + return { + entriesAdded: loaderReturn.entriesAdded, + uniqueId: loaderReturn.uniqueId, + uniqueIds: [loaderReturn.uniqueId], + loaderType: loaderReturn.loaderType + } + } + // 文本类型 const loaderReturn = await ragApplication.addLoader( new TextLoader({ text: fileContent, chunkSize: base.chunkSize, chunkOverlap: base.chunkOverlap }) as any, diff --git a/src/renderer/src/pages/knowledge/KnowledgeContent.tsx b/src/renderer/src/pages/knowledge/KnowledgeContent.tsx index 41bda2a9..f248f736 100644 --- a/src/renderer/src/pages/knowledge/KnowledgeContent.tsx +++ b/src/renderer/src/pages/knowledge/KnowledgeContent.tsx @@ -18,7 +18,7 @@ import { useKnowledge } from '@renderer/hooks/useKnowledge' import FileManager from '@renderer/services/FileManager' import { getProviderName } from '@renderer/services/ProviderService' import { FileType, FileTypes, KnowledgeBase } from '@renderer/types' -import { bookExts, documentExts, textExts } from '@shared/config/constant' +import { bookExts, documentExts, textExts, thirdPartyApplicationExts } from '@shared/config/constant' import { Alert, Button, Card, Divider, message, Tag, Tooltip, Typography, Upload } from 'antd' import { FC } from 'react' import { useTranslation } from 'react-i18next' @@ -35,7 +35,7 @@ interface KnowledgeContentProps { selectedBase: KnowledgeBase } -const fileTypes = [...bookExts, ...documentExts, ...textExts] +const fileTypes = [...bookExts, ...thirdPartyApplicationExts, ...documentExts, ...textExts] const KnowledgeContent: FC = ({ selectedBase }) => { const { t } = useTranslation() From 642ce160a1c8c308689886f08e97ee99e149d35c Mon Sep 17 00:00:00 2001 From: Shelly <49258298+duanyongcheng@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:47:01 +0800 Subject: [PATCH 07/39] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=90=8C?= =?UTF-8?q?=E5=90=8D=E6=A8=A1=E5=9E=8B=E9=80=89=E6=8B=A9=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20(#1772)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 同名模型显示的供应商名称问题 2. 同名模型不同供应商不能被同时选择 Co-authored-by: duanyongcheng --- .../src/pages/home/Inputbar/MentionModelsButton.tsx | 4 ++-- .../src/pages/home/Inputbar/MentionModelsInput.tsx | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx b/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx index 7a22c599..e408a052 100644 --- a/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx +++ b/src/renderer/src/pages/home/Inputbar/MentionModelsButton.tsx @@ -44,7 +44,7 @@ const MentionModelsButton: FC = ({ mentionModels, onMentionModel: onSelec const handleModelSelect = (model: Model) => { // Check if model is already selected - if (mentionModels.some((selected) => selected.id === model.id)) { + if (mentionModels.some((selected) => getModelUniqId(selected) === getModelUniqId(model))) { return } onSelect(model) @@ -209,7 +209,7 @@ const MentionModelsButton: FC = ({ mentionModels, onMentionModel: onSelec e.preventDefault() if (selectedIndex >= 0 && selectedIndex < flatModelItems.length) { const selectedModel = flatModelItems[selectedIndex].model - if (!mentionModels.some((selected) => selected.id === selectedModel.id)) { + if (!mentionModels.some((selected) => getModelUniqId(selected) === getModelUniqId(selectedModel))) { flatModelItems[selectedIndex].onClick() } setIsOpen(false) diff --git a/src/renderer/src/pages/home/Inputbar/MentionModelsInput.tsx b/src/renderer/src/pages/home/Inputbar/MentionModelsInput.tsx index 9c91d97c..b31b5d76 100644 --- a/src/renderer/src/pages/home/Inputbar/MentionModelsInput.tsx +++ b/src/renderer/src/pages/home/Inputbar/MentionModelsInput.tsx @@ -1,4 +1,5 @@ import { useProviders } from '@renderer/hooks/useProvider' +import { getModelUniqId } from '@renderer/services/ModelService' import { Model } from '@renderer/types' import { Flex, Tag } from 'antd' import { FC } from 'react' @@ -13,14 +14,19 @@ const MentionModelsInput: FC<{ const { t } = useTranslation() const getProviderName = (model: Model) => { - const provider = providers.find((p) => p.models?.some((m) => m.id === model.id)) + const provider = providers.find((p) => p.id === model?.provider) return provider ? (provider.isSystem ? t(`provider.${provider.id}`) : provider.name) : '' } return ( {selectedModels.map((model) => ( - onRemoveModel(model)}> + onRemoveModel(model)}> @{model.name} ({getProviderName(model)}) ))} From d175212d9a008cb86969d7bfcdec75997f599316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George=C2=B7Dong?= <98630204+GeorgeDong32@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:28:17 +0800 Subject: [PATCH 08/39] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E5=8A=A9=E6=89=8B=E6=97=B6=E6=97=A0=E6=B3=95=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E5=88=87=E6=8D=A2=E5=88=B0=E5=8A=A9=E6=89=8B=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=A8=A1=E5=9E=8B=E7=9A=84=E9=97=AE=E9=A2=98=20(#1776?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/hooks/useAssistant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/hooks/useAssistant.ts b/src/renderer/src/hooks/useAssistant.ts index 1074569a..c89c1dd3 100644 --- a/src/renderer/src/hooks/useAssistant.ts +++ b/src/renderer/src/hooks/useAssistant.ts @@ -44,7 +44,7 @@ export function useAssistant(id: string) { return { assistant, - model: assistant?.model ?? defaultModel, + model: assistant?.model ?? assistant?.defaultModel ?? defaultModel, addTopic: (topic: Topic) => dispatch(addTopic({ assistantId: assistant.id, topic })), removeTopic: (topic: Topic) => { TopicManager.removeTopic(topic.id) From e0eca970535805012b2561e170f9ceb9e64c64cf Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 11:46:04 +0800 Subject: [PATCH 09/39] fix: update Baidu API key URL in provider configuration, resolve #1794 --- src/renderer/src/config/providers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/config/providers.ts b/src/renderer/src/config/providers.ts index e6bbd0a3..08de2c94 100644 --- a/src/renderer/src/config/providers.ts +++ b/src/renderer/src/config/providers.ts @@ -526,7 +526,7 @@ export const PROVIDER_CONFIG = { }, websites: { official: 'https://cloud.baidu.com/', - apiKey: 'https://cloud.baidu.com/console/qianfan/apikey', + apiKey: 'https://console.bce.baidu.com/iam/#/iam/apikey/list', docs: 'https://cloud.baidu.com/doc/index.html', models: 'https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu' } From ab5e830ed14ee4e38f688259e2643f1f9f0dc479 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Mon, 17 Feb 2025 12:01:50 +0800 Subject: [PATCH 10/39] docs: remove Chinese issue templates for bug reports, feature requests, and questions --- .github/ISSUE_TEMPLATE/0_bug_report.yml | 6 +++--- .github/ISSUE_TEMPLATE/1_feature_request.yml | 2 +- .github/{ISSUE_TEMPLATE => issues}/#0_bug_report.yml | 0 .github/{ISSUE_TEMPLATE => issues}/#1_feature_request.yml | 0 .github/{ISSUE_TEMPLATE => issues}/#2_question.yml | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename .github/{ISSUE_TEMPLATE => issues}/#0_bug_report.yml (100%) rename .github/{ISSUE_TEMPLATE => issues}/#1_feature_request.yml (100%) rename .github/{ISSUE_TEMPLATE => issues}/#2_question.yml (100%) diff --git a/.github/ISSUE_TEMPLATE/0_bug_report.yml b/.github/ISSUE_TEMPLATE/0_bug_report.yml index 13a08edd..3b0515d5 100644 --- a/.github/ISSUE_TEMPLATE/0_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/0_bug_report.yml @@ -1,4 +1,4 @@ -name: 🐛 Bug Report (English) +name: 🐛 Bug Report description: Create a report to help us improve title: '[Bug]: ' labels: ['bug'] @@ -6,8 +6,8 @@ body: - type: markdown attributes: value: | - Thank you for taking the time to fill out this bug report! - Before submitting this issue, please make sure that you have understood the [FAQ](https://docs.cherry-ai.com/question-contact/questions) and [Knowledge Science](https://docs.cherry-ai.com/question-contact/knowledge) + Thank you for taking the time to fill out this bug report! + Before submitting this issue, please make sure that you have understood the [FAQ](https://docs.cherry-ai.com/question-contact/questions) and [Knowledge Science](https://docs.cherry-ai.com/question-contact/knowledge) - type: checkboxes id: checklist diff --git a/.github/ISSUE_TEMPLATE/1_feature_request.yml b/.github/ISSUE_TEMPLATE/1_feature_request.yml index e0fe9836..831b5f10 100644 --- a/.github/ISSUE_TEMPLATE/1_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/1_feature_request.yml @@ -1,4 +1,4 @@ -name: 💡 Feature Request (English) +name: 💡 Feature Request description: Suggest an idea for this project title: '[Feature]: ' labels: ['enhancement'] diff --git a/.github/ISSUE_TEMPLATE/#0_bug_report.yml b/.github/issues/#0_bug_report.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/#0_bug_report.yml rename to .github/issues/#0_bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/#1_feature_request.yml b/.github/issues/#1_feature_request.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/#1_feature_request.yml rename to .github/issues/#1_feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/#2_question.yml b/.github/issues/#2_question.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/#2_question.yml rename to .github/issues/#2_question.yml From b49d80b78dcf5e56712858280ca21b701d9d66e5 Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 15:57:41 +0800 Subject: [PATCH 11/39] fix: Clicking the help button always opens a new webview (cherry picked from commit 4939afafabcbfb294f00d21053939cad8238731e) --- src/renderer/src/components/app/Sidebar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index 94cd5610..053913c2 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -50,6 +50,7 @@ const Sidebar: FC = () => { const onOpenDocs = () => { MinApp.start({ + id: 'docs', name: t('docs.title'), url: 'https://docs.cherry-ai.com/', logo: AppLogo From 2076e6f99872089eee63002679dd0289cc689dff Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 15:21:13 +0800 Subject: [PATCH 12/39] fix: open current webview URL when launching external link --- src/renderer/src/components/MinApp/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/components/MinApp/index.tsx b/src/renderer/src/components/MinApp/index.tsx index 5b66329c..3cb67076 100644 --- a/src/renderer/src/components/MinApp/index.tsx +++ b/src/renderer/src/components/MinApp/index.tsx @@ -49,7 +49,10 @@ const PopupContainer: React.FC = ({ app, resolve }) => { } const onOpenLink = () => { - window.api.openWebsite(app.url) + if (webviewRef.current) { + const currentUrl = webviewRef.current.getURL() + window.api.openWebsite(currentUrl) + } } const onTogglePin = () => { From 0c0ccf3d11c58e9a098a2236121a726976526240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A6=96=E9=83=BD=E7=88=B1=E6=8A=A4=E5=8A=A8=E7=89=A9?= =?UTF-8?q?=E5=8D=8F=E4=BC=9A?= <87239270+1355873789@users.noreply.github.com> Date: Mon, 17 Feb 2025 14:01:02 +0800 Subject: [PATCH 13/39] update provider info --- src/renderer/src/config/models.ts | 54 +++++++++++++++++++++++----- src/renderer/src/config/providers.ts | 6 ++-- src/renderer/src/store/llm.ts | 2 +- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index fc338076..b49b2845 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -1326,34 +1326,70 @@ export const SYSTEM_MODELS: Record = { ], dmxapi: [ { - id: 'gpt-3.5-turbo', + id: 'Qwen/Qwen2.5-7B-Instruct', provider: 'dmxapi', - name: 'GPT-3.5-Turbo', - group: 'OpenAI' + name: 'Qwen/Qwen2.5-7B-Instruct', + group: '免费模型' + }, + { + id: 'ERNIE-Speed-128K', + provider: 'dmxapi', + name: 'ERNIE-Speed-128K', + group: '免费模型' + }, + { + id: 'THUDM/glm-4-9b-chat', + provider: 'dmxapi', + name: 'THUDM/glm-4-9b-chat', + group: '免费模型' + }, + { + id: 'glm-4-flash', + provider: 'dmxapi', + name: 'glm-4-flash', + group: '免费模型' + }, + { + id: 'hunyuan-lite', + provider: 'dmxapi', + name: 'hunyuan-lite', + group: '免费模型' }, { id: 'gpt-4o', provider: 'dmxapi', - name: 'GPT-4o', + name: 'gpt-4o', group: 'OpenAI' }, { id: 'gpt-4o-mini', provider: 'dmxapi', - name: 'GPT-4o-Mini', + name: 'gpt-4o-mini', group: 'OpenAI' }, { - id: 'deepseek-reasoner', + id: 'DMXAPI-DeepSeek-R1', provider: 'dmxapi', - name: 'DeepSeek Reasoner', + name: 'DMXAPI-DeepSeek-R1', group: 'DeepSeek' }, { - id: 'deepseek-chat', + id: 'DMXAPI-DeepSeek-V3', provider: 'dmxapi', - name: 'DeepSeek Chat', + name: 'DMXAPI-DeepSeek-V3', group: 'DeepSeek' + }, + { + id: 'claude-3-5-sonnet-20241022', + provider: 'dmxapi', + name: 'claude-3-5-sonnet-20241022', + group: 'Claude' + }, + { + id: 'gemini-2.0-flash', + provider: 'dmxapi', + name: 'gemini-2.0-flash', + group: 'Gemini' } ], perplexity: [ diff --git a/src/renderer/src/config/providers.ts b/src/renderer/src/config/providers.ts index 08de2c94..9d2837de 100644 --- a/src/renderer/src/config/providers.ts +++ b/src/renderer/src/config/providers.ts @@ -212,11 +212,11 @@ export const PROVIDER_CONFIG = { }, dmxapi: { api: { - url: 'https://api.dmxapi.com' + url: 'https://www.dmxapi.com' }, websites: { - official: 'https://dmxapi.com/', - apiKey: 'https://www.dmxapi.com/token', + official: 'https://www.dmxapi.com/register?aff=81aj/', + apiKey: 'https://www.dmxapi.com/register?aff=81aj', docs: 'https://dmxapi.com/models.html#code-block', models: 'https://www.dmxapi.com/pricing' } diff --git a/src/renderer/src/store/llm.ts b/src/renderer/src/store/llm.ts index 39056388..2396c6ef 100644 --- a/src/renderer/src/store/llm.ts +++ b/src/renderer/src/store/llm.ts @@ -152,7 +152,7 @@ const initialState: LlmState = { name: 'DMXAPI', type: 'openai', apiKey: '', - apiHost: 'https://api.dmxapi.com', + apiHost: 'https://www.dmxapi.com', models: SYSTEM_MODELS.dmxapi, isSystem: true, enabled: false From e3115d00bfb26163b98168ee2ca3ad82742b56a2 Mon Sep 17 00:00:00 2001 From: shniubobo Date: Mon, 17 Feb 2025 08:09:18 +0000 Subject: [PATCH 14/39] fix: Rendering error with MathJax for Chinese text --- package.json | 2 +- yarn.lock | 270 ++++----------------------------------------------- 2 files changed, 22 insertions(+), 250 deletions(-) diff --git a/package.json b/package.json index 0f8846bb..f45ab103 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "redux": "^5.0.1", "redux-persist": "^6.0.0", "rehype-katex": "^7.0.1", - "rehype-mathjax": "^6.0.0", + "rehype-mathjax": "^7.0.0", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.0", "remark-math": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index 21e6a2c0..77d25087 100644 --- a/yarn.lock +++ b/yarn.lock @@ -126,17 +126,6 @@ __metadata: languageName: node linkType: hard -"@asamuzakjp/dom-selector@npm:^2.0.1": - version: 2.0.2 - resolution: "@asamuzakjp/dom-selector@npm:2.0.2" - dependencies: - bidi-js: "npm:^1.0.3" - css-tree: "npm:^2.3.1" - is-potential-custom-element-name: "npm:^1.0.1" - checksum: 10c0/54d9afa3d654a98fcf2e45c53ea330237e513877f130f8c8c17611c603c8d50cb18f937e1b0bcc08f0030443a9c8479dcad9cebff02766025e2df2754459c647 - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2": version: 7.26.2 resolution: "@babel/code-frame@npm:7.26.2" @@ -3066,7 +3055,7 @@ __metadata: redux: "npm:^5.0.1" redux-persist: "npm:^6.0.0" rehype-katex: "npm:^7.0.1" - rehype-mathjax: "npm:^6.0.0" + rehype-mathjax: "npm:^7.0.0" rehype-raw: "npm:^7.0.0" remark-gfm: "npm:^4.0.0" remark-math: "npm:^6.0.0" @@ -3734,15 +3723,6 @@ __metadata: languageName: node linkType: hard -"bidi-js@npm:^1.0.3": - version: 1.0.3 - resolution: "bidi-js@npm:1.0.3" - dependencies: - require-from-string: "npm:^2.0.2" - checksum: 10c0/fdddea4aa4120a34285486f2267526cd9298b6e8b773ad25e765d4f104b6d7437ab4ba542e6939e3ac834a7570bcf121ee2cf6d3ae7cd7082c4b5bedc8f271e1 - languageName: node - linkType: hard - "bindings@npm:^1.5.0": version: 1.5.0 resolution: "bindings@npm:1.5.0" @@ -4632,25 +4612,6 @@ __metadata: languageName: node linkType: hard -"css-tree@npm:^2.3.1": - version: 2.3.1 - resolution: "css-tree@npm:2.3.1" - dependencies: - mdn-data: "npm:2.0.30" - source-map-js: "npm:^1.0.1" - checksum: 10c0/6f8c1a11d5e9b14bf02d10717fc0351b66ba12594166f65abfbd8eb8b5b490dd367f5c7721db241a3c792d935fc6751fbc09f7e1598d421477ad9fadc30f4f24 - languageName: node - linkType: hard - -"cssstyle@npm:^4.0.1": - version: 4.1.0 - resolution: "cssstyle@npm:4.1.0" - dependencies: - rrweb-cssom: "npm:^0.7.1" - checksum: 10c0/05c6597e5d3e0ec6b15221f2c0ce9a0443a46cc50a6089a3ba9ee1ac27f83ff86a445a8f95435137dadd859f091fc61b6d342abaf396d3c910471b5b33cfcbfa - languageName: node - linkType: hard - "csstype@npm:3.1.3, csstype@npm:^3.0.2, csstype@npm:^3.1.3": version: 3.1.3 resolution: "csstype@npm:3.1.3" @@ -4690,16 +4651,6 @@ __metadata: languageName: node linkType: hard -"data-urls@npm:^5.0.0": - version: 5.0.0 - resolution: "data-urls@npm:5.0.0" - dependencies: - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.0.0" - checksum: 10c0/1b894d7d41c861f3a4ed2ae9b1c3f0909d4575ada02e36d3d3bc584bdd84278e20709070c79c3b3bff7ac98598cb191eb3e86a89a79ea4ee1ef360e1694f92ad - languageName: node - linkType: hard - "data-view-buffer@npm:^1.0.2": version: 1.0.2 resolution: "data-view-buffer@npm:1.0.2" @@ -4786,13 +4737,6 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.4.3": - version: 10.4.3 - resolution: "decimal.js@npm:10.4.3" - checksum: 10c0/6d60206689ff0911f0ce968d40f163304a6c1bc739927758e6efc7921cfa630130388966f16bf6ef6b838cb33679fbe8e7a78a2f3c478afce841fd55ac8fb8ee - languageName: node - linkType: hard - "decode-named-character-reference@npm:^1.0.0": version: 1.0.2 resolution: "decode-named-character-reference@npm:1.0.2" @@ -7231,15 +7175,6 @@ __metadata: languageName: node linkType: hard -"html-encoding-sniffer@npm:^4.0.0": - version: 4.0.0 - resolution: "html-encoding-sniffer@npm:4.0.0" - dependencies: - whatwg-encoding: "npm:^3.1.1" - checksum: 10c0/523398055dc61ac9b34718a719cb4aa691e4166f29187e211e1607de63dc25ac7af52ca7c9aead0c4b3c0415ffecb17326396e1202e2e86ff4bca4c0ee4c6140 - languageName: node - linkType: hard - "html-parse-stringify@npm:^3.0.1": version: 3.0.1 resolution: "html-parse-stringify@npm:3.0.1" @@ -7378,7 +7313,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": +"https-proxy-agent@npm:^7.0.1": version: 7.0.6 resolution: "https-proxy-agent@npm:7.0.6" dependencies: @@ -7432,15 +7367,6 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - "iconv-lite@npm:^0.4.4": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -7450,6 +7376,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + "ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" @@ -7870,13 +7805,6 @@ __metadata: languageName: node linkType: hard -"is-potential-custom-element-name@npm:^1.0.1": - version: 1.0.1 - resolution: "is-potential-custom-element-name@npm:1.0.1" - checksum: 10c0/b73e2f22bc863b0939941d369486d308b43d7aef1f9439705e3582bfccaa4516406865e32c968a35f97a99396dac84e2624e67b0a16b0a15086a785e16ce7db9 - languageName: node - linkType: hard - "is-regex@npm:^1.2.1": version: 1.2.1 resolution: "is-regex@npm:1.2.1" @@ -8149,40 +8077,6 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^23.0.0": - version: 23.2.0 - resolution: "jsdom@npm:23.2.0" - dependencies: - "@asamuzakjp/dom-selector": "npm:^2.0.1" - cssstyle: "npm:^4.0.1" - data-urls: "npm:^5.0.0" - decimal.js: "npm:^10.4.3" - form-data: "npm:^4.0.0" - html-encoding-sniffer: "npm:^4.0.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.2" - is-potential-custom-element-name: "npm:^1.0.1" - parse5: "npm:^7.1.2" - rrweb-cssom: "npm:^0.6.0" - saxes: "npm:^6.0.0" - symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^4.1.3" - w3c-xmlserializer: "npm:^5.0.0" - webidl-conversions: "npm:^7.0.0" - whatwg-encoding: "npm:^3.1.1" - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.0.0" - ws: "npm:^8.16.0" - xml-name-validator: "npm:^5.0.0" - peerDependencies: - canvas: ^2.11.2 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/b062af50f7be59d914ba75236b7817c848ef3cd007aea1d6b8020a41eb263b7d5bd2652298106e9756b56892f773d990598778d02adab7d0d0d8e58726fc41d3 - languageName: node - linkType: hard - "jsesc@npm:^3.0.2": version: 3.1.0 resolution: "jsesc@npm:3.1.0" @@ -9115,13 +9009,6 @@ __metadata: languageName: node linkType: hard -"mdn-data@npm:2.0.30": - version: 2.0.30 - resolution: "mdn-data@npm:2.0.30" - checksum: 10c0/a2c472ea16cee3911ae742593715aa4c634eb3d4b9f1e6ada0902aa90df13dcbb7285d19435f3ff213ebaa3b2e0c0265c1eb0e3fb278fda7f8919f046a410cd9 - languageName: node - linkType: hard - "mdurl@npm:^2.0.0": version: 2.0.0 resolution: "mdurl@npm:2.0.0" @@ -10688,7 +10575,7 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.0.0, parse5@npm:^7.1.2": +"parse5@npm:^7.0.0": version: 7.2.1 resolution: "parse5@npm:7.2.1" dependencies: @@ -11146,7 +11033,7 @@ __metadata: languageName: node linkType: hard -"psl@npm:^1.1.28, psl@npm:^1.1.33": +"psl@npm:^1.1.28": version: 1.15.0 resolution: "psl@npm:1.15.0" dependencies: @@ -12144,19 +12031,18 @@ __metadata: languageName: node linkType: hard -"rehype-mathjax@npm:^6.0.0": - version: 6.0.0 - resolution: "rehype-mathjax@npm:6.0.0" +"rehype-mathjax@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-mathjax@npm:7.0.0" dependencies: "@types/hast": "npm:^3.0.0" "@types/mathjax": "npm:^0.0.40" - hast-util-from-dom: "npm:^5.0.0" hast-util-to-text: "npm:^4.0.0" - jsdom: "npm:^23.0.0" + hastscript: "npm:^9.0.0" mathjax-full: "npm:^3.0.0" unified: "npm:^11.0.0" unist-util-visit-parents: "npm:^6.0.0" - checksum: 10c0/f6e0e5a0ed177cfacb9c23ec7603e5ac27937018cf7eb42b8db615eac9b121748686012a200db5ee6de1ca0cd5c8ba7d3aaec28090f01cf6321957a867f1bb78 + checksum: 10c0/bd05b8495316877f4c555bef127c463c0f198f11790523e082307a701234556bc84d2483508531bcc1d2e5c85c609a85dfe7980e8d7fea0c9c5e4f5298c80945 languageName: node linkType: hard @@ -12558,20 +12444,6 @@ __metadata: languageName: node linkType: hard -"rrweb-cssom@npm:^0.6.0": - version: 0.6.0 - resolution: "rrweb-cssom@npm:0.6.0" - checksum: 10c0/3d9d90d53c2349ea9c8509c2690df5a4ef930c9cf8242aeb9425d4046f09d712bb01047e00da0e1c1dab5db35740b3d78fd45c3e7272f75d3724a563f27c30a3 - languageName: node - linkType: hard - -"rrweb-cssom@npm:^0.7.1": - version: 0.7.1 - resolution: "rrweb-cssom@npm:0.7.1" - checksum: 10c0/127b8ca6c8aac45e2755abbae6138d4a813b1bedc2caabf79466ae83ab3cfc84b5bfab513b7033f0aa4561c7753edf787d0dd01163ceacdee2e8eb1b6bf7237e - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -12669,15 +12541,6 @@ __metadata: languageName: node linkType: hard -"saxes@npm:^6.0.0": - version: 6.0.0 - resolution: "saxes@npm:6.0.0" - dependencies: - xmlchars: "npm:^2.2.0" - checksum: 10c0/3847b839f060ef3476eb8623d099aa502ad658f5c40fd60c105ebce86d244389b0d76fcae30f4d0c728d7705ceb2f7e9b34bb54717b6a7dbedaf5dad2d9a4b74 - languageName: node - linkType: hard - "scheduler@npm:^0.23.2": version: 0.23.2 resolution: "scheduler@npm:0.23.2" @@ -13015,7 +12878,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf @@ -13526,13 +13389,6 @@ __metadata: languageName: node linkType: hard -"symbol-tree@npm:^3.2.4": - version: 3.2.4 - resolution: "symbol-tree@npm:3.2.4" - checksum: 10c0/dfbe201ae09ac6053d163578778c53aa860a784147ecf95705de0cd23f42c851e1be7889241495e95c37cabb058edb1052f141387bef68f705afc8f9dd358509 - languageName: node - linkType: hard - "synckit@npm:^0.9.1": version: 0.9.2 resolution: "synckit@npm:0.9.2" @@ -13800,18 +13656,6 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.1.3": - version: 4.1.4 - resolution: "tough-cookie@npm:4.1.4" - dependencies: - psl: "npm:^1.1.33" - punycode: "npm:^2.1.1" - universalify: "npm:^0.2.0" - url-parse: "npm:^1.5.3" - checksum: 10c0/aca7ff96054f367d53d1e813e62ceb7dd2eda25d7752058a74d64b7266fd07be75908f3753a32ccf866a2f997604b414cfb1916d6e7f69bc64d9d9939b0d6c45 - languageName: node - linkType: hard - "tough-cookie@npm:~2.5.0": version: 2.5.0 resolution: "tough-cookie@npm:2.5.0" @@ -13822,15 +13666,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^5.0.0": - version: 5.0.0 - resolution: "tr46@npm:5.0.0" - dependencies: - punycode: "npm:^2.3.1" - checksum: 10c0/1521b6e7bbc8adc825c4561480f9fe48eb2276c81335eed9fa610aa4c44a48a3221f78b10e5f18b875769eb3413e30efbf209ed556a17a42aa8d690df44b7bee - languageName: node - linkType: hard - "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -14216,13 +14051,6 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^0.2.0": - version: 0.2.0 - resolution: "universalify@npm:0.2.0" - checksum: 10c0/cedbe4d4ca3967edf24c0800cfc161c5a15e240dac28e3ce575c689abc11f2c81ccc6532c8752af3b40f9120fb5e454abecd359e164f4f6aa44c29cd37e194fe - languageName: node - linkType: hard - "universalify@npm:^2.0.0": version: 2.0.1 resolution: "universalify@npm:2.0.1" @@ -14271,7 +14099,7 @@ __metadata: languageName: node linkType: hard -"url-parse@npm:^1.5.10, url-parse@npm:^1.5.3": +"url-parse@npm:^1.5.10": version: 1.5.10 resolution: "url-parse@npm:1.5.10" dependencies: @@ -14486,15 +14314,6 @@ __metadata: languageName: node linkType: hard -"w3c-xmlserializer@npm:^5.0.0": - version: 5.0.0 - resolution: "w3c-xmlserializer@npm:5.0.0" - dependencies: - xml-name-validator: "npm:^5.0.0" - checksum: 10c0/8712774c1aeb62dec22928bf1cdfd11426c2c9383a1a63f2bcae18db87ca574165a0fbe96b312b73652149167ac6c7f4cf5409f2eb101d9c805efe0e4bae798b - languageName: node - linkType: hard - "web-namespaces@npm:^2.0.0": version: 2.0.1 resolution: "web-namespaces@npm:2.0.1" @@ -14544,39 +14363,6 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^7.0.0": - version: 7.0.0 - resolution: "webidl-conversions@npm:7.0.0" - checksum: 10c0/228d8cb6d270c23b0720cb2d95c579202db3aaf8f633b4e9dd94ec2000a04e7e6e43b76a94509cdb30479bd00ae253ab2371a2da9f81446cc313f89a4213a2c4 - languageName: node - linkType: hard - -"whatwg-encoding@npm:^3.1.1": - version: 3.1.1 - resolution: "whatwg-encoding@npm:3.1.1" - dependencies: - iconv-lite: "npm:0.6.3" - checksum: 10c0/273b5f441c2f7fda3368a496c3009edbaa5e43b71b09728f90425e7f487e5cef9eb2b846a31bd760dd8077739c26faf6b5ca43a5f24033172b003b72cf61a93e - languageName: node - linkType: hard - -"whatwg-mimetype@npm:^4.0.0": - version: 4.0.0 - resolution: "whatwg-mimetype@npm:4.0.0" - checksum: 10c0/a773cdc8126b514d790bdae7052e8bf242970cebd84af62fb2f35a33411e78e981f6c0ab9ed1fe6ec5071b09d5340ac9178e05b52d35a9c4bcf558ba1b1551df - languageName: node - linkType: hard - -"whatwg-url@npm:^14.0.0": - version: 14.1.0 - resolution: "whatwg-url@npm:14.1.0" - dependencies: - tr46: "npm:^5.0.0" - webidl-conversions: "npm:^7.0.0" - checksum: 10c0/f00104f1c67ce086ba8ffedab529cbbd9aefd8c0a6555320026de7aeff31f91c38680f95818b140a7c9cc657cde3781e567835dda552ddb1e2b8faaba0ac3cb6 - languageName: node - linkType: hard - "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -14756,7 +14542,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.13.0, ws@npm:^8.16.0": +"ws@npm:^8.13.0": version: 8.18.0 resolution: "ws@npm:8.18.0" peerDependencies: @@ -14803,13 +14589,6 @@ __metadata: languageName: node linkType: hard -"xml-name-validator@npm:^5.0.0": - version: 5.0.0 - resolution: "xml-name-validator@npm:5.0.0" - checksum: 10c0/3fcf44e7b73fb18be917fdd4ccffff3639373c7cb83f8fc35df6001fecba7942f1dbead29d91ebb8315e2f2ff786b508f0c9dc0215b6353f9983c6b7d62cb1f5 - languageName: node - linkType: hard - "xml-parse-from-string@npm:^1.0.0": version: 1.0.1 resolution: "xml-parse-from-string@npm:1.0.1" @@ -14875,13 +14654,6 @@ __metadata: languageName: node linkType: hard -"xmlchars@npm:^2.2.0": - version: 2.2.0 - resolution: "xmlchars@npm:2.2.0" - checksum: 10c0/b64b535861a6f310c5d9bfa10834cf49127c71922c297da9d4d1b45eeaae40bf9b4363275876088fbe2667e5db028d2cd4f8ee72eed9bede840a67d57dab7593 - languageName: node - linkType: hard - "xmldom-sre@npm:0.1.31": version: 0.1.31 resolution: "xmldom-sre@npm:0.1.31" From bad2f15c1fba4ebdf3831a2025bc0f89bcb04487 Mon Sep 17 00:00:00 2001 From: cl1107 Date: Mon, 17 Feb 2025 16:36:01 +0800 Subject: [PATCH 15/39] feat: Add a new grid mode for message display. (#1626) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(version): 0.9.23 * feat(renderer): 新增网格模式的消息展示方式 * feat(message): 新增消息网格展示相关设置 * 根据 gridPopoverTrigger 属性动态设置消息分组的样式 * 在 MessageMenubar 组件中,各个按钮 click 事件阻止事件冒泡,避免打开 popover * 多模型回答样式添加网格模式并优化消息样式 --------- Co-authored-by: kangfenmao --- src/renderer/src/i18n/locales/en-us.json | 3 + src/renderer/src/i18n/locales/ja-jp.json | 3 + src/renderer/src/i18n/locales/ru-ru.json | 3 + src/renderer/src/i18n/locales/zh-cn.json | 3 + src/renderer/src/i18n/locales/zh-tw.json | 3 + .../src/pages/home/Messages/MessageGroup.tsx | 150 ++++++++++++++---- .../pages/home/Messages/MessageMenubar.tsx | 54 +++++-- .../src/pages/home/Tabs/SettingsTab.tsx | 37 ++++- src/renderer/src/store/settings.ts | 16 +- 9 files changed, 221 insertions(+), 51 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index a39c2637..5aabfc92 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -364,6 +364,7 @@ "message.multi_model_style.fold": "Fold", "message.multi_model_style.horizontal": "Horizontal", "message.multi_model_style.vertical": "Vertical", + "message.multi_model_style.grid": "Grid", "message.style": "Message style", "message.style.bubble": "Bubble", "message.style.plain": "Plain", @@ -636,6 +637,8 @@ "messages.input.title": "Input Settings", "messages.markdown_rendering_input_message": "Markdown render input message", "messages.math_engine": "Math engine", + "messages.grid_columns": "Message grid display columns", + "messages.grid_popover_trigger": "Grid detail trigger", "messages.metrics": "{{time_first_token_millsec}}ms to first token | {{token_speed}} tok/sec", "messages.model.title": "Model Settings", "messages.title": "Message Settings", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 94ee7182..25774cc6 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -363,6 +363,7 @@ "message.multi_model_style.fold": "折りたたむ", "message.multi_model_style.horizontal": "水平", "message.multi_model_style.vertical": "垂直", + "message.multi_model_style.grid": "グリッド", "message.style": "メッセージスタイル", "message.style.bubble": "バブル", "message.style.plain": "プレーン", @@ -636,6 +637,8 @@ "messages.input.title": "入力設定", "messages.markdown_rendering_input_message": "Markdownで入力メッセージをレンダリング", "messages.math_engine": "数式エンジン", + "messages.grid_columns": "メッセージグリッドの表示列数", + "messages.grid_popover_trigger": "グリッド詳細トリガー", "messages.metrics": "最初のトークンまでの時間 {{time_first_token_millsec}}ms | トークン速度 {{token_speed}} tok/sec", "messages.model.title": "モデル設定", "messages.title": "メッセージ設定", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index cdf67b74..79ea0c77 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -364,6 +364,7 @@ "message.multi_model_style.fold": "Свернуть", "message.multi_model_style.horizontal": "Горизонтальный", "message.multi_model_style.vertical": "Вертикальный", + "message.multi_model_style.grid": "клетчатый вид", "message.style": "Стиль сообщения", "message.style.bubble": "Пузырь", "message.style.plain": "Простой", @@ -637,6 +638,8 @@ "messages.math_engine": "Математический движок", "messages.metrics": "{{time_first_token_millsec}}ms до первого токена | {{token_speed}} tok/sec", "messages.model.title": "Настройки модели", + "messages.grid_columns": "Количество столбцов сетки сообщений", + "messages.grid_popover_trigger": "Триггер для отображения подробной информации в сетке", "messages.title": "Настройки сообщений", "messages.use_serif_font": "Использовать serif шрифт", "model": "Модель по умолчанию", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index bccc8b19..61ada8db 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -366,6 +366,7 @@ "message.multi_model_style.fold": "折叠", "message.multi_model_style.horizontal": "水平", "message.multi_model_style.vertical": "垂直", + "message.multi_model_style.grid": "网格", "message.style": "消息样式", "message.style.bubble": "气泡", "message.style.plain": "简洁", @@ -636,6 +637,8 @@ "messages.input.title": "输入设置", "messages.markdown_rendering_input_message": "Markdown 渲染输入消息", "messages.math_engine": "数学公式引擎", + "messages.grid_columns": "消息网格展示列数", + "messages.grid_popover_trigger": "网格详情触发", "messages.metrics": "首字时延 {{time_first_token_millsec}}ms | 每秒 {{token_speed}} tokens", "messages.model.title": "模型设置", "messages.title": "消息设置", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 2c6e97dd..425aa492 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -364,6 +364,7 @@ "message.multi_model_style.fold": "折疊", "message.multi_model_style.horizontal": "水平", "message.multi_model_style.vertical": "垂直", + "message.multi_model_style.grid": "网格", "message.style": "消息樣式", "message.style.bubble": "氣泡", "message.style.plain": "簡潔", @@ -635,6 +636,8 @@ "messages.input.show_estimated_tokens": "顯示預估 Token 數", "messages.input.title": "輸入設定", "messages.math_engine": "Markdown 渲染輸入訊息", + "messages.grid_columns": "消息網格展示列數", + "messages.grid_popover_trigger": "網格詳情觸發", "messages.metrics": "首字時延 {{time_first_token_millsec}}ms | 每秒 {{token_speed}} tokens", "messages.model.title": "模型設定", "messages.title": "訊息設定", diff --git a/src/renderer/src/pages/home/Messages/MessageGroup.tsx b/src/renderer/src/pages/home/Messages/MessageGroup.tsx index 3b8488bf..629185ed 100644 --- a/src/renderer/src/pages/home/Messages/MessageGroup.tsx +++ b/src/renderer/src/pages/home/Messages/MessageGroup.tsx @@ -1,4 +1,10 @@ -import { ColumnHeightOutlined, ColumnWidthOutlined, DeleteOutlined, FolderOutlined } from '@ant-design/icons' +import { + ColumnHeightOutlined, + ColumnWidthOutlined, + DeleteOutlined, + FolderOutlined, + NumberOutlined +} from '@ant-design/icons' import ModelAvatar from '@renderer/components/Avatar/ModelAvatar' import { HStack } from '@renderer/components/Layout' import Scrollbar from '@renderer/components/Scrollbar' @@ -6,7 +12,7 @@ import { useSettings } from '@renderer/hooks/useSettings' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { MultiModelMessageStyle } from '@renderer/store/settings' import { Message, Model, Topic } from '@renderer/types' -import { Button, Segmented as AntdSegmented } from 'antd' +import { Button, Popover, Segmented as AntdSegmented } from 'antd' import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' @@ -32,7 +38,7 @@ const MessageGroup: FC = ({ onGetMessages, onDeleteGroupMessages }) => { - const { multiModelMessageStyle: multiModelMessageStyleSetting } = useSettings() + const { multiModelMessageStyle: multiModelMessageStyleSetting, gridColumns, gridPopoverTrigger } = useSettings() const { t } = useTranslation() const [multiModelMessageStyle, setMultiModelMessageStyle] = @@ -67,33 +73,89 @@ const MessageGroup: FC = ({ return ( - - {messages.map((message, index) => ( - - - - ))} + + {messages.map((message, index) => + multiModelMessageStyle === 'grid' && message.role === 'assistant' && isGrouped ? ( + + + + } + trigger={gridPopoverTrigger} + styles={{ root: { maxWidth: '60vw', minWidth: '550px', overflowY: 'auto', zIndex: 1000 } }} + getPopupContainer={(triggerNode) => triggerNode.parentNode as HTMLElement} + key={message.id}> + + + + + ) : ( + + + + ) + )} {isGrouped && ( - {['fold', 'vertical', 'horizontal'].map((layout) => ( + {['fold', 'vertical', 'horizontal', 'grid'].map((layout) => ( = ({ ) : layout === 'horizontal' ? ( - ) : ( + ) : layout === 'vertical' ? ( + ) : ( + )} ))} @@ -143,30 +207,38 @@ const MessageGroup: FC = ({ } const GroupContainer = styled.div<{ $isGrouped: boolean; $layout: MultiModelMessageStyle }>` - padding-top: ${({ $isGrouped, $layout }) => ($isGrouped && $layout === 'horizontal' ? '15px' : '0')}; + padding-top: ${({ $isGrouped, $layout }) => ($isGrouped && 'horizontal' === $layout ? '15px' : '0')}; ` -const GridContainer = styled.div<{ $count: number; $layout: MultiModelMessageStyle }>` +const GridContainer = styled.div<{ $count: number; $layout: MultiModelMessageStyle; $gridColumns: number }>` width: 100%; display: grid; grid-template-columns: repeat( - ${(props) => (['fold', 'vertical'].includes(props.$layout) ? 1 : props.$count)}, + ${({ $layout, $count }) => (['fold', 'vertical'].includes($layout) ? 1 : $count)}, minmax(550px, 1fr) ); gap: ${({ $layout }) => ($layout === 'horizontal' ? '16px' : '0')}; @media (max-width: 800px) { grid-template-columns: repeat( - ${(props) => (['fold', 'vertical'].includes(props.$layout) ? 1 : props.$count)}, + ${({ $layout, $count }) => (['fold', 'vertical'].includes($layout) ? 1 : $count)}, minmax(400px, 1fr) ); } overflow-y: auto; + ${({ $gridColumns, $layout, $count }) => + $layout === 'grid' && + css` + grid-template-columns: repeat(${$count > 1 ? $gridColumns || 2 : 1}, minmax(0, 1fr)); + grid-template-rows: auto; + gap: 16px; + `} ` interface MessageWrapperProps { - $layout: 'fold' | 'horizontal' | 'vertical' + $layout: 'fold' | 'horizontal' | 'vertical' | 'grid' $selected: boolean $isGrouped: boolean + $isInPopover?: boolean } const MessageWrapper = styled(Scrollbar)` @@ -193,6 +265,22 @@ const MessageWrapper = styled(Scrollbar)` } return '' }} + + ${({ $layout, $isInPopover, $isGrouped }) => + $layout === 'grid' && $isGrouped + ? css` + max-height: ${$isInPopover ? '50vh' : '300px'}; + overflow-y: auto; + border: 0.5px solid var(--color-border); + padding: 10px; + border-radius: 6px; + ` + : css` + overflow-y: auto; + border: 0.5px solid transparent; + padding: 0 10px; + border-radius: 6px; + `} ` const GroupMenuBar = styled.div<{ $layout: MultiModelMessageStyle }>` diff --git a/src/renderer/src/pages/home/Messages/MessageMenubar.tsx b/src/renderer/src/pages/home/Messages/MessageMenubar.tsx index 9cd8b3ae..0b3e6f05 100644 --- a/src/renderer/src/pages/home/Messages/MessageMenubar.tsx +++ b/src/renderer/src/pages/home/Messages/MessageMenubar.tsx @@ -60,12 +60,16 @@ const MessageMenubar: FC = (props) => { const isUserMessage = message.role === 'user' - const onCopy = useCallback(() => { - navigator.clipboard.writeText(removeTrailingDoubleSpaces(message.content)) - window.message.success({ content: t('message.copied'), key: 'copy-message' }) - setCopied(true) - setTimeout(() => setCopied(false), 2000) - }, [message.content, t]) + const onCopy = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + navigator.clipboard.writeText(removeTrailingDoubleSpaces(message.content)) + window.message.success({ content: t('message.copied'), key: 'copy-message' }) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + }, + [message.content, t] + ) const onNewBranch = useCallback(async () => { await modelGenerating() @@ -195,14 +199,16 @@ const MessageMenubar: FC = (props) => { [message, onEdit, onNewBranch, t] ) - const onRegenerate = async () => { + const onRegenerate = async (e: React.MouseEvent | undefined) => { + e?.stopPropagation?.() await modelGenerating() const selectedModel = isGrouped ? model : assistantModel const _message = resetAssistantMessage(message, selectedModel) onEditMessage?.(_message) } - const onMentionModel = async () => { + const onMentionModel = async (e: React.MouseEvent) => { + e.stopPropagation() await modelGenerating() const selectedModel = await SelectModelPopup.show({ model }) if (!selectedModel) return @@ -216,9 +222,13 @@ const MessageMenubar: FC = (props) => { onEditMessage?.(_message) } - const onUseful = useCallback(() => { - onEditMessage?.({ ...message, useful: !message.useful }) - }, [message, onEditMessage]) + const onUseful = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + onEditMessage?.({ ...message, useful: !message.useful }) + }, + [message, onEditMessage] + ) return ( @@ -270,13 +280,14 @@ const MessageMenubar: FC = (props) => { key: 'translate-close', onClick: () => onEditMessage?.({ ...message, translatedContent: undefined }) } - ] + ], + onClick: (e) => e.domEvent.stopPropagation() }} trigger={['click']} placement="topRight" arrow> - + e.stopPropagation()}> @@ -298,14 +309,25 @@ const MessageMenubar: FC = (props) => { onDeleteMessage?.(message) : undefined}> + onClick={ + isGrouped + ? (e) => { + e.stopPropagation() + onDeleteMessage?.(message) + } + : (e) => e.stopPropagation() + }> {!isUserMessage && ( - - + e.domEvent.stopPropagation() }} + trigger={['click']} + placement="topRight" + arrow> + e.stopPropagation()}> diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index 2df3ff66..8828716c 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -19,6 +19,8 @@ import { setCodeShowLineNumbers, setCodeStyle, setFontSize, + setGridColumns, + setGridPopoverTrigger, setMathEngine, setMessageFont, setMessageStyle, @@ -42,13 +44,14 @@ interface Props { const SettingsTab: FC = (props) => { const { assistant, updateAssistantSettings, updateAssistant } = useAssistant(props.assistant.id) - const { messageStyle, codeStyle, fontSize, language } = useSettings() + const { messageStyle, codeStyle, fontSize, language, gridColumns } = useSettings() const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE) const [contextCount, setContextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT) const [enableMaxTokens, setEnableMaxTokens] = useState(assistant?.settings?.enableMaxTokens ?? false) const [maxTokens, setMaxTokens] = useState(assistant?.settings?.maxTokens ?? 0) const [fontSizeValue, setFontSizeValue] = useState(fontSize) + const [gridColumnsValue, setGridColumnsValue] = useState(gridColumns) const [streamOutput, setStreamOutput] = useState(assistant?.settings?.streamOutput ?? true) const { t } = useTranslation() @@ -69,7 +72,8 @@ const SettingsTab: FC = (props) => { mathEngine, autoTranslateWithSpace, pasteLongTextThreshold, - multiModelMessageStyle + multiModelMessageStyle, + gridPopoverTrigger } = useSettings() const onUpdateAssistantSettings = (settings: Partial) => { @@ -283,6 +287,7 @@ const SettingsTab: FC = (props) => { {t('message.message.multi_model_style.fold')} {t('message.message.multi_model_style.vertical')} {t('message.message.multi_model_style.horizontal')} + {t('message.message.multi_model_style.grid')} @@ -313,6 +318,34 @@ const SettingsTab: FC = (props) => { + + {t('settings.messages.grid_popover_trigger')} + + + + + {t('settings.messages.grid_columns')} + + + + setGridColumnsValue(value)} + onChangeComplete={(value) => dispatch(setGridColumns(value))} + min={2} + max={9} + step={1} + /> + + + {t('settings.font_size.title')} diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts index 18dba29f..03b51658 100644 --- a/src/renderer/src/store/settings.ts +++ b/src/renderer/src/store/settings.ts @@ -44,6 +44,8 @@ export interface SettingsState { mathEngine: 'MathJax' | 'KaTeX' messageStyle: 'plain' | 'bubble' codeStyle: CodeStyleVarious + gridColumns: number + gridPopoverTrigger: 'hover' | 'click' // webdav 配置 host, user, pass, path webdavHost: string webdavUser: string @@ -69,7 +71,7 @@ export interface SettingsState { notionApiKey: string | null } -export type MultiModelMessageStyle = 'horizontal' | 'vertical' | 'fold' +export type MultiModelMessageStyle = 'horizontal' | 'vertical' | 'fold' | 'grid' const initialState: SettingsState = { showAssistants: true, @@ -99,6 +101,8 @@ const initialState: SettingsState = { mathEngine: 'KaTeX', messageStyle: 'plain', codeStyle: 'auto', + gridColumns: 2, + gridPopoverTrigger: 'hover', webdavHost: '', webdavUser: '', webdavPass: '', @@ -224,6 +228,12 @@ const settingsSlice = createSlice({ setMathEngine: (state, action: PayloadAction<'MathJax' | 'KaTeX'>) => { state.mathEngine = action.payload }, + setGridColumns: (state, action: PayloadAction) => { + state.gridColumns = action.payload + }, + setGridPopoverTrigger: (state, action: PayloadAction<'hover' | 'click'>) => { + state.gridPopoverTrigger = action.payload + }, setMessageStyle: (state, action: PayloadAction<'plain' | 'bubble'>) => { state.messageStyle = action.payload }, @@ -265,7 +275,7 @@ const settingsSlice = createSlice({ setEnableQuickAssistant: (state, action: PayloadAction) => { state.enableQuickAssistant = action.payload }, - setMultiModelMessageStyle: (state, action: PayloadAction<'horizontal' | 'vertical' | 'fold'>) => { + setMultiModelMessageStyle: (state, action: PayloadAction<'horizontal' | 'vertical' | 'fold' | 'grid'>) => { state.multiModelMessageStyle = action.payload }, setNotionDatabaseID: (state, action: PayloadAction) => { @@ -310,6 +320,8 @@ export const { setCodeShowLineNumbers, setCodeCollapsible, setMathEngine, + setGridColumns, + setGridPopoverTrigger, setMessageStyle, setCodeStyle, setTranslateModelPrompt, From 266f909045913387c31f04abd2ba5f9a618b156c Mon Sep 17 00:00:00 2001 From: Chen Tao <70054568+eeee0717@users.noreply.github.com> Date: Mon, 17 Feb 2025 16:36:25 +0800 Subject: [PATCH 16/39] feat: allow knowledge base multiple search #1346 (#1773) * feat: agent can select multiple knowledge bases * feat: basic search multiple knowledge base * fix bug: knowledge base is delete, assistants and agents sync delete * fix bug: assistant and knowledge base button sync * feat: allow to search multiple knowledge base * chore: finish rebase to upstream/main --- src/renderer/src/hooks/useKnowledge.ts | 14 ++-- .../pages/agents/components/AddAgentPopup.tsx | 9 ++- .../src/pages/home/Inputbar/Inputbar.tsx | 23 ++++--- .../home/Inputbar/KnowledgeBaseButton.tsx | 64 ++++++++----------- .../AssistantKnowledgeBaseSettings.tsx | 7 +- src/renderer/src/providers/BaseProvider.ts | 29 +++++++-- src/renderer/src/services/KnowledgeService.ts | 13 +--- src/renderer/src/types/index.ts | 2 +- 8 files changed, 83 insertions(+), 78 deletions(-) diff --git a/src/renderer/src/hooks/useKnowledge.ts b/src/renderer/src/hooks/useKnowledge.ts index ffd425e1..dbb90ca8 100644 --- a/src/renderer/src/hooks/useKnowledge.ts +++ b/src/renderer/src/hooks/useKnowledge.ts @@ -307,16 +307,22 @@ export const useKnowledgeBases = () => { // remove assistant knowledge_base const _assistants = assistants.map((assistant) => { - if (assistant.knowledge_base?.id === baseId) { - return { ...assistant, knowledge_base: undefined } + if (assistant.knowledge_bases?.find((kb) => kb.id === baseId)) { + return { + ...assistant, + knowledge_bases: assistant.knowledge_bases.filter((kb) => kb.id !== baseId) + } } return assistant }) // remove agent knowledge_base const _agents = agents.map((agent) => { - if (agent.knowledge_base?.id === baseId) { - return { ...agent, knowledge_base: undefined } + if (agent.knowledge_bases?.find((kb) => kb.id === baseId)) { + return { + ...agent, + knowledge_bases: agent.knowledge_bases.filter((kb) => kb.id !== baseId) + } } return agent }) diff --git a/src/renderer/src/pages/agents/components/AddAgentPopup.tsx b/src/renderer/src/pages/agents/components/AddAgentPopup.tsx index cd169edf..162c2e70 100644 --- a/src/renderer/src/pages/agents/components/AddAgentPopup.tsx +++ b/src/renderer/src/pages/agents/components/AddAgentPopup.tsx @@ -9,7 +9,7 @@ import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon' import { fetchGenerate } from '@renderer/services/ApiService' import { getDefaultModel } from '@renderer/services/AssistantService' import { useAppSelector } from '@renderer/store' -import { Agent } from '@renderer/types' +import { Agent, KnowledgeBase } from '@renderer/types' import { getLeadingEmoji, uuid } from '@renderer/utils' import { Button, Form, FormInstance, Input, Modal, Popover, Select, SelectProps } from 'antd' import TextArea from 'antd/es/input/TextArea' @@ -25,7 +25,7 @@ type FieldType = { id: string name: string prompt: string - knowledge_base_id: string + knowledge_base_id: string[] } const PopupContainer: React.FC = ({ resolve }) => { @@ -57,7 +57,9 @@ const PopupContainer: React.FC = ({ resolve }) => { const _agent: Agent = { id: uuid(), name: values.name, - knowledge_base: knowledgeState.bases.find((t) => t.id === values.knowledge_base_id), + knowledge_bases: values.knowledge_base_id + .map((id) => knowledgeState.bases.find((t) => t.id === id)) + .filter((base): base is KnowledgeBase => base !== undefined), emoji: _emoji, prompt: values.prompt, defaultModel: getDefaultModel(), @@ -156,6 +158,7 @@ const PopupContainer: React.FC = ({ resolve }) => { {showKnowledgeIcon && ( base.id)} + allowClear + placeholder={t('agents.add.knowledge_base.placeholder')} + menuItemSelectedIcon={} + options={knowledgeOptions} + onChange={(ids) => { + const newSelected = knowledgeState.bases.filter((base) => ids.includes(base.id)) + onSelect(newSelected) + }} + style={{ width: '200px' }} + /> )} ) } -const KnowledgeBaseButton: FC = ({ selectedBase, onSelect, disabled, ToolbarButton }) => { +const KnowledgeBaseButton: FC = ({ selectedBases, onSelect, disabled, ToolbarButton }) => { const { t } = useTranslation() - if (selectedBase) { - return ( - - onSelect(undefined)}> - - - - ) - } - return ( } + content={} overlayStyle={{ maxWidth: 400 }} trigger="click"> - selectedBase && onSelect(undefined)} disabled={disabled}> - + + 0 ? 'var(--color-link)' : 'var(--color-icon)' }} + /> diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantKnowledgeBaseSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantKnowledgeBaseSettings.tsx index 9108843d..90efde55 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantKnowledgeBaseSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantKnowledgeBaseSettings.tsx @@ -26,8 +26,8 @@ const AssistantKnowledgeBaseSettings: React.FC = ({ assistant, updateAssi }) const onUpdate = (value) => { - const knowledge_base = knowledgeState.bases.find((t) => t.id === value) - const _assistant = { ...assistant, knowledge_base } + const knowledge_bases = value.map((id) => knowledgeState.bases.find((b) => b.id === id)) + const _assistant = { ...assistant, knowledge_bases } updateAssistant(_assistant) } @@ -37,8 +37,9 @@ const AssistantKnowledgeBaseSettings: React.FC = ({ assistant, updateAssi {t('common.knowledge_base')} dispatch(setGridPopoverTrigger(value))} + size="small"> + {t('settings.messages.grid_popover_trigger.hover')} + {t('settings.messages.grid_popover_trigger.click')} + + setGridColumnsValue(value)} + onChangeComplete={(value) => dispatch(setGridColumns(value))} + min={2} + max={6} + step={1} + /> + + )}