From f2195154f6a94e3ac324465c1adc6150180a186e Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Mon, 9 Sep 2024 18:55:37 +0800 Subject: [PATCH 01/25] feat: add shortcut key --- app/components/chat.module.scss | 49 +++++++++++++ app/components/chat.tsx | 118 ++++++++++++++++++++++++++++++++ app/locales/cn.ts | 9 +++ app/locales/en.ts | 8 +++ app/locales/tw.ts | 8 +++ 5 files changed, 192 insertions(+) diff --git a/app/components/chat.module.scss b/app/components/chat.module.scss index 7176399cc..98972f623 100644 --- a/app/components/chat.module.scss +++ b/app/components/chat.module.scss @@ -646,3 +646,52 @@ bottom: 30px; } } + +.shortcut-key-container { + padding: 10px; + overflow-y: auto; + display: flex; + flex-direction: column; +} + +.shortcut-key-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 16px; +} + +.shortcut-key-item { + display: flex; + flex-direction: column; + overflow: hidden; + border: 1px solid #ddd; + border-radius: 10px; + padding: 10px; + background-color: #fff; +} + +.shortcut-key-title { + font-size: 14px; + color: #333; + margin-bottom: 8px; +} + +.shortcut-key-keys { + display: flex; + gap: 8px; +} + +.shortcut-key { + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #ddd; + border-radius: 8px; + padding: 4px; + background-color: #f9f9f9; + min-width: 32px; +} + +.shortcut-key span { + font-size: 12px; +} \ No newline at end of file diff --git a/app/components/chat.tsx b/app/components/chat.tsx index dad1933ac..ab94ab41d 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -829,6 +829,57 @@ export function DeleteImageButton(props: { deleteImage: () => void }) { ); } +export function ShortcutKeyModal(props: { onClose: () => void }) { + const shortcuts = [ + { title: Locale.Chat.ShortcutKey.newChat, keys: ["⌘", "Shift", "o"] }, + { title: Locale.Chat.ShortcutKey.focusInput, keys: ["Shift", "Esc"] }, + { title: Locale.Chat.ShortcutKey.copyLastCode, keys: ["⌘", "Shift", ";"] }, + { + title: Locale.Chat.ShortcutKey.copyLastMessage, + keys: ["⌘", "Shift", "c"], + }, + { title: Locale.Chat.ShortcutKey.showShortcutKey, keys: ["⌘", "/"] }, + ]; + return ( +
+ } + key="ok" + onClick={() => { + props.onClose(); + }} + />, + ]} + > +
+
+ {shortcuts.map((shortcut, index) => ( +
+
+ {shortcut.title} +
+
+ {shortcut.keys.map((key, i) => ( +
+ {key} +
+ ))} +
+
+ ))} +
+
+
+
+ ); +} + function _Chat() { type RenderMessage = ChatMessage & { preview?: boolean }; @@ -1373,6 +1424,69 @@ function _Chat() { setAttachImages(images); } + // 快捷键 + const [showShortcutKeyModal, setShowShortcutKeyModal] = useState(false); + + useEffect(() => { + const handleKeyDown = (event) => { + // 打开新聊天 command + shift + o + if ( + (event.metaKey || event.ctrlKey) && + event.shiftKey && + event.key.toLowerCase() === "o" + ) { + event.preventDefault(); + setTimeout(() => { + chatStore.newSession(); + navigate(Path.Chat); + }, 10); + } + // 聚焦聊天输入 shift + esc + else if (event.shiftKey && event.key.toLowerCase() === "escape") { + event.preventDefault(); + inputRef.current?.focus(); + } + // 复制最后一个代码块 command + shift + ; + else if ( + (event.metaKey || event.ctrlKey) && + event.shiftKey && + event.code === "Semicolon" + ) { + event.preventDefault(); + const copyCodeButton = document.querySelectorAll(".copy-code-button"); + if (copyCodeButton.length > 0) { + copyCodeButton[copyCodeButton.length - 1].click(); + } + } + // 复制最后一个回复 command + shift + c + else if ( + (event.metaKey || event.ctrlKey) && + event.shiftKey && + event.key.toLowerCase() === "c" + ) { + event.preventDefault(); + const lastNonUserMessage = messages + .filter((message) => message.role !== "user") + .pop(); + if (lastNonUserMessage) { + const lastMessageContent = getMessageTextContent(lastNonUserMessage); + copyToClipboard(lastMessageContent); + } + } + // 展示快捷键 command + / + else if ((event.metaKey || event.ctrlKey) && event.key === "/") { + event.preventDefault(); + setShowShortcutKeyModal(true); + } + }; + + window.addEventListener("keydown", handleKeyDown); + + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, [messages, chatStore, navigate]); + return (
@@ -1760,6 +1874,10 @@ function _Chat() { }} /> )} + + {showShortcutKeyModal && ( + setShowShortcutKeyModal(false)} /> + )}
); } diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 33e368f69..24f707e40 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -1,3 +1,4 @@ +import { ShortcutKeyModal } from "../components/chat"; import { getClientConfig } from "../config/client"; import { SubmitKey } from "../store/config"; @@ -81,6 +82,14 @@ const cn = { SaveAs: "存为面具", }, IsContext: "预设提示词", + ShortcutKey: { + Title: "键盘快捷方式", + newChat: "打开新聊天", + focusInput: "聚焦输入框", + copyLastMessage: "复制最后一个回复", + copyLastCode: "复制最后一个代码块", + showShortcutKey: "显示快捷方式", + }, }, Export: { Title: "分享聊天记录", diff --git a/app/locales/en.ts b/app/locales/en.ts index 403b9b687..09b76f1fa 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -83,6 +83,14 @@ const en: LocaleType = { SaveAs: "Save as Mask", }, IsContext: "Contextual Prompt", + ShortcutKey: { + Title: "Keyboard Shortcuts", + newChat: "Open New Chat", + focusInput: "Focus Input Field", + copyLastMessage: "Copy Last Reply", + copyLastCode: "Copy Last Code Block", + showShortcutKey: "Show Shortcuts", + }, }, Export: { Title: "Export Messages", diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 6b2c0fd65..c54a7b8c5 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -81,6 +81,14 @@ const tw = { SaveAs: "另存新檔", }, IsContext: "預設提示詞", + ShortcutKey: { + Title: "鍵盤快捷方式", + newChat: "打開新聊天", + focusInput: "聚焦輸入框", + copyLastMessage: "複製最後一個回覆", + copyLastCode: "複製最後一個代碼塊", + showShortcutKey: "顯示快捷方式", + }, }, Export: { Title: "將聊天記錄匯出為 Markdown", From 7804182d0d027f630497c911652cd877ea0cc30a Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Mon, 9 Sep 2024 19:18:12 +0800 Subject: [PATCH 02/25] fix: type error --- app/components/chat.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index ab94ab41d..085292585 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1428,7 +1428,7 @@ function _Chat() { const [showShortcutKeyModal, setShowShortcutKeyModal] = useState(false); useEffect(() => { - const handleKeyDown = (event) => { + const handleKeyDown = (event: any) => { // 打开新聊天 command + shift + o if ( (event.metaKey || event.ctrlKey) && @@ -1453,7 +1453,8 @@ function _Chat() { event.code === "Semicolon" ) { event.preventDefault(); - const copyCodeButton = document.querySelectorAll(".copy-code-button"); + const copyCodeButton = + document.querySelectorAll(".copy-code-button"); if (copyCodeButton.length > 0) { copyCodeButton[copyCodeButton.length - 1].click(); } From 61245e3d7e41064bc9b5a431848489a3d82c2ef5 Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Mon, 9 Sep 2024 19:29:10 +0800 Subject: [PATCH 03/25] fix: dark theme css --- app/components/chat.module.scss | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/components/chat.module.scss b/app/components/chat.module.scss index 98972f623..5145188ec 100644 --- a/app/components/chat.module.scss +++ b/app/components/chat.module.scss @@ -664,15 +664,17 @@ display: flex; flex-direction: column; overflow: hidden; - border: 1px solid #ddd; + border: var(--border-in-light); border-radius: 10px; padding: 10px; - background-color: #fff; + background-color: var(--white); + box-shadow: var(--card-shadow); + transition: background-color 0.3s ease, box-shadow 0.3s ease; } .shortcut-key-title { font-size: 14px; - color: #333; + color: var(--black); margin-bottom: 8px; } @@ -685,13 +687,14 @@ display: flex; align-items: center; justify-content: center; - border: 1px solid #ddd; + border: var(--border-in-light); border-radius: 8px; padding: 4px; - background-color: #f9f9f9; + background-color: var(--gray); min-width: 32px; } .shortcut-key span { font-size: 12px; + color: var(--black); } \ No newline at end of file From e578c5f3ade565bc179ac2b639fa4d64b7d12a05 Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Tue, 10 Sep 2024 12:01:51 +0800 Subject: [PATCH 04/25] =?UTF-8?q?chore:=20=E6=A0=B7=E5=BC=8F=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/chat.module.scss | 10 +++------- app/components/chat.tsx | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/app/components/chat.module.scss b/app/components/chat.module.scss index 5145188ec..73542fc67 100644 --- a/app/components/chat.module.scss +++ b/app/components/chat.module.scss @@ -656,26 +656,22 @@ .shortcut-key-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 16px; } .shortcut-key-item { display: flex; - flex-direction: column; + justify-content: space-between; + align-items: center; overflow: hidden; - border: var(--border-in-light); - border-radius: 10px; padding: 10px; background-color: var(--white); - box-shadow: var(--card-shadow); - transition: background-color 0.3s ease, box-shadow 0.3s ease; } .shortcut-key-title { font-size: 14px; color: var(--black); - margin-bottom: 8px; } .shortcut-key-keys { diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 085292585..a91c8af7e 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -830,15 +830,25 @@ export function DeleteImageButton(props: { deleteImage: () => void }) { } export function ShortcutKeyModal(props: { onClose: () => void }) { + const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0; const shortcuts = [ - { title: Locale.Chat.ShortcutKey.newChat, keys: ["⌘", "Shift", "o"] }, + { + title: Locale.Chat.ShortcutKey.newChat, + keys: isMac ? ["⌘", "Shift", "O"] : ["Ctrl", "Shift", "O"], + }, { title: Locale.Chat.ShortcutKey.focusInput, keys: ["Shift", "Esc"] }, - { title: Locale.Chat.ShortcutKey.copyLastCode, keys: ["⌘", "Shift", ";"] }, + { + title: Locale.Chat.ShortcutKey.copyLastCode, + keys: isMac ? ["⌘", "Shift", ";"] : ["Ctrl", "Shift", ";"], + }, { title: Locale.Chat.ShortcutKey.copyLastMessage, - keys: ["⌘", "Shift", "c"], + keys: isMac ? ["⌘", "Shift", "C"] : ["Ctrl", "Shift", "C"], + }, + { + title: Locale.Chat.ShortcutKey.showShortcutKey, + keys: isMac ? ["⌘", "/"] : ["Ctrl", "/"], }, - { title: Locale.Chat.ShortcutKey.showShortcutKey, keys: ["⌘", "/"] }, ]; return (
@@ -1424,7 +1434,7 @@ function _Chat() { setAttachImages(images); } - // 快捷键 + // 快捷键 shortcut keys const [showShortcutKeyModal, setShowShortcutKeyModal] = useState(false); useEffect(() => { From 18e2403b01943ad245e84756695aa9db0a70ad3b Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Tue, 10 Sep 2024 14:30:51 +0800 Subject: [PATCH 05/25] =?UTF-8?q?chore:=20=E6=9B=B4=E6=8D=A2icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/chat.tsx | 9 +++++++++ app/icons/shortcutkey.svg | 1 + 2 files changed, 10 insertions(+) create mode 100644 app/icons/shortcutkey.svg diff --git a/app/components/chat.tsx b/app/components/chat.tsx index a91c8af7e..1fc10c35c 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -42,6 +42,7 @@ import SizeIcon from "../icons/size.svg"; import QualityIcon from "../icons/hd.svg"; import StyleIcon from "../icons/palette.svg"; import PluginIcon from "../icons/plugin.svg"; +import ShortcutkeyIcon from "../icons/shortcutkey.svg"; import { ChatMessage, @@ -437,6 +438,7 @@ export function ChatActions(props: { showPromptHints: () => void; hitBottom: boolean; uploading: boolean; + setShowShortcutKeyModal: () => void; }) { const config = useAppConfig(); const navigate = useNavigate(); @@ -755,6 +757,12 @@ export function ChatActions(props: { }} /> )} + + props.setShowShortcutKeyModal(true)} + text={Locale.Chat.ShortcutKey.Title} + icon={} + />
); } @@ -1814,6 +1822,7 @@ function _Chat() { setUserInput("/"); onSearch(""); }} + setShowShortcutKeyModal={setShowShortcutKeyModal} />
+
+ } + bordered + title={Locale.Chat.Actions.RefreshTitle} + onClick={() => { + showToast(Locale.Chat.Actions.RefreshToast); + chatStore.summarizeSession(true); + }} + /> +
{!isMobileScreen && (
= SUMMARIZE_MIN_LEN + (config.enableAutoGenerateTitle && + session.topic === DEFAULT_TOPIC && + countMessages(messages) >= SUMMARIZE_MIN_LEN) || + refreshTitle ) { - const topicMessages = messages.concat( - createMessage({ - role: "user", - content: Locale.Store.Prompt.Topic, - }), - ); + const topicMessages = messages + .slice( + messages.length - modelConfig.historyMessageCount, + messages.length, + ) + .concat( + createMessage({ + role: "user", + content: Locale.Store.Prompt.Topic, + }), + ); api.llm.chat({ messages: topicMessages, config: { From 37c0cfe1e9d2568138e820634ad9404c0c5fb21f Mon Sep 17 00:00:00 2001 From: skymkmk Date: Fri, 13 Sep 2024 21:13:19 +0800 Subject: [PATCH 18/25] translation: translations by claude for manual refresh --- app/locales/ar.ts | 2 ++ app/locales/bn.ts | 2 ++ app/locales/cn.ts | 2 ++ app/locales/cs.ts | 2 ++ app/locales/de.ts | 2 ++ app/locales/en.ts | 2 ++ app/locales/es.ts | 2 ++ app/locales/fr.ts | 2 ++ app/locales/id.ts | 2 ++ app/locales/it.ts | 2 ++ app/locales/jp.ts | 2 ++ app/locales/ko.ts | 2 ++ app/locales/no.ts | 2 ++ app/locales/pt.ts | 2 ++ app/locales/ru.ts | 2 ++ app/locales/sk.ts | 2 ++ app/locales/tr.ts | 2 ++ app/locales/tw.ts | 2 ++ app/locales/vi.ts | 2 ++ 19 files changed, 38 insertions(+) diff --git a/app/locales/ar.ts b/app/locales/ar.ts index 9bd491083..0c3fef720 100644 --- a/app/locales/ar.ts +++ b/app/locales/ar.ts @@ -43,6 +43,8 @@ const ar: PartialLocaleType = { PinToastAction: "عرض", Delete: "حذف", Edit: "تحرير", + RefreshTitle: "تحديث العنوان", + RefreshToast: "تم إرسال طلب تحديث العنوان", }, Commands: { new: "دردشة جديدة", diff --git a/app/locales/bn.ts b/app/locales/bn.ts index acabc8e2a..eeb1608e0 100644 --- a/app/locales/bn.ts +++ b/app/locales/bn.ts @@ -43,6 +43,8 @@ const bn: PartialLocaleType = { PinToastAction: "দেখুন", Delete: "মুছে ফেলুন", Edit: "সম্পাদনা করুন", + RefreshTitle: "শিরোনাম রিফ্রেশ করুন", + RefreshToast: "শিরোনাম রিফ্রেশ অনুরোধ পাঠানো হয়েছে", }, Commands: { new: "নতুন চ্যাট", diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 92e81bcb1..b5fcdbb8b 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -44,6 +44,8 @@ const cn = { Delete: "删除", Edit: "编辑", FullScreen: "全屏", + RefreshTitle: "刷新标题", + RefreshToast: "已发送刷新标题请求", }, Commands: { new: "新建聊天", diff --git a/app/locales/cs.ts b/app/locales/cs.ts index d16c474e8..d0c7f392c 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -43,6 +43,8 @@ const cs: PartialLocaleType = { PinToastAction: "Zobrazit", Delete: "Smazat", Edit: "Upravit", + RefreshTitle: "Obnovit název", + RefreshToast: "Požadavek na obnovení názvu byl odeslán", }, Commands: { new: "Nová konverzace", diff --git a/app/locales/de.ts b/app/locales/de.ts index a1f817047..da2859f01 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -43,6 +43,8 @@ const de: PartialLocaleType = { PinToastAction: "Ansehen", Delete: "Löschen", Edit: "Bearbeiten", + RefreshTitle: "Titel aktualisieren", + RefreshToast: "Anfrage zur Titelaktualisierung gesendet", }, Commands: { new: "Neues Gespräch", diff --git a/app/locales/en.ts b/app/locales/en.ts index 09b76f1fa..0a2fcc275 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -45,6 +45,8 @@ const en: LocaleType = { Delete: "Delete", Edit: "Edit", FullScreen: "FullScreen", + RefreshTitle: "Refresh Title", + RefreshToast: "Title refresh request sent", }, Commands: { new: "Start a new chat", diff --git a/app/locales/es.ts b/app/locales/es.ts index 5e4f900b7..6f2344c2c 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -44,6 +44,8 @@ const es: PartialLocaleType = { PinToastAction: "Ver", Delete: "Eliminar", Edit: "Editar", + RefreshTitle: "Actualizar título", + RefreshToast: "Se ha enviado la solicitud de actualización del título", }, Commands: { new: "Nueva conversación", diff --git a/app/locales/fr.ts b/app/locales/fr.ts index 65efc32b8..5a2a86ad9 100644 --- a/app/locales/fr.ts +++ b/app/locales/fr.ts @@ -43,6 +43,8 @@ const fr: PartialLocaleType = { PinToastAction: "Voir", Delete: "Supprimer", Edit: "Modifier", + RefreshTitle: "Actualiser le titre", + RefreshToast: "Demande d'actualisation du titre envoyée", }, Commands: { new: "Nouvelle discussion", diff --git a/app/locales/id.ts b/app/locales/id.ts index 3ac7af490..09bf0d09a 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -43,6 +43,8 @@ const id: PartialLocaleType = { PinToastAction: "Lihat", Delete: "Hapus", Edit: "Edit", + RefreshTitle: "Segarkan Judul", + RefreshToast: "Permintaan penyegaran judul telah dikirim", }, Commands: { new: "Obrolan Baru", diff --git a/app/locales/it.ts b/app/locales/it.ts index 1a54cfa43..67983a8db 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -43,6 +43,8 @@ const it: PartialLocaleType = { PinToastAction: "Visualizza", Delete: "Elimina", Edit: "Modifica", + RefreshTitle: "Aggiorna titolo", + RefreshToast: "Richiesta di aggiornamento del titolo inviata", }, Commands: { new: "Nuova chat", diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 6aaf0ba67..efb080a20 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -43,6 +43,8 @@ const jp: PartialLocaleType = { PinToastAction: "見る", Delete: "削除", Edit: "編集", + RefreshTitle: "タイトルを更新", + RefreshToast: "タイトル更新リクエストが送信されました", }, Commands: { new: "新しいチャット", diff --git a/app/locales/ko.ts b/app/locales/ko.ts index 563827fb9..827c5fc0a 100644 --- a/app/locales/ko.ts +++ b/app/locales/ko.ts @@ -43,6 +43,8 @@ const ko: PartialLocaleType = { PinToastAction: "보기", Delete: "삭제", Edit: "편집", + RefreshTitle: "제목 새로고침", + RefreshToast: "제목 새로고침 요청이 전송되었습니다", }, Commands: { new: "새 채팅", diff --git a/app/locales/no.ts b/app/locales/no.ts index d7dc16b3f..0fe2ad456 100644 --- a/app/locales/no.ts +++ b/app/locales/no.ts @@ -44,6 +44,8 @@ const no: PartialLocaleType = { PinToastAction: "Se", Delete: "Slett", Edit: "Rediger", + RefreshTitle: "Oppdater tittel", + RefreshToast: "Forespørsel om titteloppdatering sendt", }, Commands: { new: "Ny samtale", diff --git a/app/locales/pt.ts b/app/locales/pt.ts index 9fd13ba1c..03610ecce 100644 --- a/app/locales/pt.ts +++ b/app/locales/pt.ts @@ -43,6 +43,8 @@ const pt: PartialLocaleType = { PinToastAction: "Visualizar", Delete: "Deletar", Edit: "Editar", + RefreshTitle: "Atualizar Título", + RefreshToast: "Solicitação de atualização de título enviada", }, Commands: { new: "Iniciar um novo chat", diff --git a/app/locales/ru.ts b/app/locales/ru.ts index e983dcddb..f4d76f810 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -43,6 +43,8 @@ const ru: PartialLocaleType = { PinToastAction: "Просмотреть", Delete: "Удалить", Edit: "Редактировать", + RefreshTitle: "Обновить заголовок", + RefreshToast: "Запрос на обновление заголовка отправлен", }, Commands: { new: "Новый чат", diff --git a/app/locales/sk.ts b/app/locales/sk.ts index 2586aaaa7..61ea18b78 100644 --- a/app/locales/sk.ts +++ b/app/locales/sk.ts @@ -45,6 +45,8 @@ const sk: PartialLocaleType = { PinToastAction: "Zobraziť", Delete: "Vymazať", Edit: "Upraviť", + RefreshTitle: "Obnoviť názov", + RefreshToast: "Požiadavka na obnovenie názvu bola odoslaná", }, Commands: { new: "Začať nový chat", diff --git a/app/locales/tr.ts b/app/locales/tr.ts index ac410615e..6fccdda5e 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -43,6 +43,8 @@ const tr: PartialLocaleType = { PinToastAction: "Görünüm", Delete: "Sil", Edit: "Düzenle", + RefreshTitle: "Başlığı Yenile", + RefreshToast: "Başlık yenileme isteği gönderildi", }, Commands: { new: "Yeni sohbet", diff --git a/app/locales/tw.ts b/app/locales/tw.ts index c54a7b8c5..a080b000c 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -43,6 +43,8 @@ const tw = { PinToastAction: "檢視", Delete: "刪除", Edit: "編輯", + RefreshTitle: "刷新標題", + RefreshToast: "已發送刷新標題請求", }, Commands: { new: "新建聊天", diff --git a/app/locales/vi.ts b/app/locales/vi.ts index 9a21ee406..00934b3a6 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -43,6 +43,8 @@ const vi: PartialLocaleType = { PinToastAction: "Xem", Delete: "Xóa", Edit: "Chỉnh sửa", + RefreshTitle: "Làm mới tiêu đề", + RefreshToast: "Đã gửi yêu cầu làm mới tiêu đề", }, Commands: { new: "Tạo cuộc trò chuyện mới", From 93bc2f5870976a17ce9deacd29816022f5036c52 Mon Sep 17 00:00:00 2001 From: skymkmk Date: Fri, 13 Sep 2024 20:30:12 +0800 Subject: [PATCH 19/25] feat: now user can choose their own summarize model --- app/components/model-config.tsx | 25 +++++++++++ app/store/chat.ts | 75 +++++++++++++-------------------- app/store/config.ts | 13 +++++- 3 files changed, 66 insertions(+), 47 deletions(-) diff --git a/app/components/model-config.tsx b/app/components/model-config.tsx index 6ce25f664..948c9fb29 100644 --- a/app/components/model-config.tsx +++ b/app/components/model-config.tsx @@ -12,6 +12,7 @@ export function ModelConfigList(props: { }) { const allModels = useAllModels(); const value = `${props.modelConfig.model}@${props.modelConfig?.providerName}`; + const compressModelValue = `${props.modelConfig.compressModel}@${props.modelConfig?.compressProviderName}`; return ( <> @@ -228,6 +229,30 @@ export function ModelConfigList(props: { } > + + + ); } diff --git a/app/store/chat.ts b/app/store/chat.ts index 58c105e7e..4332c2246 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -1,33 +1,29 @@ -import { trimTopic, getMessageTextContent } from "../utils"; +import { getMessageTextContent, trimTopic } from "../utils"; -import Locale, { getLang } from "../locales"; +import { indexedDBStorage } from "@/app/utils/indexedDB-storage"; +import { nanoid } from "nanoid"; +import type { + ClientApi, + MultimodalContent, + RequestMessage, +} from "../client/api"; +import { getClientApi } from "../client/api"; +import { ChatControllerPool } from "../client/controller"; import { showToast } from "../components/ui-lib"; -import { ModelConfig, ModelType, useAppConfig } from "./config"; -import { createEmptyMask, Mask } from "./mask"; import { DEFAULT_INPUT_TEMPLATE, DEFAULT_MODELS, DEFAULT_SYSTEM_TEMPLATE, KnowledgeCutOffDate, StoreKey, - SUMMARIZE_MODEL, - GEMINI_SUMMARIZE_MODEL, } from "../constant"; -import { getClientApi } from "../client/api"; -import type { - ClientApi, - RequestMessage, - MultimodalContent, -} from "../client/api"; -import { ChatControllerPool } from "../client/controller"; -import { prettyObject } from "../utils/format"; -import { estimateTokenLength } from "../utils/token"; -import { nanoid } from "nanoid"; -import { createPersistStore } from "../utils/store"; -import { collectModelsWithDefaultModel } from "../utils/model"; -import { useAccessStore } from "./access"; +import Locale, { getLang } from "../locales"; import { isDalle3, safeLocalStorage } from "../utils"; -import { indexedDBStorage } from "@/app/utils/indexedDB-storage"; +import { prettyObject } from "../utils/format"; +import { createPersistStore } from "../utils/store"; +import { estimateTokenLength } from "../utils/token"; +import { ModelConfig, ModelType, useAppConfig } from "./config"; +import { createEmptyMask, Mask } from "./mask"; const localStorage = safeLocalStorage(); @@ -106,27 +102,6 @@ function createEmptySession(): ChatSession { }; } -function getSummarizeModel(currentModel: string) { - // if it is using gpt-* models, force to use 4o-mini to summarize - if (currentModel.startsWith("gpt") || currentModel.startsWith("chatgpt")) { - const configStore = useAppConfig.getState(); - const accessStore = useAccessStore.getState(); - const allModel = collectModelsWithDefaultModel( - configStore.models, - [configStore.customModels, accessStore.customModels].join(","), - accessStore.defaultModel, - ); - const summarizeModel = allModel.find( - (m) => m.name === SUMMARIZE_MODEL && m.available, - ); - return summarizeModel?.name ?? currentModel; - } - if (currentModel.startsWith("gemini")) { - return GEMINI_SUMMARIZE_MODEL; - } - return currentModel; -} - function countMessages(msgs: ChatMessage[]) { return msgs.reduce( (pre, cur) => pre + estimateTokenLength(getMessageTextContent(cur)), @@ -581,7 +556,7 @@ export const useChatStore = createPersistStore( return; } - const providerName = modelConfig.providerName; + const providerName = modelConfig.compressProviderName; const api: ClientApi = getClientApi(providerName); // remove error messages if any @@ -603,7 +578,7 @@ export const useChatStore = createPersistStore( api.llm.chat({ messages: topicMessages, config: { - model: getSummarizeModel(session.mask.modelConfig.model), + model: modelConfig.compressModel, stream: false, providerName, }, @@ -666,7 +641,7 @@ export const useChatStore = createPersistStore( config: { ...modelcfg, stream: true, - model: getSummarizeModel(session.mask.modelConfig.model), + model: modelConfig.compressModel, }, onUpdate(message) { session.memoryPrompt = message; @@ -715,7 +690,7 @@ export const useChatStore = createPersistStore( }, { name: StoreKey.Chat, - version: 3.1, + version: 3.2, migrate(persistedState, version) { const state = persistedState as any; const newState = JSON.parse( @@ -762,6 +737,16 @@ export const useChatStore = createPersistStore( }); } + // add default summarize model for every session + if (version < 3.2) { + newState.sessions.forEach((s) => { + const config = useAppConfig.getState(); + s.mask.modelConfig.compressModel = config.modelConfig.compressModel; + s.mask.modelConfig.compressProviderName = + config.modelConfig.compressProviderName; + }); + } + return newState as any; }, }, diff --git a/app/store/config.ts b/app/store/config.ts index e8e3c9863..9985b9e76 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -50,7 +50,7 @@ export const DEFAULT_CONFIG = { models: DEFAULT_MODELS as any as LLMModel[], modelConfig: { - model: "gpt-3.5-turbo" as ModelType, + model: "gpt-4o-mini" as ModelType, providerName: "OpenAI" as ServiceProvider, temperature: 0.5, top_p: 1, @@ -60,6 +60,8 @@ export const DEFAULT_CONFIG = { sendMemory: true, historyMessageCount: 4, compressMessageLengthThreshold: 1000, + compressModel: "gpt-4o-mini" as ModelType, + compressProviderName: "OpenAI" as ServiceProvider, enableInjectSystemPrompts: true, template: config?.template ?? DEFAULT_INPUT_TEMPLATE, size: "1024x1024" as DalleSize, @@ -140,7 +142,7 @@ export const useAppConfig = createPersistStore( }), { name: StoreKey.Config, - version: 3.9, + version: 4, migrate(persistedState, version) { const state = persistedState as ChatConfig; @@ -178,6 +180,13 @@ export const useAppConfig = createPersistStore( : config?.template ?? DEFAULT_INPUT_TEMPLATE; } + if (version < 4) { + state.modelConfig.compressModel = + DEFAULT_CONFIG.modelConfig.compressModel; + state.modelConfig.compressProviderName = + DEFAULT_CONFIG.modelConfig.compressProviderName; + } + return state as any; }, }, From 1b869d930593060d416f565a4570ab3afdcda932 Mon Sep 17 00:00:00 2001 From: skymkmk Date: Fri, 13 Sep 2024 21:13:19 +0800 Subject: [PATCH 20/25] translation: translations by claude for new writings --- app/locales/ar.ts | 4 ++++ app/locales/bn.ts | 4 ++++ app/locales/cn.ts | 4 ++++ app/locales/cs.ts | 4 ++++ app/locales/de.ts | 4 ++++ app/locales/en.ts | 4 ++++ app/locales/es.ts | 4 ++++ app/locales/fr.ts | 4 ++++ app/locales/id.ts | 4 ++++ app/locales/it.ts | 4 ++++ app/locales/jp.ts | 4 ++++ app/locales/ko.ts | 4 ++++ app/locales/no.ts | 4 ++++ app/locales/pt.ts | 4 ++++ app/locales/ru.ts | 4 ++++ app/locales/sk.ts | 4 ++++ app/locales/tr.ts | 4 ++++ app/locales/tw.ts | 4 ++++ app/locales/vi.ts | 4 ++++ 19 files changed, 76 insertions(+) diff --git a/app/locales/ar.ts b/app/locales/ar.ts index 9bd491083..fef123047 100644 --- a/app/locales/ar.ts +++ b/app/locales/ar.ts @@ -404,6 +404,10 @@ const ar: PartialLocaleType = { }, Model: "النموذج", + CompressModel: { + Title: "نموذج الضغط", + SubTitle: "النموذج المستخدم لضغط السجل التاريخي", + }, Temperature: { Title: "العشوائية (temperature)", SubTitle: "كلما زادت القيمة، زادت العشوائية في الردود", diff --git a/app/locales/bn.ts b/app/locales/bn.ts index acabc8e2a..ea66ce646 100644 --- a/app/locales/bn.ts +++ b/app/locales/bn.ts @@ -411,6 +411,10 @@ const bn: PartialLocaleType = { }, Model: "মডেল (model)", + CompressModel: { + Title: "সংকোচন মডেল", + SubTitle: "ইতিহাস সংকুচিত করার জন্য ব্যবহৃত মডেল", + }, Temperature: { Title: "যাদুকরিতা (temperature)", SubTitle: "মান বাড়ালে উত্তর বেশি এলোমেলো হবে", diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 92e81bcb1..068429585 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -470,6 +470,10 @@ const cn = { }, Model: "模型 (model)", + CompressModel: { + Title: "压缩模型", + SubTitle: "用于压缩历史记录的模型", + }, Temperature: { Title: "随机性 (temperature)", SubTitle: "值越大,回复越随机", diff --git a/app/locales/cs.ts b/app/locales/cs.ts index d16c474e8..a23367472 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -410,6 +410,10 @@ const cs: PartialLocaleType = { }, Model: "Model (model)", + CompressModel: { + Title: "Kompresní model", + SubTitle: "Model používaný pro kompresi historie", + }, Temperature: { Title: "Náhodnost (temperature)", SubTitle: "Čím vyšší hodnota, tím náhodnější odpovědi", diff --git a/app/locales/de.ts b/app/locales/de.ts index a1f817047..56e787381 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -421,6 +421,10 @@ const de: PartialLocaleType = { }, Model: "Modell", + CompressModel: { + Title: "Kompressionsmodell", + SubTitle: "Modell zur Komprimierung des Verlaufs", + }, Temperature: { Title: "Zufälligkeit (temperature)", SubTitle: "Je höher der Wert, desto zufälliger die Antwort", diff --git a/app/locales/en.ts b/app/locales/en.ts index 09b76f1fa..41337ac2f 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -474,6 +474,10 @@ const en: LocaleType = { }, Model: "Model", + CompressModel: { + Title: "Compression Model", + SubTitle: "Model used to compress history", + }, Temperature: { Title: "Temperature", SubTitle: "A larger value makes the more random output", diff --git a/app/locales/es.ts b/app/locales/es.ts index 5e4f900b7..8fa42b659 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -423,6 +423,10 @@ const es: PartialLocaleType = { }, Model: "Modelo (model)", + CompressModel: { + Title: "Modelo de compresión", + SubTitle: "Modelo utilizado para comprimir el historial", + }, Temperature: { Title: "Aleatoriedad (temperature)", SubTitle: "Cuanto mayor sea el valor, más aleatorio será el resultado", diff --git a/app/locales/fr.ts b/app/locales/fr.ts index 65efc32b8..198fdddd4 100644 --- a/app/locales/fr.ts +++ b/app/locales/fr.ts @@ -422,6 +422,10 @@ const fr: PartialLocaleType = { }, Model: "Modèle", + CompressModel: { + Title: "Modèle de compression", + SubTitle: "Modèle utilisé pour compresser l'historique", + }, Temperature: { Title: "Aléatoire (temperature)", SubTitle: "Plus la valeur est élevée, plus les réponses sont aléatoires", diff --git a/app/locales/id.ts b/app/locales/id.ts index 3ac7af490..61530a775 100644 --- a/app/locales/id.ts +++ b/app/locales/id.ts @@ -411,6 +411,10 @@ const id: PartialLocaleType = { }, Model: "Model", + CompressModel: { + Title: "Model Kompresi", + SubTitle: "Model yang digunakan untuk mengompres riwayat", + }, Temperature: { Title: "Randomness (temperature)", SubTitle: "Semakin tinggi nilainya, semakin acak responsnya", diff --git a/app/locales/it.ts b/app/locales/it.ts index 1a54cfa43..57d9d0f15 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -423,6 +423,10 @@ const it: PartialLocaleType = { }, Model: "Modello (model)", + CompressModel: { + Title: "Modello di compressione", + SubTitle: "Modello utilizzato per comprimere la cronologia", + }, Temperature: { Title: "Casualità (temperature)", SubTitle: "Valore più alto, risposte più casuali", diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 6aaf0ba67..b09489d9f 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -407,6 +407,10 @@ const jp: PartialLocaleType = { }, Model: "モデル (model)", + CompressModel: { + Title: "圧縮モデル", + SubTitle: "履歴を圧縮するために使用されるモデル", + }, Temperature: { Title: "ランダム性 (temperature)", SubTitle: "値が大きいほど応答がランダムになります", diff --git a/app/locales/ko.ts b/app/locales/ko.ts index 563827fb9..973927ed5 100644 --- a/app/locales/ko.ts +++ b/app/locales/ko.ts @@ -404,6 +404,10 @@ const ko: PartialLocaleType = { }, Model: "모델 (model)", + CompressModel: { + Title: "압축 모델", + SubTitle: "기록을 압축하는 데 사용되는 모델", + }, Temperature: { Title: "무작위성 (temperature)", SubTitle: "값이 클수록 응답이 더 무작위적", diff --git a/app/locales/no.ts b/app/locales/no.ts index d7dc16b3f..490d2bfda 100644 --- a/app/locales/no.ts +++ b/app/locales/no.ts @@ -415,6 +415,10 @@ const no: PartialLocaleType = { }, Model: "Modell", + CompressModel: { + Title: "Komprimeringsmodell", + SubTitle: "Modell brukt for å komprimere historikken", + }, Temperature: { Title: "Tilfeldighet (temperature)", SubTitle: "Høyere verdi gir mer tilfeldige svar", diff --git a/app/locales/pt.ts b/app/locales/pt.ts index 9fd13ba1c..5dadc8e3a 100644 --- a/app/locales/pt.ts +++ b/app/locales/pt.ts @@ -346,6 +346,10 @@ const pt: PartialLocaleType = { }, Model: "Modelo", + CompressModel: { + Title: "Modelo de Compressão", + SubTitle: "Modelo usado para comprimir o histórico", + }, Temperature: { Title: "Temperatura", SubTitle: "Um valor maior torna a saída mais aleatória", diff --git a/app/locales/ru.ts b/app/locales/ru.ts index e983dcddb..4c583618b 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -414,6 +414,10 @@ const ru: PartialLocaleType = { }, Model: "Модель", + CompressModel: { + Title: "Модель сжатия", + SubTitle: "Модель, используемая для сжатия истории", + }, Temperature: { Title: "Случайность (temperature)", SubTitle: "Чем больше значение, тем более случайные ответы", diff --git a/app/locales/sk.ts b/app/locales/sk.ts index 2586aaaa7..4b4085f4d 100644 --- a/app/locales/sk.ts +++ b/app/locales/sk.ts @@ -365,6 +365,10 @@ const sk: PartialLocaleType = { }, Model: "Model", + CompressModel: { + Title: "Kompresný model", + SubTitle: "Model používaný na kompresiu histórie", + }, Temperature: { Title: "Teplota", SubTitle: "Vyššia hodnota robí výstup náhodnejším", diff --git a/app/locales/tr.ts b/app/locales/tr.ts index ac410615e..edb4572bf 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -414,6 +414,10 @@ const tr: PartialLocaleType = { }, Model: "Model (model)", + CompressModel: { + Title: "Sıkıştırma Modeli", + SubTitle: "Geçmişi sıkıştırmak için kullanılan model", + }, Temperature: { Title: "Rastgelelik (temperature)", SubTitle: "Değer arttıkça yanıt daha rastgele olur", diff --git a/app/locales/tw.ts b/app/locales/tw.ts index c54a7b8c5..88b86772c 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -368,6 +368,10 @@ const tw = { }, Model: "模型 (model)", + CompressModel: { + Title: "壓縮模型", + SubTitle: "用於壓縮歷史記錄的模型", + }, Temperature: { Title: "隨機性 (temperature)", SubTitle: "值越大,回應越隨機", diff --git a/app/locales/vi.ts b/app/locales/vi.ts index 9a21ee406..3b0456d1c 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -410,6 +410,10 @@ const vi: PartialLocaleType = { }, Model: "Mô hình (model)", + CompressModel: { + Title: "Mô hình nén", + SubTitle: "Mô hình được sử dụng để nén lịch sử", + }, Temperature: { Title: "Độ ngẫu nhiên (temperature)", SubTitle: "Giá trị càng lớn, câu trả lời càng ngẫu nhiên", From fa48ace39badb237728188482550ae5bb8f0e47a Mon Sep 17 00:00:00 2001 From: skymkmk Date: Sat, 14 Sep 2024 07:49:26 +0800 Subject: [PATCH 21/25] fix: prevent users from setting a extremly short history that resulting in no content being sent for the title summary --- app/store/chat.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/store/chat.ts b/app/store/chat.ts index 1609666c3..d2a1fecd6 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -595,9 +595,13 @@ export const useChatStore = createPersistStore( countMessages(messages) >= SUMMARIZE_MIN_LEN) || refreshTitle ) { + const startIndex = Math.max( + 0, + messages.length - modelConfig.historyMessageCount, + ); const topicMessages = messages .slice( - messages.length - modelConfig.historyMessageCount, + startIndex < messages.length ? startIndex : messages.length - 1, messages.length, ) .concat( From 84a7afcd948743fa8c69b712d812ad6fbd73c5db Mon Sep 17 00:00:00 2001 From: evenwan Date: Sat, 14 Sep 2024 09:31:05 +0800 Subject: [PATCH 22/25] feat: Improve setting.model selector --- app/components/model-config.tsx | 22 +++++++++++++++------- app/components/ui-lib.module.scss | 6 ++++++ app/components/ui-lib.tsx | 12 +++++++++--- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/components/model-config.tsx b/app/components/model-config.tsx index 6ce25f664..6c40ab1b2 100644 --- a/app/components/model-config.tsx +++ b/app/components/model-config.tsx @@ -5,12 +5,17 @@ import Locale from "../locales"; import { InputRange } from "./input-range"; import { ListItem, Select } from "./ui-lib"; import { useAllModels } from "../utils/hooks"; +import { groupBy } from "lodash-es"; export function ModelConfigList(props: { modelConfig: ModelConfig; updateConfig: (updater: (config: ModelConfig) => void) => void; }) { const allModels = useAllModels(); + const groupModels = groupBy( + allModels.filter((v) => v.available), + "provider.providerName", + ); const value = `${props.modelConfig.model}@${props.modelConfig?.providerName}`; return ( @@ -19,6 +24,7 @@ export function ModelConfigList(props: { , + React.SelectHTMLAttributes & { + align?: "left" | "center"; + }, HTMLSelectElement >, ) { - const { className, children, ...otherProps } = props; + const { className, children, align, ...otherProps } = props; return ( -
+
From 9a5a3d4ce4e6b1c7210fc1b9d9e78231d4e2b3a8 Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Sat, 14 Sep 2024 16:06:18 +0800 Subject: [PATCH 23/25] fix: #5429 Anthropic authentication_error CORS --- app/api/anthropic.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/api/anthropic.ts b/app/api/anthropic.ts index 3d49f4c88..88f217a90 100644 --- a/app/api/anthropic.ts +++ b/app/api/anthropic.ts @@ -98,6 +98,7 @@ async function request(req: NextRequest) { headers: { "Content-Type": "application/json", "Cache-Control": "no-store", + "anthropic-dangerous-direct-browser-access": true, [authHeaderName]: authValue, "anthropic-version": req.headers.get("anthropic-version") || From 8ac9141a29b049a851c51ea3c65f08d18cfd8ce6 Mon Sep 17 00:00:00 2001 From: Meaqua Date: Sun, 15 Sep 2024 14:21:27 +0800 Subject: [PATCH 24/25] fix: ts error --- app/api/anthropic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/anthropic.ts b/app/api/anthropic.ts index 88f217a90..d7b070247 100644 --- a/app/api/anthropic.ts +++ b/app/api/anthropic.ts @@ -98,7 +98,7 @@ async function request(req: NextRequest) { headers: { "Content-Type": "application/json", "Cache-Control": "no-store", - "anthropic-dangerous-direct-browser-access": true, + "anthropic-dangerous-direct-browser-access": "true", [authHeaderName]: authValue, "anthropic-version": req.headers.get("anthropic-version") || From e986088becfeee53a21d136e8ac6ab484909f2fc Mon Sep 17 00:00:00 2001 From: DDDDD12138 Date: Sun, 15 Sep 2024 21:59:21 +0800 Subject: [PATCH 25/25] chore: correct typo --- app/components/chat.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 17f8d3a34..3cc02d486 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -520,8 +520,8 @@ export function ChatActions(props: { // if current model is not available // switch to first available model - const isUnavaliableModel = !models.some((m) => m.name === currentModel); - if (isUnavaliableModel && models.length > 0) { + const isUnavailableModel = !models.some((m) => m.name === currentModel); + if (isUnavailableModel && models.length > 0) { // show next model to default model if exist let nextModel = models.find((model) => model.isDefault) || models[0]; chatStore.updateCurrentSession((session) => {