From 7199f73e06a8eabd2ba38cb3194330b0c0615b54 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Tue, 18 Feb 2025 15:48:13 +0800 Subject: [PATCH 01/66] style: Adjust horizontal message layout display property --- src/renderer/src/pages/home/Messages/MessageGroup.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/pages/home/Messages/MessageGroup.tsx b/src/renderer/src/pages/home/Messages/MessageGroup.tsx index 5bfc8300..648130c1 100644 --- a/src/renderer/src/pages/home/Messages/MessageGroup.tsx +++ b/src/renderer/src/pages/home/Messages/MessageGroup.tsx @@ -202,7 +202,7 @@ const MessageWrapper = styled(Scrollbar)` return props.$selected ? 'block' : 'none' } if (props.$layout === 'horizontal') { - return 'inline-flex' + return 'inline-block' } return 'block' }}; From 7c4d81c108fc3770492069c2e234c9476bf68f2d Mon Sep 17 00:00:00 2001 From: ousugo Date: Tue, 18 Feb 2025 15:18:16 +0800 Subject: [PATCH 02/66] feat: Add kimi-latest model support in vision and model logos --- src/renderer/src/config/models.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index b49b2845..2b9740b1 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -150,7 +150,8 @@ const visionAllowedModels = [ 'gpt-4o(?:-[\\w-]+)?', 'chatgpt-4o(?:-[\\w-]+)?', 'o1(?:-[\\w-]+)?', - 'deepseek-vl(?:[\\w-]+)?' + 'deepseek-vl(?:[\\w-]+)?', + 'kimi-latest' ] const visionExcludedModels = ['gpt-4-\\d+-preview', 'gpt-4-turbo-preview', 'gpt-4-32k', 'gpt-4-\\d+'] @@ -180,6 +181,7 @@ export function getModelLogo(modelId: string) { abab: isLight ? MinimaxModelLogo : MinimaxModelLogoDark, o3: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, o1: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, + 'kimi-latest': isLight ? MoonshotModelLogo : MoonshotModelLogoDark, 'gpt-3': isLight ? ChatGPT35ModelLogo : ChatGPT35ModelLogoDark, 'gpt-4': isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark, gpts: isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark, @@ -1385,7 +1387,7 @@ export const SYSTEM_MODELS: Record = { name: 'claude-3-5-sonnet-20241022', group: 'Claude' }, - { + { id: 'gemini-2.0-flash', provider: 'dmxapi', name: 'gemini-2.0-flash', From fb8ed35b5938bed803bb66a70be409d6e42534aa Mon Sep 17 00:00:00 2001 From: ousugo Date: Tue, 18 Feb 2025 14:01:46 +0800 Subject: [PATCH 03/66] fix: Clicking the taskbar icon while enable the Quick Assistant can't open the main window --- src/main/index.ts | 14 ++++---------- src/main/services/WindowService.ts | 27 +++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 0f0c72cd..b40950e3 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,5 +1,5 @@ import { electronApp, optimizer } from '@electron-toolkit/utils' -import { app, BrowserWindow } from 'electron' +import { app } from 'electron' import installExtension, { REDUX_DEVTOOLS } from 'electron-devtools-installer' import { registerIpc } from './ipc' @@ -46,9 +46,8 @@ if (!app.requestSingleInstanceLock()) { new TrayService() app.on('activate', function () { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (BrowserWindow.getAllWindows().length === 0) { + const mainWindow = windowService.getMainWindow() + if (!mainWindow || mainWindow.isDestroyed()) { windowService.createMainWindow() } else { windowService.showMainWindow() @@ -68,12 +67,7 @@ if (!app.requestSingleInstanceLock()) { // Listen for second instance app.on('second-instance', () => { - const mainWindow = BrowserWindow.getAllWindows()[0] - if (mainWindow) { - mainWindow.isMinimized() && mainWindow.restore() - mainWindow.show() - mainWindow.focus() - } + windowService.showMainWindow() }) app.on('browser-window-created', (_, window) => { diff --git a/src/main/services/WindowService.ts b/src/main/services/WindowService.ts index 1ce7eb8a..414c568d 100644 --- a/src/main/services/WindowService.ts +++ b/src/main/services/WindowService.ts @@ -28,6 +28,7 @@ export class WindowService { public createMainWindow(): BrowserWindow { if (this.mainWindow && !this.mainWindow.isDestroyed()) { + this.mainWindow.show() return this.mainWindow } @@ -248,17 +249,32 @@ export class WindowService { event.preventDefault() mainWindow.hide() }) + + mainWindow.on('closed', () => { + this.mainWindow = null + }) + + mainWindow.on('show', () => { + if (this.miniWindow && !this.miniWindow.isDestroyed()) { + this.miniWindow.hide() + } + }) } public showMainWindow() { - if (this.mainWindow) { + if (this.miniWindow && !this.miniWindow.isDestroyed()) { + this.miniWindow.hide() + } + + if (this.mainWindow && !this.mainWindow.isDestroyed()) { if (this.mainWindow.isMinimized()) { - return this.mainWindow.restore() + this.mainWindow.restore() } this.mainWindow.show() this.mainWindow.focus() } else { - this.createMainWindow() + this.mainWindow = this.createMainWindow() + this.mainWindow.focus() } } @@ -269,7 +285,10 @@ export class WindowService { return } - if (this.selectionMenuWindow) { + if (this.mainWindow && !this.mainWindow.isDestroyed()) { + this.mainWindow.hide() + } + if (this.selectionMenuWindow && !this.selectionMenuWindow.isDestroyed()) { this.selectionMenuWindow.hide() } From bf8a7c01b00f339be9154b4bf1a8d9f9d39050c6 Mon Sep 17 00:00:00 2001 From: lucifer9 Date: Tue, 18 Feb 2025 15:55:41 +0800 Subject: [PATCH 04/66] Refactor WebDAV i18n and UI for improved flexibility and localization - i18n Updates: - Refactored WebDAV-related translations into nested JSON structures for better organization. - Added support for pluralization in time intervals (minutes and hours) across all locales (en-us, ja-jp, ru-ru, zh-cn, zh-tw). - UI Enhancements: - Updated `DataSettings` and `WebDavSettings` components to use the new i18n keys for time intervals. - Improved the `Select` dropdown for sync intervals with dynamic pluralization based on locale. - Adjusted input field widths for better alignment and consistency. - Code Cleanup: - Removed redundant comments and unused code in `WebDavSettings.tsx`. - Simplified button and input styling for a cleaner layout. --- src/renderer/src/i18n/locales/en-us.json | 42 ++++++++-------- src/renderer/src/i18n/locales/ja-jp.json | 29 ++++++++++- src/renderer/src/i18n/locales/ru-ru.json | 44 +++++++++-------- src/renderer/src/i18n/locales/zh-cn.json | 46 ++++++++++-------- src/renderer/src/i18n/locales/zh-tw.json | 48 +++++++++++-------- .../settings/DataSettings/DataSettings.tsx | 6 +-- .../settings/DataSettings/WebDavSettings.tsx | 33 +++++++++---- 7 files changed, 157 insertions(+), 91 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index beee13c6..01758be8 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -573,25 +573,29 @@ "empty_database_id": "Database_id is not configured" }, "title": "Data Settings", - "webdav.autoSync": "Auto Backup", - "webdav.autoSync.off": "Off", - "webdav.backup.button": "Backup to WebDAV", - "webdav.host": "WebDAV Host", - "webdav.host.placeholder": "http://localhost:8080", - "webdav.hours": "Hours", - "webdav.lastSync": "Last Backup", - "webdav.minutes": "Minutes", - "webdav.noSync": "Waiting for next backup", - "webdav.password": "WebDAV Password", - "webdav.path": "WebDAV Path", - "webdav.path.placeholder": "/backup", - "webdav.restore.button": "Restore from WebDAV", - "webdav.restore.content": "Restore from WebDAV will overwrite the current data, continue?", - "webdav.restore.title": "Restore from WebDAV", - "webdav.syncError": "Backup Error", - "webdav.syncStatus": "Backup Status", - "webdav.title": "WebDAV", - "webdav.user": "WebDAV User" + "webdav": { + "autoSync": "Auto Backup", + "autoSync.off": "Off", + "backup.button": "Backup to WebDAV", + "host": "WebDAV Host", + "host.placeholder": "http://localhost:8080", + "minute_interval_one": "{{count}} minute", + "minute_interval_other": "{{count}} minutes", + "hour_interval_one": "{{count}} hour", + "hour_interval_other": "{{count}} hours", + "lastSync": "Last Backup", + "noSync": "Waiting for next backup", + "password": "WebDAV Password", + "path": "WebDAV Path", + "path.placeholder": "/backup", + "restore.button": "Restore from WebDAV", + "restore.content": "Restore from WebDAV will overwrite the current data, continue?", + "restore.title": "Restore from WebDAV", + "syncError": "Backup Error", + "syncStatus": "Backup Status", + "title": "WebDAV", + "user": "WebDAV User" + } }, "display.custom.css": "Custom CSS", "display.custom.css.placeholder": "/* Put custom CSS here */", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 16f489ba..b0c23706 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -573,6 +573,29 @@ "empty_database_id": "Database_idが設定されていません" }, "title": "データ設定", + "webdav": { + "autoSync": "自動バックアップ", + "autoSync.off": "オフ", + "backup.button": "WebDAVにバックアップ", + "host": "WebDAVホスト", + "host.placeholder": "http://localhost:8080", + "minute_interval_one": "{{count}} 分", + "minute_interval_other": "{{count}} 分", + "hour_interval_one": "{{count}} 時間", + "hour_interval_other": "{{count}} 時間", + "lastSync": "最終バックアップ", + "noSync": "次回のバックアップを待機中", + "password": "WebDAVパスワード", + "path": "WebDAVパス", + "path.placeholder": "/backup", + "restore.button": "WebDAVから復元", + "restore.content": "WebDAVから復元すると現在のデータが上書きされます。続行しますか?", + "restore.title": "WebDAVから復元", + "syncError": "バックアップエラー", + "syncStatus": "バックアップ状態", + "title": "WebDAV", + "user": "WebDAVユーザー" + }, "webdav.autoSync": "自動バックアップ", "webdav.autoSync.off": "オフ", "webdav.backup.button": "WebDAVにバックアップ", @@ -591,7 +614,11 @@ "webdav.syncError": "バックアップエラー", "webdav.syncStatus": "バックアップ状態", "webdav.title": "WebDAV", - "webdav.user": "WebDAVユーザー" + "webdav.user": "WebDAVユーザー", + "minute_interval_one": "{{count}} 分", + "minute_interval_other": "{{count}} 分", + "hour_interval_one": "{{count}} 時間", + "hour_interval_other": "{{count}} 時間" }, "display.custom.css": "カスタムCSS", "display.custom.css.placeholder": "/* ここにカスタムCSSを入力 */", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 35b5cbd5..b78842ac 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -573,25 +573,31 @@ "empty_database_id": "Не настроен Database_id" }, "title": "Настройки данных", - "webdav.autoSync": "Автоматическое резервное копирование", - "webdav.autoSync.off": "Выключено", - "webdav.backup.button": "Резервное копирование на WebDAV", - "webdav.host": "Хост WebDAV", - "webdav.host.placeholder": "http://localhost:8080", - "webdav.hours": "часов", - "webdav.lastSync": "Последняя синхронизация", - "webdav.minutes": "минут", - "webdav.noSync": "Ожидание следующего резервного копирования", - "webdav.password": "Пароль WebDAV", - "webdav.path": "Путь WebDAV", - "webdav.path.placeholder": "/backup", - "webdav.restore.button": "Восстановление с WebDAV", - "webdav.restore.content": "Восстановление с WebDAV перезапишет текущие данные, продолжить?", - "webdav.restore.title": "Восстановление с WebDAV", - "webdav.syncError": "Ошибка резервного копирования", - "webdav.syncStatus": "Статус резервного копирования", - "webdav.title": "WebDAV", - "webdav.user": "Пользователь WebDAV" + "webdav": { + "autoSync": "Автоматическое резервное копирование", + "autoSync.off": "Выключено", + "backup.button": "Резервное копирование на WebDAV", + "host": "Хост WebDAV", + "host.placeholder": "http://localhost:8080", + "minute_interval_one": "{{count}} минута", + "minute_interval_few": "{{count}} минуты", + "minute_interval_many": "{{count}} минут", + "hour_interval_one": "{{count}} час", + "hour_interval_few": "{{count}} часа", + "hour_interval_many": "{{count}} часов", + "lastSync": "Последняя синхронизация", + "noSync": "Ожидание следующего резервного копирования", + "password": "Пароль WebDAV", + "path": "Путь WebDAV", + "path.placeholder": "/backup", + "restore.button": "Восстановление с WebDAV", + "restore.content": "Восстановление с WebDAV перезапишет текущие данные, продолжить?", + "restore.title": "Восстановление с WebDAV", + "syncError": "Ошибка резервного копирования", + "syncStatus": "Статус резервного копирования", + "title": "WebDAV", + "user": "Пользователь WebDAV" + } }, "display.custom.css": "Пользовательский CSS", "display.custom.css.placeholder": "/* Здесь введите пользовательский CSS */", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index a5a051b4..82b66eb2 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -573,25 +573,33 @@ "empty_database_id": "未配置Database_id" }, "title": "数据设置", - "webdav.autoSync": "自动备份", - "webdav.autoSync.off": "关闭", - "webdav.backup.button": "备份到 WebDAV", - "webdav.host": "WebDAV 地址", - "webdav.host.placeholder": "http://localhost:8080", - "webdav.hours": "小时", - "webdav.lastSync": "上次备份时间", - "webdav.minutes": "分钟", - "webdav.noSync": "等待下次备份", - "webdav.password": "WebDAV 密码", - "webdav.path": "WebDAV 路径", - "webdav.path.placeholder": "/backup", - "webdav.restore.button": "从 WebDAV 恢复", - "webdav.restore.content": "从 WebDAV 恢复将覆盖当前数据,是否继续?", - "webdav.restore.title": "从 WebDAV 恢复", - "webdav.syncError": "备份错误", - "webdav.syncStatus": "备份状态", - "webdav.title": "WebDAV", - "webdav.user": "WebDAV 用户名" + "webdav": { + "autoSync": "自动备份", + "autoSync.off": "关闭", + "backup.button": "备份到 WebDAV", + "host": "WebDAV 地址", + "host.placeholder": "http://localhost:8080", + "minute_interval_one": "{{count}} 分钟", + "minute_interval_other": "{{count}} 分钟", + "hour_interval_one": "{{count}} 小时", + "hour_interval_other": "{{count}} 小时", + "lastSync": "上次备份时间", + "noSync": "等待下次备份", + "password": "WebDAV 密码", + "path": "WebDAV 路径", + "path.placeholder": "/backup", + "restore.button": "从 WebDAV 恢复", + "restore.content": "从 WebDAV 恢复将覆盖当前数据,是否继续?", + "restore.title": "从 WebDAV 恢复", + "syncError": "备份错误", + "syncStatus": "备份状态", + "title": "WebDAV", + "user": "WebDAV 用户名" + }, + "minute_interval_one": "{{count}} 分钟", + "minute_interval_other": "{{count}} 分钟", + "hour_interval_one": "{{count}} 小时", + "hour_interval_other": "{{count}} 小时" }, "display.custom.css": "自定义 CSS", "display.custom.css.placeholder": "/* 这里写自定义CSS */", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index da003c51..fb12f08f 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -571,27 +571,35 @@ "empty_database_id": "未配置Database_id" }, "title": "數據設定", - "webdav.autoSync": "自動備份", - "webdav.autoSync.off": "關閉", - "webdav.backup.button": "從 WebDAV 備份", - "webdav.host": "WebDAV 主機位址", - "webdav.host.placeholder": "http://localhost:8080", - "webdav.hours": "小時", - "webdav.lastSync": "上次同步時間", - "webdav.minutes": "分鐘", - "webdav.noSync": "等待下次備份", - "webdav.password": "WebDAV 密碼", - "webdav.path": "WebDAV Path", - "webdav.path.placeholder": "/backup", - "webdav.restore.button": "從 WebDAV 恢復", - "webdav.restore.content": "從 WebDAV 恢復將覆蓋當前資料,是否繼續?", - "webdav.restore.title": "從 WebDAV 恢復", - "webdav.syncError": "備份錯誤", - "webdav.syncStatus": "備份狀態", - "webdav.title": "WebDAV", - "webdav.user": "WebDAV 使用者名稱", + "webdav": { + "autoSync": "自動備份", + "autoSync.off": "關閉", + "backup.button": "備份到 WebDAV", + "host": "WebDAV 主機位址", + "host.placeholder": "http://localhost:8080", + "minute_interval_one": "{{count}} 分鐘", + "minute_interval_other": "{{count}} 分鐘", + "hour_interval_one": "{{count}} 小時", + "hour_interval_other": "{{count}} 小時", + "lastSync": "上次備份時間", + "noSync": "等待下次備份", + "password": "WebDAV 密碼", + "path": "WebDAV 路徑", + "path.placeholder": "/backup", + "restore.button": "從 WebDAV 恢復", + "restore.content": "從 WebDAV 恢復將覆蓋當前資料,是否繼續?", + "restore.title": "從 WebDAV 恢復", + "syncError": "備份錯誤", + "syncStatus": "備份狀態", + "title": "WebDAV", + "user": "WebDAV 使用者名稱" + }, "app_data": "應用數據", - "app_logs": "應用日誌" + "app_logs": "應用日誌", + "minute_interval_one": "{{count}} 分鐘", + "minute_interval_other": "{{count}} 分鐘", + "hour_interval_one": "{{count}} 小時", + "hour_interval_other": "{{count}} 小時" }, "display.custom.css": "自定義 CSS", "display.custom.css.placeholder": "/* 這裡寫自定義 CSS */", diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index 9fc325b6..45324efa 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -87,7 +87,7 @@ const NotionSettings: FC = () => { value={notionDatabaseID || ''} onChange={handleNotionDatabaseIdChange} onBlur={handleNotionDatabaseIdChange} - style={{ width: 315 }} + style={{ width: 250 }} placeholder={t('settings.data.notion.database_id_placeholder')} /> @@ -95,7 +95,7 @@ const NotionSettings: FC = () => { {t('settings.data.notion.api_key')} - + { style={{ width: 250 }} placeholder={t('settings.data.notion.api_key_placeholder')} /> - diff --git a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx index d641ee8f..1edf6753 100644 --- a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx @@ -163,7 +163,6 @@ const WebDavSettings: FC = () => { {t('settings.general.backup.title')} - {/* 添加 在线备份 在线还原 按钮 */} @@ -178,18 +177,32 @@ const WebDavSettings: FC = () => { {webdavSync && syncInterval > 0 && ( From b2c6662192a7121ca3ed9f5a3c7d4416b61ce39c Mon Sep 17 00:00:00 2001 From: lucifer9 Date: Tue, 18 Feb 2025 16:12:31 +0800 Subject: [PATCH 05/66] adjust Notion database ID input width in DataSettings --- src/renderer/src/pages/settings/DataSettings/DataSettings.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index 45324efa..bb7d3ac9 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -81,13 +81,13 @@ const NotionSettings: FC = () => { {t('settings.data.notion.database_id')} - + From de76d3fedc737bc08b9ed98f0ee600f46942cd8b Mon Sep 17 00:00:00 2001 From: ousugo Date: Tue, 18 Feb 2025 14:27:47 +0800 Subject: [PATCH 06/66] fix: Improve DragableList component styling and placeholder handling --- src/renderer/src/components/DragableList/index.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/components/DragableList/index.tsx b/src/renderer/src/components/DragableList/index.tsx index 6be5dcd6..5d9acc94 100644 --- a/src/renderer/src/components/DragableList/index.tsx +++ b/src/renderer/src/components/DragableList/index.tsx @@ -46,23 +46,28 @@ const DragableList: FC> = ({ {(provided) => ( -
+
{list.map((item, index) => { const id = item.id || item return ( - - {(provided) => ( + + {(provided, snapshot) => (
+ style={{ + ...listStyle, + ...provided.draggableProps.style, + marginBottom: index === list.length - 1 && !snapshot.isDragging ? 0 : 8 + }}> {children(item, index)}
)}
) })} + {provided.placeholder}
)} From f8fce871daf4e19c21b315ecffc2025c3c04ae8d Mon Sep 17 00:00:00 2001 From: ousugo Date: Mon, 17 Feb 2025 23:08:17 +0800 Subject: [PATCH 07/66] fix: Recalculate token consumption after modifying the message, resolve #1829 --- .../src/pages/home/Messages/Message.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/pages/home/Messages/Message.tsx b/src/renderer/src/pages/home/Messages/Message.tsx index 3f793a36..e0dc3a0d 100644 --- a/src/renderer/src/pages/home/Messages/Message.tsx +++ b/src/renderer/src/pages/home/Messages/Message.tsx @@ -6,8 +6,8 @@ import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings' import { useTopic } from '@renderer/hooks/useTopic' import { fetchChatCompletion } from '@renderer/services/ApiService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' -import { getMessageModelId } from '@renderer/services/MessagesService' -import { estimateMessageUsage } from '@renderer/services/TokenService' +import { getContextCount, getMessageModelId } from '@renderer/services/MessagesService' +import { estimateHistoryTokens, estimateMessageUsage } from '@renderer/services/TokenService' import { Message, Topic } from '@renderer/types' import { classNames, runAsyncFunction } from '@renderer/utils' import { Divider } from 'antd' @@ -75,13 +75,22 @@ const MessageItem: FC = ({ const messageBackground = getMessageBackground(isBubbleStyle, isAssistantMessage) const onEditMessage = useCallback( - (msg: Message) => { + async (msg: Message) => { + const usage = await estimateMessageUsage(msg) + msg.usage = usage + setMessage(msg) const messages = onGetMessages?.()?.map((m) => (m.id === message.id ? msg : m)) messages && onSetMessages?.(messages) topic && db.topics.update(topic.id, { messages }) + + if (messages) { + const tokensCount = await estimateHistoryTokens(assistant, messages) + const contextCount = getContextCount(assistant, messages) + EventEmitter.emit(EVENT_NAMES.ESTIMATED_TOKEN_COUNT, { tokensCount, contextCount }) + } }, - [message.id, onGetMessages, onSetMessages, topic] + [message.id, onGetMessages, onSetMessages, topic, assistant] ) const messageHighlightHandler = (highlight: boolean = true) => { From 1d5ace0fb2758629a75a3055713345a7245d64fb Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Tue, 18 Feb 2025 18:16:14 +0800 Subject: [PATCH 08/66] feat: Add 'off' option for reasoning effort in assistant settings --- src/renderer/src/i18n/locales/en-us.json | 1 + src/renderer/src/i18n/locales/ja-jp.json | 1 + src/renderer/src/i18n/locales/ru-ru.json | 1 + src/renderer/src/i18n/locales/zh-cn.json | 1 + src/renderer/src/i18n/locales/zh-tw.json | 1 + .../settings/AssistantSettings/AssistantModelSettings.tsx | 3 ++- 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 01758be8..3e58f674 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -51,6 +51,7 @@ "settings.reasoning_effort.high": "high", "settings.reasoning_effort.low": "low", "settings.reasoning_effort.medium": "medium", + "settings.reasoning_effort.off": "off", "settings.reasoning_effort.tip": "Only supports reasoning models", "title": "Assistants" }, diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index b0c23706..aacfe3b5 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -52,6 +52,7 @@ "settings.reasoning_effort.high": "長い", "settings.reasoning_effort.low": "短い", "settings.reasoning_effort.medium": "中程度", + "settings.reasoning_effort.off": "オフ", "settings.reasoning_effort.tip": "この設定は推論モデルのみサポートしています" }, "auth": { diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index b78842ac..8aae527b 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -52,6 +52,7 @@ "settings.reasoning_effort.high": "Длинная", "settings.reasoning_effort.low": "Короткая", "settings.reasoning_effort.medium": "Средняя", + "settings.reasoning_effort.off": "Выключено", "settings.reasoning_effort.tip": "Эта настройка поддерживается только моделями с рассуждением" }, "auth": { diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 82b66eb2..55cc73e0 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -51,6 +51,7 @@ "settings.reasoning_effort.high": "长", "settings.reasoning_effort.low": "短", "settings.reasoning_effort.medium": "中", + "settings.reasoning_effort.off": "关", "settings.reasoning_effort.tip": "该设置仅支持推理模型", "title": "助手" }, diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index fb12f08f..f6f6d2b8 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -51,6 +51,7 @@ "settings.reasoning_effort.high": "長", "settings.reasoning_effort.low": "短", "settings.reasoning_effort.medium": "中", + "settings.reasoning_effort.off": "關", "settings.reasoning_effort.tip": "該設置僅支持推理模型", "title": "助手" }, diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx index 580018e4..6d31beea 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx @@ -23,7 +23,7 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA 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 [reasoningEffort, setReasoningEffort] = useState(assistant?.settings?.reasoning_effort ?? 'medium') + const [reasoningEffort, setReasoningEffort] = useState(assistant?.settings?.reasoning_effort) const [streamOutput, setStreamOutput] = useState(assistant?.settings?.streamOutput ?? true) const [defaultModel, setDefaultModel] = useState(assistant?.defaultModel) const [topP, setTopP] = useState(assistant?.settings?.topP ?? 1) @@ -391,6 +391,7 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA {t('assistants.settings.reasoning_effort.low')} {t('assistants.settings.reasoning_effort.medium')} {t('assistants.settings.reasoning_effort.high')} + {t('assistants.settings.reasoning_effort.off')} From 3c958c3d11870ee73766d7c01406b4b3361b39df Mon Sep 17 00:00:00 2001 From: eeee0717 Date: Tue, 18 Feb 2025 18:22:07 +0800 Subject: [PATCH 09/66] =?UTF-8?q?feat:=20=E7=9B=AE=E5=BD=95=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E5=8F=AF=E8=A7=86=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/services/KnowledgeService.ts | 17 ++++++++++++++++- src/renderer/src/hooks/useKnowledge.ts | 18 ++++++++++++++++++ .../src/pages/knowledge/KnowledgeContent.tsx | 11 +++++++++-- .../pages/knowledge/components/StatusIcon.tsx | 11 ++++------- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/main/services/KnowledgeService.ts b/src/main/services/KnowledgeService.ts index 43b11ebe..53f66130 100644 --- a/src/main/services/KnowledgeService.ts +++ b/src/main/services/KnowledgeService.ts @@ -15,6 +15,8 @@ import { FileType, KnowledgeBaseParams, KnowledgeItem } from '@types' import { app } from 'electron' import { v4 as uuidv4 } from 'uuid' +import { windowService } from './WindowService' + class KnowledgeService { private storageDir = path.join(app.getPath('userData'), 'Data', 'KnowledgeBase') @@ -83,10 +85,23 @@ class KnowledgeService { ): Promise => { const ragApplication = await this.getRagApplication(base) + const sendDirectoryProcessingPercent = (totalFiles: number, processedFiles: number) => { + const mainWindow = windowService.getMainWindow() + mainWindow?.webContents.send(base.id, (processedFiles / totalFiles) * 100) + } + if (item.type === 'directory') { const directory = item.content as string const files = getAllFiles(directory) - const loaderPromises = files.map((file) => addFileLoader(ragApplication, file, base, forceReload)) + const totalFiles = files.length + let processedFiles = 0 + const loaderPromises = files.map(async (file) => { + const result = await addFileLoader(ragApplication, file, base, forceReload) + processedFiles++ + + sendDirectoryProcessingPercent(totalFiles, processedFiles) + return result + }) const loaderResults = await Promise.all(loaderPromises) const uniqueIds = loaderResults.map((result) => result.uniqueId) return { diff --git a/src/renderer/src/hooks/useKnowledge.ts b/src/renderer/src/hooks/useKnowledge.ts index dbb90ca8..18a53324 100644 --- a/src/renderer/src/hooks/useKnowledge.ts +++ b/src/renderer/src/hooks/useKnowledge.ts @@ -198,6 +198,23 @@ export const useKnowledge = (baseId: string) => { return base?.items.filter((item) => item.type === type && item.processingStatus !== undefined) || [] } + // 获取目录处理进度 + const getDirectoryProcessingPercent = (itemId: string) => { + const [percent, setPercent] = useState(0) + + useEffect(() => { + const cleanup = window.electron.ipcRenderer.on(itemId, (_, progressingPercent: number) => { + setPercent(progressingPercent) + }) + + return () => { + cleanup() + } + }, [itemId]) + + return percent + } + // 清除已完成的项目 const clearCompleted = () => { dispatch(clearCompletedProcessing({ baseId })) @@ -280,6 +297,7 @@ export const useKnowledge = (baseId: string) => { refreshItem, getProcessingStatus, getProcessingItemsByType, + getDirectoryProcessingPercent, clearCompleted, clearAll, removeItem, diff --git a/src/renderer/src/pages/knowledge/KnowledgeContent.tsx b/src/renderer/src/pages/knowledge/KnowledgeContent.tsx index ef4bb511..d4ebf062 100644 --- a/src/renderer/src/pages/knowledge/KnowledgeContent.tsx +++ b/src/renderer/src/pages/knowledge/KnowledgeContent.tsx @@ -53,6 +53,7 @@ const KnowledgeContent: FC = ({ selectedBase }) => { addSitemap, removeItem, getProcessingStatus, + getDirectoryProcessingPercent, addNote, addDirectory } = useKnowledge(selectedBase.id || '') @@ -63,6 +64,7 @@ const KnowledgeContent: FC = ({ selectedBase }) => { if (!base) { return null } + const progressingPercent = getDirectoryProcessingPercent(base?.id) const handleAddFile = () => { if (disabled) { @@ -113,7 +115,7 @@ const KnowledgeContent: FC = ({ selectedBase }) => { inputPlaceholder: t('knowledge.url_placeholder'), inputProps: { rows: 10, - onPressEnter: () => {} + onPressEnter: () => { } } }) @@ -271,7 +273,12 @@ const KnowledgeContent: FC = ({ selectedBase }) => { {item.uniqueId && - + + From 9e283d6930cd105b2be4fda6180b8e40702f2532 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Tue, 18 Feb 2025 20:54:29 +0800 Subject: [PATCH 13/66] fix: Update agent knowledge base field name and handling --- .../src/pages/agents/components/AddAgentPopup.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/pages/agents/components/AddAgentPopup.tsx b/src/renderer/src/pages/agents/components/AddAgentPopup.tsx index 506a28c8..8e9927ce 100644 --- a/src/renderer/src/pages/agents/components/AddAgentPopup.tsx +++ b/src/renderer/src/pages/agents/components/AddAgentPopup.tsx @@ -25,7 +25,7 @@ type FieldType = { id: string name: string prompt: string - knowledge_base_id: string[] + knowledge_base_ids: string[] } const PopupContainer: React.FC = ({ resolve }) => { @@ -57,9 +57,9 @@ const PopupContainer: React.FC = ({ resolve }) => { const _agent: Agent = { id: uuid(), name: values.name, - knowledge_bases: values.knowledge_base_id - .map((id) => knowledgeState.bases.find((t) => t.id === id)) - .filter((base): base is KnowledgeBase => base !== undefined), + knowledge_bases: values.knowledge_base_ids + ?.map((id) => knowledgeState.bases.find((t) => t.id === id)) + ?.filter((base): base is KnowledgeBase => base !== undefined), emoji: _emoji, prompt: values.prompt, defaultModel: getDefaultModel(), @@ -156,7 +156,7 @@ const PopupContainer: React.FC = ({ resolve }) => { />
{showKnowledgeIcon && ( - + {t('settings.data.webdav.autoSync.off')} - - {t('settings.data.webdav.minute_interval', { count: 1 })} - - - {t('settings.data.webdav.minute_interval', { count: 5 })} - - - {t('settings.data.webdav.minute_interval', { count: 15 })} - - - {t('settings.data.webdav.minute_interval', { count: 30 })} - - - {t('settings.data.webdav.hour_interval', { count: 1 })} - - - {t('settings.data.webdav.hour_interval', { count: 2 })} - - - {t('settings.data.webdav.hour_interval', { count: 6 })} - - - {t('settings.data.webdav.hour_interval', { count: 12 })} - - - {t('settings.data.webdav.hour_interval', { count: 24 })} - + {t('settings.data.webdav.minute_interval', { count: 1 })} + {t('settings.data.webdav.minute_interval', { count: 5 })} + {t('settings.data.webdav.minute_interval', { count: 15 })} + {t('settings.data.webdav.minute_interval', { count: 30 })} + {t('settings.data.webdav.hour_interval', { count: 1 })} + {t('settings.data.webdav.hour_interval', { count: 2 })} + {t('settings.data.webdav.hour_interval', { count: 6 })} + {t('settings.data.webdav.hour_interval', { count: 12 })} + {t('settings.data.webdav.hour_interval', { count: 24 })}
{webdavSync && syncInterval > 0 && ( From b38a9c954a6a03baa96549401cbc03b95551947b Mon Sep 17 00:00:00 2001 From: Yrom Date: Tue, 18 Feb 2025 20:52:25 +0800 Subject: [PATCH 15/66] feat: Enable search capability for Qwen commercial version model --- src/renderer/src/config/models.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 2b9740b1..bb863d6b 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -1668,6 +1668,11 @@ export function isWebSearchModel(model: Model): boolean { if (provider.id === 'zhipu') { return model?.id?.startsWith('glm-4-') } + if (provider.id === 'dashscope') { + const models = ['qwen-turbo', 'qwen-max', 'qwen-plus'] + // matches id like qwen-max-0919, qwen-max-latest + return models.some((i) => model.id.startsWith(i)) + } return false } @@ -1680,7 +1685,14 @@ export function getOpenAIWebSearchParams(assistant: Assistant, model: Model): Re if (model.provider === 'hunyuan') { return { enable_enhancement: true } } - + if (model.provider === 'dashscope') { + return { + enable_search: true, + search_options: { + forced_search: true + } + } + } return { tools: webSearchTools } From d07e1360371819c7493b663d7c8bfb697876bb3a Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Tue, 18 Feb 2025 21:16:59 +0800 Subject: [PATCH 16/66] fix: Add top margin to 'Add Assistant' button in AssistantsTab --- src/renderer/src/pages/home/Tabs/AssistantsTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx index efb8c13b..4eee98a6 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx @@ -153,7 +153,7 @@ const Assistants: FC = ({ }} {!dragging && ( - + {t('chat.add.assistant.title')} From 7159481217b8feafd7dce36d4c674569e0ac7d32 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: Wed, 19 Feb 2025 04:37:23 +0800 Subject: [PATCH 17/66] Updated provider information --- src/renderer/src/config/models.ts | 7 +++++-- src/renderer/src/config/providers.ts | 10 +++++----- src/renderer/src/store/llm.ts | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index bb863d6b..cd76e5b2 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -179,9 +179,9 @@ export function getModelLogo(modelId: string) { pixtral: isLight ? PixtralModelLogo : PixtralModelLogoDark, jina: isLight ? JinaModelLogo : JinaModelLogoDark, abab: isLight ? MinimaxModelLogo : MinimaxModelLogoDark, + minimax: isLight ? MinimaxModelLogo : MinimaxModelLogoDark, o3: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, o1: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, - 'kimi-latest': isLight ? MoonshotModelLogo : MoonshotModelLogoDark, 'gpt-3': isLight ? ChatGPT35ModelLogo : ChatGPT35ModelLogoDark, 'gpt-4': isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark, gpts: isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark, @@ -196,13 +196,16 @@ export function getModelLogo(modelId: string) { glm: isLight ? ChatGLMModelLogo : ChatGLMModelLogoDark, deepseek: isLight ? DeepSeekModelLogo : DeepSeekModelLogoDark, qwen: isLight ? QwenModelLogo : QwenModelLogoDark, - qwq: isLight ? QwenModelLogo : QwenModelLogoDark, + "qwq-": isLight ? QwenModelLogo : QwenModelLogoDark, + "qvq-": isLight ? QwenModelLogo : QwenModelLogoDark, + Omni: isLight ? QwenModelLogo : QwenModelLogoDark, gemma: isLight ? GemmaModelLogo : GemmaModelLogoDark, 'yi-': isLight ? YiModelLogo : YiModelLogoDark, llama: isLight ? LlamaModelLogo : LlamaModelLogoDark, mixtral: isLight ? MistralModelLogo : MistralModelLogo, mistral: isLight ? MistralModelLogo : MistralModelLogoDark, moonshot: isLight ? MoonshotModelLogo : MoonshotModelLogoDark, + kimi: isLight ? MoonshotModelLogo : MoonshotModelLogoDark, phi: isLight ? MicrosoftModelLogo : MicrosoftModelLogoDark, baichuan: isLight ? BaichuanModelLogo : BaichuanModelLogoDark, claude: isLight ? ClaudeModelLogo : ClaudeModelLogoDark, diff --git a/src/renderer/src/config/providers.ts b/src/renderer/src/config/providers.ts index 9d2837de..a68d81ae 100644 --- a/src/renderer/src/config/providers.ts +++ b/src/renderer/src/config/providers.ts @@ -212,13 +212,13 @@ export const PROVIDER_CONFIG = { }, dmxapi: { api: { - url: 'https://www.dmxapi.com' + url: 'https://www.dmxapi.cn' }, websites: { - 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' + official: 'https://www.dmxapi.cn/register?aff=bwwY', + apiKey: 'https://www.dmxapi.cn/register?aff=bwwY', + docs: 'https://dmxapi.cn/models.html#code-block', + models: 'https://www.dmxapi.cn/pricing' } }, perplexity: { diff --git a/src/renderer/src/store/llm.ts b/src/renderer/src/store/llm.ts index 2396c6ef..3f2fc10d 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://www.dmxapi.com', + apiHost: 'https://www.dmxapi.cn', models: SYSTEM_MODELS.dmxapi, isSystem: true, enabled: false From 9ffe92d378b70934e91b5b1450733f7170af5598 Mon Sep 17 00:00:00 2001 From: icinggslits Date: Wed, 19 Feb 2025 03:18:31 +0800 Subject: [PATCH 18/66] fix: Update language options promptly --- src/renderer/src/config/translate.ts | 10 ++++++++++ src/renderer/src/pages/translate/TranslatePage.tsx | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/config/translate.ts b/src/renderer/src/config/translate.ts index ee5c2acf..4c5054f4 100644 --- a/src/renderer/src/config/translate.ts +++ b/src/renderer/src/config/translate.ts @@ -57,3 +57,13 @@ export const TranslateLanguageOptions = [ emoji: '🇸🇦' } ] + +export const translateLanguageOptions = (): typeof TranslateLanguageOptions => { + return TranslateLanguageOptions.map((option) => { + return { + value: option.value, + label: i18n.t(`languages.${option.value}`), + emoji: option.emoji + } + }) +} diff --git a/src/renderer/src/pages/translate/TranslatePage.tsx b/src/renderer/src/pages/translate/TranslatePage.tsx index c6bf516e..ac5d3ce8 100644 --- a/src/renderer/src/pages/translate/TranslatePage.tsx +++ b/src/renderer/src/pages/translate/TranslatePage.tsx @@ -2,7 +2,7 @@ import { CheckOutlined, SendOutlined, SettingOutlined, SwapOutlined, WarningOutl import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar' import CopyIcon from '@renderer/components/Icons/CopyIcon' import { isLocalAi } from '@renderer/config/env' -import { TranslateLanguageOptions } from '@renderer/config/translate' +import { translateLanguageOptions } from '@renderer/config/translate' import db from '@renderer/databases' import { useDefaultModel } from '@renderer/hooks/useAssistant' import { fetchTranslate } from '@renderer/services/ApiService' @@ -129,7 +129,7 @@ const TranslatePage: FC = () => { value={targetLanguage} style={{ width: 180 }} optionFilterProp="label" - options={TranslateLanguageOptions} + options={translateLanguageOptions()} onChange={(value) => { setTargetLanguage(value) db.settings.put({ id: 'translate:target:language', value }) From 045708d9b3bf2ac755e01cab9a256ebeee43e907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George=C2=B7Dong?= Date: Tue, 18 Feb 2025 23:57:38 +0800 Subject: [PATCH 19/66] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=88=B0Notion=E7=9A=84=E7=9B=B8=E5=85=B3=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/i18n/locales/en-us.json | 10 +++++----- src/renderer/src/i18n/locales/ja-jp.json | 10 +++++----- src/renderer/src/i18n/locales/ru-ru.json | 10 +++++----- src/renderer/src/i18n/locales/zh-cn.json | 10 +++++----- src/renderer/src/i18n/locales/zh-tw.json | 12 ++++++------ 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 2becd102..28a70e02 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -355,7 +355,7 @@ "error.invalid.enter.model": "Please select a model", "error.invalid.proxy.url": "Invalid proxy URL", "error.invalid.webdav": "Invalid WebDAV settings", - "error.notion.export": "Notion import failed", + "error.notion.export": "Failed to export to Notion. Please check connection status and configuration according to documentation", "error.notion.no_api_key": "Notion ApiKey or Notion DatabaseID is not configured", "group.delete.content": "Deleting a group message will delete the user's question and all assistant's answers", "group.delete.title": "Delete Group Message", @@ -377,13 +377,13 @@ "reset.double.confirm.title": "DATA LOST !!!", "restore.success": "Restored successfully", "save.success.title": "Saved successfully", - "success.notion.export": "Notion import successful", + "success.notion.export": "Successfully exported to Notion", "switch.disabled": "Please wait for the current reply to complete", "topic.added": "New topic added", "upgrade.success.button": "Restart", "upgrade.success.content": "Please restart the application to complete the upgrade", "upgrade.success.title": "Upgrade successfully", - "warn.notion.exporting": "Notion is importing, please do not import repeatedly", + "warn.notion.exporting": "Exporting to Notion, please do not request export repeatedly!", "error.invalid.api.host": "Invalid API Host", "error.invalid.api.key": "Invalid API Key" }, @@ -569,9 +569,9 @@ "notion.title": "Notion Configuration", "notion.check": { "button": "Check", - "fail": "Connection failed, please check the configuration", + "fail": "Connection failed, please check network and Api_key and Database_id", "success": "Connection successful", - "error": "Connection error, please check the network", + "error": "Connection error, please check network configuration and Api_key and Database_id", "empty_api_key": "Api_key is not configured", "empty_database_id": "Database_id is not configured" }, diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index d655b05f..faaab183 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -354,7 +354,7 @@ "error.invalid.enter.model": "モデルを選択してください", "error.invalid.proxy.url": "無効なプロキシURL", "error.invalid.webdav": "無効なWebDAV設定", - "error.notion.export": "Notion インポートに失敗", + "error.notion.export": "Notionへのエクスポートに失敗しました。接続状態と設定を確認してください", "error.notion.no_api_key": "Notion ApiKey または Notion DatabaseID が設定されていません", "group.delete.content": "分組メッセージを削除するとユーザーの質問と助け手の回答がすべて削除されます", "group.delete.title": "分組メッセージを削除", @@ -376,13 +376,13 @@ "reset.double.confirm.title": "データが失われます!!!", "restore.success": "復元に成功しました", "save.success.title": "保存に成功しました", - "success.notion.export": "Notion へのインポートに成功", + "success.notion.export": "Notionへのエクスポートに成功しました", "switch.disabled": "現在の応答が完了するまで切り替えを無効にします", "topic.added": "新しいトピックが追加されました", "upgrade.success.button": "再起動", "upgrade.success.content": "アップグレードを完了するためにアプリケーションを再起動してください", "upgrade.success.title": "アップグレードに成功しました", - "warn.notion.exporting": "Notion 正在インポート中です。重複インポートしないでください。", + "warn.notion.exporting": "Notionにエクスポート中です。重複してエクスポートしないでください! ", "error.enter.name": "ナレッジベース名を入力してください", "error.invalid.api.host": "無効なAPIアドレスです", "error.invalid.api.key": "無効なAPIキーです" @@ -569,9 +569,9 @@ "notion.title": "Notion 設定", "notion.check": { "button": "確認", - "fail": "接続に失敗しました。設定を確認してください。", + "fail": "接続エラー、ネットワーク設定とApi_keyとDatabase_idを確認してください", "success": "接続に成功しました。", - "error": "接続エラーが発生しました。ネットワークを確認してください。", + "error": "接続エラー、ネットワーク設定とApi_keyとDatabase_idを確認してください", "empty_api_key": "Api_keyが設定されていません", "empty_database_id": "Database_idが設定されていません" }, diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 4cc2d22e..ae7e54b9 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -355,7 +355,7 @@ "error.invalid.enter.model": "Пожалуйста, выберите модель", "error.invalid.proxy.url": "Неверный URL прокси", "error.invalid.webdav": "Неверные настройки WebDAV", - "error.notion.export": "Импорт в Notion не удался", + "error.notion.export": "Ошибка экспорта в Notion, пожалуйста, проверьте состояние подключения и настройки в документации", "error.notion.no_api_key": "Notion ApiKey или Notion DatabaseID не настроен", "group.delete.content": "Удаление группы сообщений удалит пользовательский вопрос и все ответы помощника", "group.delete.title": "Удалить группу сообщений", @@ -377,13 +377,13 @@ "reset.double.confirm.title": "ДАННЫЕ БУДУТ УТЕРЯНЫ !!!", "restore.success": "Успешно восстановлено", "save.success.title": "Успешно сохранено", - "success.notion.export": "Импорт в Notion выполнен успешно", + "success.notion.export": "Успешный экспорт в Notion", "switch.disabled": "Пожалуйста, дождитесь завершения текущего ответа", "topic.added": "Новый топик добавлен", "upgrade.success.button": "Перезапустить", "upgrade.success.content": "Пожалуйста, перезапустите приложение для завершения обновления", "upgrade.success.title": "Обновление успешно", - "warn.notion.exporting": "Идет импорт в Notion, пожалуйста, не повторяйте импорт", + "warn.notion.exporting": "Экспортируется в Notion, пожалуйста, не отправляйте повторные запросы!", "error.invalid.api.host": "Неверный API адрес", "error.invalid.api.key": "Неверный API ключ" }, @@ -569,9 +569,9 @@ "notion.title": "Настройки Notion", "notion.check": { "button": "Проверить", - "fail": "Ошибка подключения, проверьте настройки", + "fail": "Не удалось подключиться, пожалуйста, проверьте сеть и правильность Api_key и Database_id", "success": "Подключение успешно", - "error": "Ошибка подключения, проверьте сеть", + "error": "Аномалия в подключении, пожалуйста, проверьте настройки сети, а также правильность Api_key и Database_id", "empty_api_key": "Не настроен Api_key", "empty_database_id": "Не настроен Database_id" }, diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index feb9470d..37a763a2 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -357,7 +357,7 @@ "error.invalid.enter.model": "请选择一个模型", "error.invalid.proxy.url": "无效的代理地址", "error.invalid.webdav": "无效的 WebDAV 设置", - "error.notion.export": "Notion 导入失败", + "error.notion.export": "导出Notion错误,请检查连接状态并对照文档检查配置", "error.notion.no_api_key": "未配置Notion ApiKey或Notion DatabaseID", "group.delete.content": "删除分组消息会删除用户提问和所有助手的回答", "group.delete.title": "删除分组消息", @@ -379,13 +379,13 @@ "reset.double.confirm.title": "数据丢失!!!", "restore.success": "恢复成功", "save.success.title": "保存成功", - "success.notion.export": "导入Notion成功", + "success.notion.export": "成功导出到Notion", "switch.disabled": "请等待当前回复完成后操作", "topic.added": "话题添加成功", "upgrade.success.button": "重启", "upgrade.success.content": "重启用以完成升级", "upgrade.success.title": "升级成功", - "warn.notion.exporting": "Notion正在导入,请勿重复导入" + "warn.notion.exporting": "正在导出到Notion, 请勿重复请求导出!" }, "minapp": { "sidebar.add.title": "添加到侧边栏", @@ -569,9 +569,9 @@ "notion.title": "Notion 配置", "notion.check": { "button": "检查", - "fail": "连接失败,请检查配置", + "fail": "连接失败,请检查网络及Api_key和Database_id是否正确", "success": "连接成功", - "error": "连接异常,请检查网络", + "error": "连接异常,请检查网络及Api_key和Database_id是否正确", "empty_api_key": "未配置Api_key", "empty_database_id": "未配置Database_id" }, diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 3b88c689..000f1b3f 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -355,7 +355,7 @@ "error.invalid.enter.model": "請選擇一個模型", "error.invalid.proxy.url": "無效的代理 URL", "error.invalid.webdav": "無效的 WebDAV 設定", - "error.notion.export": "Notion 匯入失敗", + "error.notion.export": "導出Notion錯誤,請檢查連接狀態並對照文檔檢查配置", "error.notion.no_api_key": "未配置 Notion ApiKey 或 Notion DatabaseID", "group.delete.content": "刪除分組消息會刪除用戶提問和所有助手的回答", "group.delete.title": "刪除分組消息", @@ -377,13 +377,13 @@ "reset.double.confirm.title": "資料將會丟失!!!", "restore.success": "恢復成功", "save.success.title": "保存成功", - "success.notion.export": "匯入 Notion 成功", + "success.notion.export": "成功導出到Notion", "switch.disabled": "請等待當前回覆完成", "topic.added": "新話題已添加", "upgrade.success.button": "重新啟動", "upgrade.success.content": "請重新啟動應用以完成升級", "upgrade.success.title": "升級成功", - "warn.notion.exporting": "Notion 正在匯入,請勿重複匯入", + "warn.notion.exporting": "正在導出到Notion,請勿重複請求導出!", "error.invalid.api.host": "無效的 API 位址", "error.invalid.api.key": "無效的 API 密鑰" }, @@ -560,16 +560,16 @@ "title": "清除緩存" }, "data.title": "數據目錄", - "notion.api_key": "Notion 金鑰", + "notion.api_key": "Notion 密鑰", "notion.api_key_placeholder": "請輸入Notion 密鑰", "notion.database_id": "Notion 資料庫 ID", "notion.database_id_placeholder": "請輸入Notion 資料庫 ID", "notion.title": "Notion 配置", "notion.check": { "button": "檢查", - "fail": "連線失敗,請檢查配置", + "fail": "連接失敗,請檢查網絡及Api_key和Database_id是否正確", "success": "連線成功", - "error": "連線異常,請檢查網路", + "error": "連接異常,請檢查網絡及Api_key和Database_id是否正確", "empty_api_key": "未配置Api_key", "empty_database_id": "未配置Database_id" }, From 6aaa3def0dae80b3ab4a4fb556eb48feef91199d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George=C2=B7Dong?= Date: Wed, 19 Feb 2025 00:11:48 +0800 Subject: [PATCH 20/66] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0Notion=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E6=8C=89=E9=92=AETooltip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/i18n/locales/en-us.json | 1 + src/renderer/src/i18n/locales/ja-jp.json | 1 + src/renderer/src/i18n/locales/ru-ru.json | 1 + src/renderer/src/i18n/locales/zh-cn.json | 1 + src/renderer/src/i18n/locales/zh-tw.json | 1 + .../pages/settings/DataSettings/DataSettings.tsx | 16 ++++++++-------- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 28a70e02..d33b6cbc 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -567,6 +567,7 @@ "notion.database_id": "Notion Database ID", "notion.database_id_placeholder": "Enter Notion Database ID", "notion.title": "Notion Configuration", + "notion.help": "Notion Configuration Documentation", "notion.check": { "button": "Check", "fail": "Connection failed, please check network and Api_key and Database_id", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index faaab183..2ab936b4 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -567,6 +567,7 @@ "notion.database_id": "Notion データベースID", "notion.database_id_placeholder": "Notion データベースIDを入力してください", "notion.title": "Notion 設定", + "notion.help": "Notion 設定ドキュメント", "notion.check": { "button": "確認", "fail": "接続エラー、ネットワーク設定とApi_keyとDatabase_idを確認してください", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index ae7e54b9..03e41da4 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -567,6 +567,7 @@ "notion.database_id": "ID базы данных Notion", "notion.database_id_placeholder": "Введите ID базы данных Notion", "notion.title": "Настройки Notion", + "notion.help": "Документация по настройке Notion", "notion.check": { "button": "Проверить", "fail": "Не удалось подключиться, пожалуйста, проверьте сеть и правильность Api_key и Database_id", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 37a763a2..f3041187 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -567,6 +567,7 @@ "notion.database_id": "Notion 数据库 ID", "notion.database_id_placeholder": "请输入Notion 数据库 ID", "notion.title": "Notion 配置", + "notion.help" : "Notion 配置文档", "notion.check": { "button": "检查", "fail": "连接失败,请检查网络及Api_key和Database_id是否正确", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 000f1b3f..9ce0f9e2 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -565,6 +565,7 @@ "notion.database_id": "Notion 資料庫 ID", "notion.database_id_placeholder": "請輸入Notion 資料庫 ID", "notion.title": "Notion 配置", + "notion.help": "Notion 配置文檔", "notion.check": { "button": "檢查", "fail": "連接失敗,請檢查網絡及Api_key和Database_id是否正確", diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index bb7d3ac9..b51483c1 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -7,7 +7,7 @@ import { backup, reset, restore } from '@renderer/services/BackupService' import { RootState, useAppDispatch } from '@renderer/store' import { setNotionApiKey, setNotionDatabaseID } from '@renderer/store/settings' import { AppInfo } from '@renderer/types' -import { Button, Modal, Typography } from 'antd' +import { Button, Modal, Tooltip, Typography } from 'antd' import Input from 'antd/es/input/Input' import { FC, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -73,10 +73,12 @@ const NotionSettings: FC = () => { {t('settings.data.notion.title')} - + + + @@ -104,9 +106,7 @@ const NotionSettings: FC = () => { style={{ width: 250 }} placeholder={t('settings.data.notion.api_key_placeholder')} /> - +
{/* 添加分割线 */} From 4721a660fa349f1f2d936438901bb7f19dcdeac3 Mon Sep 17 00:00:00 2001 From: ousugo Date: Wed, 19 Feb 2025 00:24:44 +0800 Subject: [PATCH 21/66] feat: Add German language support to translation options --- src/renderer/src/config/translate.ts | 5 +++++ 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 | 5 +++-- 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/renderer/src/config/translate.ts b/src/renderer/src/config/translate.ts index 4c5054f4..fa35acea 100644 --- a/src/renderer/src/config/translate.ts +++ b/src/renderer/src/config/translate.ts @@ -55,6 +55,11 @@ export const TranslateLanguageOptions = [ value: 'arabic', label: i18n.t('languages.arabic'), emoji: '🇸🇦' + }, + { + value: 'german', + label: i18n.t('languages.german'), + emoji: '🇩🇪' } ] diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index d33b6cbc..4a6c81d7 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -317,7 +317,8 @@ "korean": "Korean", "portuguese": "Portuguese", "russian": "Russian", - "spanish": "Spanish" + "spanish": "Spanish", + "german": "German" }, "mermaid": { "download": { diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 2ab936b4..0ae3ba2b 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -312,6 +312,7 @@ "chinese-traditional": "繁体字中国語", "english": "英語", "french": "フランス語", + "german": "ドイツ語", "italian": "イタリア語", "japanese": "日本語", "korean": "韓国語", @@ -811,4 +812,4 @@ "title": "ドキュメント" } } -} \ No newline at end of file +} diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 03e41da4..0f9d8fdf 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -312,6 +312,7 @@ "chinese-traditional": "Китайский традиционный", "english": "Английский", "french": "Французский", + "german": "Немецкий", "italian": "Итальянский", "japanese": "Японский", "korean": "Корейский", @@ -790,4 +791,4 @@ "title": "Документация" } } -} \ No newline at end of file +} diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index f3041187..f5a13b0c 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -317,7 +317,8 @@ "korean": "韩文", "portuguese": "葡萄牙文", "russian": "俄文", - "spanish": "西班牙文" + "spanish": "西班牙文", + "german": "德文" }, "mermaid": { "download": { diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 9ce0f9e2..d220154d 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -317,7 +317,8 @@ "korean": "韓文", "portuguese": "葡萄牙文", "russian": "俄文", - "spanish": "西班牙文" + "spanish": "西班牙文", + "german": "德文" }, "mermaid": { "download": { @@ -792,4 +793,4 @@ "title": "幫助文件" } } -} \ No newline at end of file +} From 2c3f89dbdec90193c543e29d4d60a5c560cfa924 Mon Sep 17 00:00:00 2001 From: suyao Date: Wed, 19 Feb 2025 03:31:01 +0800 Subject: [PATCH 22/66] fix: update model identification with provider-specific uniqueness --- src/renderer/src/hooks/useModel.ts | 10 ++++++++-- src/renderer/src/pages/home/Messages/Message.tsx | 5 +++-- .../src/pages/home/Messages/MessageContent.tsx | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/hooks/useModel.ts b/src/renderer/src/hooks/useModel.ts index 05b164e3..69fa983f 100644 --- a/src/renderer/src/hooks/useModel.ts +++ b/src/renderer/src/hooks/useModel.ts @@ -1,7 +1,13 @@ import { useProviders } from './useProvider' -export function useModel(id?: string) { +export function useModel(id?: string, providerId?: string) { const { providers } = useProviders() const allModels = providers.map((p) => p.models).flat() - return allModels.find((m) => m.id === id) + return allModels.find((m) => { + if (providerId) { + return m.id === id && m.provider === providerId + } else { + return m.id === id + } + }) } diff --git a/src/renderer/src/pages/home/Messages/Message.tsx b/src/renderer/src/pages/home/Messages/Message.tsx index e0dc3a0d..6235996c 100644 --- a/src/renderer/src/pages/home/Messages/Message.tsx +++ b/src/renderer/src/pages/home/Messages/Message.tsx @@ -7,6 +7,7 @@ import { useTopic } from '@renderer/hooks/useTopic' import { fetchChatCompletion } from '@renderer/services/ApiService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { getContextCount, getMessageModelId } from '@renderer/services/MessagesService' +import { getModelUniqId } from '@renderer/services/ModelService' import { estimateHistoryTokens, estimateMessageUsage } from '@renderer/services/TokenService' import { Message, Topic } from '@renderer/types' import { classNames, runAsyncFunction } from '@renderer/utils' @@ -56,7 +57,7 @@ const MessageItem: FC = ({ const [message, setMessage] = useState(_message) const { t } = useTranslation() const { assistant, setModel } = useAssistant(message.assistantId) - const model = useModel(getMessageModelId(message)) || message.model + const model = useModel(getMessageModelId(message), message.model?.provider) || message.model const { isBubbleStyle } = useMessageStyle() const { showMessageDivider, messageFont, fontSize } = useSettings() const messageContainerRef = useRef(null) @@ -185,7 +186,7 @@ const MessageItem: FC = ({ })} ref={messageContainerRef} style={{ ...style, alignItems: isBubbleStyle ? (isAssistantMessage ? 'start' : 'end') : undefined }}> - + diff --git a/src/renderer/src/pages/home/Messages/MessageContent.tsx b/src/renderer/src/pages/home/Messages/MessageContent.tsx index 63b29aa3..2a1b29c2 100644 --- a/src/renderer/src/pages/home/Messages/MessageContent.tsx +++ b/src/renderer/src/pages/home/Messages/MessageContent.tsx @@ -1,4 +1,5 @@ import { InfoCircleOutlined, SyncOutlined, TranslationOutlined } from '@ant-design/icons' +import { getModelUniqId } from '@renderer/services/ModelService' import { Message, Model } from '@renderer/types' import { getBriefInfo } from '@renderer/utils' import { withMessageThought } from '@renderer/utils/formats' @@ -77,7 +78,7 @@ const MessageContent: React.FC = ({ message: _message, model }) => { return ( - {message.mentions?.map((model) => {'@' + model.name})} + {message.mentions?.map((model) => {'@' + model.name})} From c494288f7bf6ea642cc9e7c9c373374da9b4f097 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Wed, 19 Feb 2025 09:20:57 +0800 Subject: [PATCH 23/66] refactor: Simplify DragableList styling and remove unnecessary margins --- src/renderer/src/components/DragableList/index.tsx | 4 ++-- src/renderer/src/pages/home/Tabs/AssistantsTab.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/components/DragableList/index.tsx b/src/renderer/src/components/DragableList/index.tsx index 5d9acc94..05ed09c4 100644 --- a/src/renderer/src/components/DragableList/index.tsx +++ b/src/renderer/src/components/DragableList/index.tsx @@ -51,7 +51,7 @@ const DragableList: FC> = ({ const id = item.id || item return ( - {(provided, snapshot) => ( + {(provided) => (
> = ({ style={{ ...listStyle, ...provided.draggableProps.style, - marginBottom: index === list.length - 1 && !snapshot.isDragging ? 0 : 8 + marginBottom: 8 }}> {children(item, index)}
diff --git a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx index 4eee98a6..efb8c13b 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx @@ -153,7 +153,7 @@ const Assistants: FC = ({ }} {!dragging && ( - + {t('chat.add.assistant.title')} From cb8d47a17bdd8af83f245c338a5e09cfe48136ba Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Wed, 19 Feb 2025 09:28:36 +0800 Subject: [PATCH 24/66] fix: Improve knowledge base processing and deletion handling --- src/renderer/src/hooks/useKnowledge.ts | 6 +++++- src/renderer/src/pages/knowledge/KnowledgeContent.tsx | 3 ++- src/renderer/src/pages/knowledge/KnowledgePage.tsx | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/hooks/useKnowledge.ts b/src/renderer/src/hooks/useKnowledge.ts index 18a53324..4de51ca1 100644 --- a/src/renderer/src/hooks/useKnowledge.ts +++ b/src/renderer/src/hooks/useKnowledge.ts @@ -199,10 +199,14 @@ export const useKnowledge = (baseId: string) => { } // 获取目录处理进度 - const getDirectoryProcessingPercent = (itemId: string) => { + const getDirectoryProcessingPercent = (itemId?: string) => { const [percent, setPercent] = useState(0) useEffect(() => { + if (!itemId) { + return + } + const cleanup = window.electron.ipcRenderer.on(itemId, (_, progressingPercent: number) => { setPercent(progressingPercent) }) diff --git a/src/renderer/src/pages/knowledge/KnowledgeContent.tsx b/src/renderer/src/pages/knowledge/KnowledgeContent.tsx index d4ebf062..602e748a 100644 --- a/src/renderer/src/pages/knowledge/KnowledgeContent.tsx +++ b/src/renderer/src/pages/knowledge/KnowledgeContent.tsx @@ -64,6 +64,7 @@ const KnowledgeContent: FC = ({ selectedBase }) => { if (!base) { return null } + const progressingPercent = getDirectoryProcessingPercent(base?.id) const handleAddFile = () => { @@ -115,7 +116,7 @@ const KnowledgeContent: FC = ({ selectedBase }) => { inputPlaceholder: t('knowledge.url_placeholder'), inputProps: { rows: 10, - onPressEnter: () => { } + onPressEnter: () => {} } }) diff --git a/src/renderer/src/pages/knowledge/KnowledgePage.tsx b/src/renderer/src/pages/knowledge/KnowledgePage.tsx index ef2407cc..8e9f55ab 100644 --- a/src/renderer/src/pages/knowledge/KnowledgePage.tsx +++ b/src/renderer/src/pages/knowledge/KnowledgePage.tsx @@ -65,6 +65,7 @@ const KnowledgePage: FC = () => { title: t('knowledge.delete_confirm'), centered: true, onOk: () => { + setSelectedBase(undefined) deleteKnowledgeBase(base.id) } }) From 799267049fa4aedf89115e3d0c643f7291a819bb Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Wed, 19 Feb 2025 09:35:10 +0800 Subject: [PATCH 25/66] fix: Safely update topic with existing topic data --- src/renderer/src/pages/home/Messages/Messages.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/pages/home/Messages/Messages.tsx b/src/renderer/src/pages/home/Messages/Messages.tsx index 7d91b1a5..3d40b5c2 100644 --- a/src/renderer/src/pages/home/Messages/Messages.tsx +++ b/src/renderer/src/pages/home/Messages/Messages.tsx @@ -166,7 +166,8 @@ const Messages: FC = ({ assistant, topic, setActiveTopic }) => { setMessages([]) setDisplayMessages([]) const defaultTopic = getDefaultTopic(assistant.id) - updateTopic({ ...topic, name: defaultTopic.name, messages: [] }) + const _topic = getTopic(assistant, topic.id) + _topic && updateTopic({ ..._topic, name: defaultTopic.name, messages: [] }) TopicManager.clearTopicMessages(topic.id) }), EventEmitter.on(EVENT_NAMES.EXPORT_TOPIC_IMAGE, async () => { From affc866c17953fc2db5e76476e8320a7e3079853 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Wed, 19 Feb 2025 09:45:30 +0800 Subject: [PATCH 26/66] feat: Add default API host for DMX provider in migration --- src/renderer/src/store/index.ts | 2 +- src/renderer/src/store/migrate.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts index 1cca18b8..fbe7fee5 100644 --- a/src/renderer/src/store/index.ts +++ b/src/renderer/src/store/index.ts @@ -30,7 +30,7 @@ const persistedReducer = persistReducer( { key: 'cherry-studio', storage, - version: 69, + version: 70, blacklist: ['runtime'], migrate }, diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts index e7b87794..6100ed2b 100644 --- a/src/renderer/src/store/migrate.ts +++ b/src/renderer/src/store/migrate.ts @@ -1074,6 +1074,14 @@ const migrateConfig = { state.settings.gridColumns = 2 state.settings.gridPopoverTrigger = 'hover' return state + }, + '70': (state: RootState) => { + state.llm.providers.forEach((provider) => { + if (provider.id === 'dmxapi') { + provider.apiHost = 'https://www.dmxapi.cn' + } + }) + return state } } From e0fcdf43c5d4237f6e4286d188fc2c254c5934df Mon Sep 17 00:00:00 2001 From: icinggslits Date: Wed, 19 Feb 2025 02:54:10 +0800 Subject: [PATCH 27/66] feature: Adaptive height of textarea on translation page --- .../src/pages/translate/TranslatePage.tsx | 81 ++++++++++++++++++- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/pages/translate/TranslatePage.tsx b/src/renderer/src/pages/translate/TranslatePage.tsx index ac5d3ce8..624d639e 100644 --- a/src/renderer/src/pages/translate/TranslatePage.tsx +++ b/src/renderer/src/pages/translate/TranslatePage.tsx @@ -10,9 +10,10 @@ import { getDefaultTranslateAssistant } from '@renderer/services/AssistantServic import { Assistant, Message } from '@renderer/types' import { runAsyncFunction, uuid } from '@renderer/utils' import { Button, Select, Space } from 'antd' -import TextArea from 'antd/es/input/TextArea' +import TextArea, { TextAreaRef } from 'antd/es/input/TextArea' import { isEmpty } from 'lodash' -import { FC, useEffect, useState } from 'react' +import { debounce } from 'lodash' +import React, { FC, useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { Link } from 'react-router-dom' import styled from 'styled-components' @@ -29,11 +30,83 @@ const TranslatePage: FC = () => { const { translateModel } = useDefaultModel() const [loading, setLoading] = useState(false) const [copied, setCopied] = useState(false) + const contentContainerRef = useRef(null) + const textAreaRef = useRef(null) _text = text _result = result _targetLanguage = targetLanguage + const safetyMarginOfTextarea = (textarea: HTMLTextAreaElement): number => { + const defaultSafetyMargin = 30 + const lineHeight = window.getComputedStyle(textarea).lineHeight + if (lineHeight.endsWith('px')) { + const safetyMargin = parseInt(lineHeight.slice(0, -2)) + if (Number.isNaN(safetyMargin)) { + return defaultSafetyMargin + } else { + return safetyMargin + 4 + } + } else { + return defaultSafetyMargin + } + } + + const updateTextareaToMaxHeight = (textarea: HTMLTextAreaElement, safetyMargin: number) => { + const { top: textareaTop } = textarea.getBoundingClientRect() + textarea.style.height = `${window.innerHeight - safetyMargin - textareaTop}px` + } + + const updateTextareaHeight = useCallback((textarea: HTMLTextAreaElement, contentContainer: HTMLDivElement | null) => { + textarea.style.height = 'auto' + const unlimitedHeightUpdate = () => { + textarea.style.height = `${textarea.scrollHeight}px` + } + const safetyMargin = safetyMarginOfTextarea(textarea) + + if (contentContainer) { + const { bottom: textareaBottom, top: textareaTop } = textarea.getBoundingClientRect() + const { bottom: contentContainerBottom } = contentContainer.getBoundingClientRect() + if (textareaBottom !== 0 && contentContainerBottom !== 0) { + if (contentContainerBottom - textareaTop - textarea.scrollHeight < safetyMargin) { + updateTextareaToMaxHeight(textarea, safetyMargin) + } else { + unlimitedHeightUpdate() + } + } else { + unlimitedHeightUpdate() + } + } else { + unlimitedHeightUpdate() + } + }, []) + + const handleInput = (event: React.ChangeEvent) => { + updateTextareaHeight(event.target, contentContainerRef.current) + } + + useEffect(() => { + // Initialize when switching to this page + if (textAreaRef?.current?.resizableTextArea?.textArea) { + updateTextareaHeight(textAreaRef.current.resizableTextArea.textArea, contentContainerRef.current) + } + + const debounceHandleResize = debounce( + () => { + if (textAreaRef?.current?.resizableTextArea) { + updateTextareaHeight(textAreaRef.current.resizableTextArea.textArea, contentContainerRef.current) + } + }, + 16, + { maxWait: 16 } + ) + + const handleResize = () => debounceHandleResize() + + window.addEventListener('resize', handleResize) + return () => window.removeEventListener('resize', handleResize) + }, [textAreaRef, updateTextareaHeight]) + const onTranslate = async () => { if (!text.trim()) { return @@ -113,7 +186,7 @@ const TranslatePage: FC = () => { {t('translate.title')} - +