mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-11 16:39:15 +08:00
refactor(Inputbar): remove MentionModelsInput and KnowledgeBaseInput components; update InputbarTools and Inputbar to handle model mentions and knowledge base selections directly. Update icons to use Hammer instead of SquareTerminal in various components. Enhance i18n translations for clear actions across multiple languages.
This commit is contained in:
parent
263166c9d1
commit
c8c0d22787
@ -14,6 +14,7 @@ import { Tooltip } from 'antd'
|
|||||||
import {
|
import {
|
||||||
FileSearch,
|
FileSearch,
|
||||||
Folder,
|
Folder,
|
||||||
|
Hammer,
|
||||||
Home,
|
Home,
|
||||||
Languages,
|
Languages,
|
||||||
LayoutGrid,
|
LayoutGrid,
|
||||||
@ -22,7 +23,6 @@ import {
|
|||||||
Palette,
|
Palette,
|
||||||
Settings,
|
Settings,
|
||||||
Sparkle,
|
Sparkle,
|
||||||
SquareTerminal,
|
|
||||||
Sun,
|
Sun,
|
||||||
Terminal,
|
Terminal,
|
||||||
X
|
X
|
||||||
@ -53,7 +53,7 @@ const getTabIcon = (tabId: string): React.ReactNode | undefined => {
|
|||||||
case 'knowledge':
|
case 'knowledge':
|
||||||
return <FileSearch size={14} />
|
return <FileSearch size={14} />
|
||||||
case 'mcp':
|
case 'mcp':
|
||||||
return <SquareTerminal size={14} />
|
return <Hammer size={14} />
|
||||||
case 'files':
|
case 'files':
|
||||||
return <Folder size={14} />
|
return <Folder size={14} />
|
||||||
case 'settings':
|
case 'settings':
|
||||||
|
|||||||
@ -2703,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "Quickly translate with 3 spaces",
|
"auto_translate_with_space": "Quickly translate with 3 spaces",
|
||||||
|
"clear": {
|
||||||
|
"all": "[to be translated]:清除",
|
||||||
|
"knowledge_base": "Clear selected knowledge bases",
|
||||||
|
"models": "Clear all models"
|
||||||
|
},
|
||||||
"show_translate_confirm": "Show translation confirmation dialog",
|
"show_translate_confirm": "Show translation confirmation dialog",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "Simplified Chinese",
|
"chinese": "Simplified Chinese",
|
||||||
|
|||||||
@ -2703,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "スペースを3回押して翻訳",
|
"auto_translate_with_space": "スペースを3回押して翻訳",
|
||||||
|
"clear": {
|
||||||
|
"all": "[to be translated]:清除",
|
||||||
|
"knowledge_base": "選択された知識ベースをクリア",
|
||||||
|
"models": "すべてのモデルをクリア"
|
||||||
|
},
|
||||||
"show_translate_confirm": "翻訳確認ダイアログを表示",
|
"show_translate_confirm": "翻訳確認ダイアログを表示",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "簡体字中国語",
|
"chinese": "簡体字中国語",
|
||||||
|
|||||||
@ -2703,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "Быстрый перевод с помощью 3-х пробелов",
|
"auto_translate_with_space": "Быстрый перевод с помощью 3-х пробелов",
|
||||||
|
"clear": {
|
||||||
|
"all": "[to be translated]:清除",
|
||||||
|
"knowledge_base": "Очистить выбранные базы знаний",
|
||||||
|
"models": "Очистить все модели"
|
||||||
|
},
|
||||||
"show_translate_confirm": "Показать диалоговое окно подтверждения перевода",
|
"show_translate_confirm": "Показать диалоговое окно подтверждения перевода",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "Китайский упрощенный",
|
"chinese": "Китайский упрощенный",
|
||||||
|
|||||||
@ -2703,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "3 个空格快速翻译",
|
"auto_translate_with_space": "3 个空格快速翻译",
|
||||||
|
"clear": {
|
||||||
|
"all": "清除",
|
||||||
|
"knowledge_base": "清除选中的知识库",
|
||||||
|
"models": "清除@的所有模型"
|
||||||
|
},
|
||||||
"show_translate_confirm": "显示翻译确认对话框",
|
"show_translate_confirm": "显示翻译确认对话框",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "简体中文",
|
"chinese": "简体中文",
|
||||||
|
|||||||
@ -2703,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "快速敲擊 3 次空格翻譯",
|
"auto_translate_with_space": "快速敲擊 3 次空格翻譯",
|
||||||
|
"clear": {
|
||||||
|
"all": "[to be translated]:清除",
|
||||||
|
"knowledge_base": "清除選中的知識庫",
|
||||||
|
"models": "清除@的所有模型"
|
||||||
|
},
|
||||||
"show_translate_confirm": "顯示翻譯確認對話框",
|
"show_translate_confirm": "顯示翻譯確認對話框",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "簡體中文",
|
"chinese": "簡體中文",
|
||||||
|
|||||||
@ -1578,6 +1578,7 @@
|
|||||||
"style_type_tip": "Ο τύπος στυλ για την επεξεργασμένη εικόνα, ισχύει μόνο για την έκδοση V_2 και νεότερες"
|
"style_type_tip": "Ο τύπος στυλ για την επεξεργασμένη εικόνα, ισχύει μόνο για την έκδοση V_2 και νεότερες"
|
||||||
},
|
},
|
||||||
"generate": {
|
"generate": {
|
||||||
|
"height": "Ύψος",
|
||||||
"magic_prompt_option_tip": "Έξυπνη βελτιστοποίηση της προτροπής για βελτίωση των αποτελεσμάτων",
|
"magic_prompt_option_tip": "Έξυπνη βελτιστοποίηση της προτροπής για βελτίωση των αποτελεσμάτων",
|
||||||
"model_tip": "Έκδοση μοντέλου: Το V2 είναι το τελευταίο μοντέλο διεπαφής, το V2A είναι γρήγορο μοντέλο, το V_1 είναι το αρχικό μοντέλο και το _TURBO είναι η επιταχυνόμενη έκδοση",
|
"model_tip": "Έκδοση μοντέλου: Το V2 είναι το τελευταίο μοντέλο διεπαφής, το V2A είναι γρήγορο μοντέλο, το V_1 είναι το αρχικό μοντέλο και το _TURBO είναι η επιταχυνόμενη έκδοση",
|
||||||
"negative_prompt_tip": "Περιγράψτε στοιχεία που δεν θέλετε να εμφανίζονται στην εικόνα, υποστηρίζεται μόνο στις εκδόσεις V_1, V_1_TURBO, V_2 και V_2_TURBO",
|
"negative_prompt_tip": "Περιγράψτε στοιχεία που δεν θέλετε να εμφανίζονται στην εικόνα, υποστηρίζεται μόνο στις εκδόσεις V_1, V_1_TURBO, V_2 και V_2_TURBO",
|
||||||
@ -1585,8 +1586,11 @@
|
|||||||
"person_generation": "Δημιουργία προσώπου",
|
"person_generation": "Δημιουργία προσώπου",
|
||||||
"person_generation_tip": "Επιτρέπει στο μοντέλο να δημιουργεί εικόνες προσώπων",
|
"person_generation_tip": "Επιτρέπει στο μοντέλο να δημιουργεί εικόνες προσώπων",
|
||||||
"rendering_speed_tip": "Ελέγχει την ισορροπία μεταξύ ταχύτητας και ποιότητας απόδοσης, ισχύει μόνο για την έκδοση V_3",
|
"rendering_speed_tip": "Ελέγχει την ισορροπία μεταξύ ταχύτητας και ποιότητας απόδοσης, ισχύει μόνο για την έκδοση V_3",
|
||||||
|
"safety_tolerance": "Ασφάλεια",
|
||||||
|
"safety_tolerance_tip": "Έλεγχος της ασφάλειας της δημιουργίας εικόνας, ισχύει μόνο για την έκδοση FLUX.1-Kontext-pro",
|
||||||
"seed_tip": "Ελέγχει την τυχαιότητα της δημιουργίας εικόνας, χρησιμοποιείται για να επαναληφθεί το ίδιο αποτέλεσμα",
|
"seed_tip": "Ελέγχει την τυχαιότητα της δημιουργίας εικόνας, χρησιμοποιείται για να επαναληφθεί το ίδιο αποτέλεσμα",
|
||||||
"style_type_tip": "Στυλ δημιουργίας εικόνας, ισχύει μόνο για την έκδοση V_2 και μεταγενέστερες"
|
"style_type_tip": "Στυλ δημιουργίας εικόνας, ισχύει μόνο για την έκδοση V_2 και μεταγενέστερες",
|
||||||
|
"width": "Πλάτος"
|
||||||
},
|
},
|
||||||
"generated_image": "Δημιουργία εικόνας",
|
"generated_image": "Δημιουργία εικόνας",
|
||||||
"go_to_settings": "Πηγαίνετε στις ρυθμίσεις",
|
"go_to_settings": "Πηγαίνετε στις ρυθμίσεις",
|
||||||
@ -2699,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "Μετάφραση με τρεις γρήγορες πιστώσεις",
|
"auto_translate_with_space": "Μετάφραση με τρεις γρήγορες πιστώσεις",
|
||||||
|
"clear": {
|
||||||
|
"all": "Εκκαθάριση",
|
||||||
|
"knowledge_base": "Εκκαθάριση επιλεγμένων βάσεων γνώσης",
|
||||||
|
"models": "Εκκαθάριση όλων των μοντέλων"
|
||||||
|
},
|
||||||
"show_translate_confirm": "Εμφάνιση παραθύρου επιβεβαίωσης μετάφρασης",
|
"show_translate_confirm": "Εμφάνιση παραθύρου επιβεβαίωσης μετάφρασης",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "Σινογραμματικό",
|
"chinese": "Σινογραμματικό",
|
||||||
|
|||||||
@ -1578,6 +1578,7 @@
|
|||||||
"style_type_tip": "Estilo de la imagen editada, solo aplicable para la versión V_2 y posteriores"
|
"style_type_tip": "Estilo de la imagen editada, solo aplicable para la versión V_2 y posteriores"
|
||||||
},
|
},
|
||||||
"generate": {
|
"generate": {
|
||||||
|
"height": "Altura",
|
||||||
"magic_prompt_option_tip": "Optimización inteligente de indicaciones para mejorar los resultados de generación",
|
"magic_prompt_option_tip": "Optimización inteligente de indicaciones para mejorar los resultados de generación",
|
||||||
"model_tip": "Versión del modelo: V2 es el modelo más reciente de la interfaz, V2A es un modelo rápido, V_1 es el modelo inicial y _TURBO es la versión acelerada",
|
"model_tip": "Versión del modelo: V2 es el modelo más reciente de la interfaz, V2A es un modelo rápido, V_1 es el modelo inicial y _TURBO es la versión acelerada",
|
||||||
"negative_prompt_tip": "Describe elementos que no deseas en la imagen. Solo compatible con las versiones V_1, V_1_TURBO, V_2 y V_2_TURBO",
|
"negative_prompt_tip": "Describe elementos que no deseas en la imagen. Solo compatible con las versiones V_1, V_1_TURBO, V_2 y V_2_TURBO",
|
||||||
@ -1585,8 +1586,11 @@
|
|||||||
"person_generation": "Generar Persona",
|
"person_generation": "Generar Persona",
|
||||||
"person_generation_tip": "Permite que el modelo genere imágenes de personas",
|
"person_generation_tip": "Permite que el modelo genere imágenes de personas",
|
||||||
"rendering_speed_tip": "Controla el equilibrio entre velocidad y calidad de renderizado, solo aplicable a la versión V_3",
|
"rendering_speed_tip": "Controla el equilibrio entre velocidad y calidad de renderizado, solo aplicable a la versión V_3",
|
||||||
|
"safety_tolerance": "Tolerancia de seguridad",
|
||||||
|
"safety_tolerance_tip": "Controla la tolerancia de seguridad en la generación de imágenes, solo aplicable a la versión FLUX.1-Kontext-pro",
|
||||||
"seed_tip": "Controla la aleatoriedad en la generación de imágenes, útil para reproducir resultados idénticos",
|
"seed_tip": "Controla la aleatoriedad en la generación de imágenes, útil para reproducir resultados idénticos",
|
||||||
"style_type_tip": "Estilo de generación de imágenes, solo aplicable para la versión V_2 y posteriores"
|
"style_type_tip": "Estilo de generación de imágenes, solo aplicable para la versión V_2 y posteriores",
|
||||||
|
"width": "Ancho"
|
||||||
},
|
},
|
||||||
"generated_image": "Generar imagen",
|
"generated_image": "Generar imagen",
|
||||||
"go_to_settings": "Ir a configuración",
|
"go_to_settings": "Ir a configuración",
|
||||||
@ -2699,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "Traducir con tres espacios rápidos",
|
"auto_translate_with_space": "Traducir con tres espacios rápidos",
|
||||||
|
"clear": {
|
||||||
|
"all": "Limpiar",
|
||||||
|
"knowledge_base": "Limpiar bases de conocimiento seleccionadas",
|
||||||
|
"models": "Limpiar todos los modelos"
|
||||||
|
},
|
||||||
"show_translate_confirm": "Mostrar diálogo de confirmación de traducción",
|
"show_translate_confirm": "Mostrar diálogo de confirmación de traducción",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "Chino simplificado",
|
"chinese": "Chino simplificado",
|
||||||
|
|||||||
@ -1578,6 +1578,7 @@
|
|||||||
"style_type_tip": "Style de l'image après édition, uniquement applicable aux versions V_2 et ultérieures"
|
"style_type_tip": "Style de l'image après édition, uniquement applicable aux versions V_2 et ultérieures"
|
||||||
},
|
},
|
||||||
"generate": {
|
"generate": {
|
||||||
|
"height": "Hauteur",
|
||||||
"magic_prompt_option_tip": "Интеллектуальная оптимизация подсказок для улучшения результатов генерации",
|
"magic_prompt_option_tip": "Интеллектуальная оптимизация подсказок для улучшения результатов генерации",
|
||||||
"model_tip": "Версия модели: V2 — это последняя модель API, V2A — быстрая модель, V_1 — первое поколение модели, _TURBO — ускоренная версия",
|
"model_tip": "Версия модели: V2 — это последняя модель API, V2A — быстрая модель, V_1 — первое поколение модели, _TURBO — ускоренная версия",
|
||||||
"negative_prompt_tip": "Описывает элементы, которые вы не хотите видеть на изображении. Поддерживается только версиями V_1, V_1_TURBO, V_2 и V_2_TURBO",
|
"negative_prompt_tip": "Описывает элементы, которые вы не хотите видеть на изображении. Поддерживается только версиями V_1, V_1_TURBO, V_2 и V_2_TURBO",
|
||||||
@ -1585,8 +1586,11 @@
|
|||||||
"person_generation": "Générer un personnage",
|
"person_generation": "Générer un personnage",
|
||||||
"person_generation_tip": "Autoriser le modèle à générer des images de personnages",
|
"person_generation_tip": "Autoriser le modèle à générer des images de personnages",
|
||||||
"rendering_speed_tip": "Contrôler l'équilibre entre la vitesse et la qualité du rendu, uniquement applicable à la version V_3",
|
"rendering_speed_tip": "Contrôler l'équilibre entre la vitesse et la qualité du rendu, uniquement applicable à la version V_3",
|
||||||
|
"safety_tolerance": "Tolérance de sécurité",
|
||||||
|
"safety_tolerance_tip": "Contrôle la tolérance de sécurité dans la génération d'images, uniquement applicable à la version FLUX.1-Kontext-pro",
|
||||||
"seed_tip": "Контролирует случайность генерации изображения, используется для воспроизведения одинаковых результатов",
|
"seed_tip": "Контролирует случайность генерации изображения, используется для воспроизведения одинаковых результатов",
|
||||||
"style_type_tip": "Стиль генерации изображения, применим к версии V_2 и выше"
|
"style_type_tip": "Стиль генерации изображения, применим к версии V_2 и выше",
|
||||||
|
"width": "Largeur"
|
||||||
},
|
},
|
||||||
"generated_image": "Image générée",
|
"generated_image": "Image générée",
|
||||||
"go_to_settings": "Aller aux paramètres",
|
"go_to_settings": "Aller aux paramètres",
|
||||||
@ -2699,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "Traduire en frappant rapidement 3 fois l'espace",
|
"auto_translate_with_space": "Traduire en frappant rapidement 3 fois l'espace",
|
||||||
|
"clear": {
|
||||||
|
"all": "Effacer",
|
||||||
|
"knowledge_base": "Effacer les bases de connaissances sélectionnées",
|
||||||
|
"models": "Effacer tous les modèles"
|
||||||
|
},
|
||||||
"show_translate_confirm": "Afficher la boîte de dialogue de confirmation de traduction",
|
"show_translate_confirm": "Afficher la boîte de dialogue de confirmation de traduction",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "Chinois simplifié",
|
"chinese": "Chinois simplifié",
|
||||||
|
|||||||
@ -1578,6 +1578,7 @@
|
|||||||
"style_type_tip": "Estilo da imagem editada, disponível apenas para a versão V_2 ou superior"
|
"style_type_tip": "Estilo da imagem editada, disponível apenas para a versão V_2 ou superior"
|
||||||
},
|
},
|
||||||
"generate": {
|
"generate": {
|
||||||
|
"height": "[to be translated]:高度",
|
||||||
"magic_prompt_option_tip": "Otimização inteligente do prompt para melhorar os resultados da geração",
|
"magic_prompt_option_tip": "Otimização inteligente do prompt para melhorar os resultados da geração",
|
||||||
"model_tip": "Versão do modelo: V2 é o modelo mais recente da interface, V2A é o modelo rápido, V_1 é o modelo de primeira geração e _TURBO é a versão acelerada",
|
"model_tip": "Versão do modelo: V2 é o modelo mais recente da interface, V2A é o modelo rápido, V_1 é o modelo de primeira geração e _TURBO é a versão acelerada",
|
||||||
"negative_prompt_tip": "Descreve elementos que você não deseja ver nas imagens; suportado apenas nas versões V_1, V_1_TURBO, V_2 e V_2_TURBO",
|
"negative_prompt_tip": "Descreve elementos que você não deseja ver nas imagens; suportado apenas nas versões V_1, V_1_TURBO, V_2 e V_2_TURBO",
|
||||||
@ -1585,8 +1586,11 @@
|
|||||||
"person_generation": "Gerar Personagem",
|
"person_generation": "Gerar Personagem",
|
||||||
"person_generation_tip": "Permite que o modelo gere imagens de personagens",
|
"person_generation_tip": "Permite que o modelo gere imagens de personagens",
|
||||||
"rendering_speed_tip": "Controla o equilíbrio entre velocidade e qualidade de renderização, aplicável apenas à versão V_3",
|
"rendering_speed_tip": "Controla o equilíbrio entre velocidade e qualidade de renderização, aplicável apenas à versão V_3",
|
||||||
|
"safety_tolerance": "[to be translated]:安全容忍度",
|
||||||
|
"safety_tolerance_tip": "[to be translated]:控制图像生成的安全容忍度,仅适用于 FLUX.1-Kontext-pro 版本",
|
||||||
"seed_tip": "Controla a aleatoriedade na geração das imagens, usado para reproduzir resultados idênticos",
|
"seed_tip": "Controla a aleatoriedade na geração das imagens, usado para reproduzir resultados idênticos",
|
||||||
"style_type_tip": "Estilo de geração da imagem, aplicável apenas às versões V_2 e superiores"
|
"style_type_tip": "Estilo de geração da imagem, aplicável apenas às versões V_2 e superiores",
|
||||||
|
"width": "[to be translated]:宽度"
|
||||||
},
|
},
|
||||||
"generated_image": "Imagem gerada",
|
"generated_image": "Imagem gerada",
|
||||||
"go_to_settings": "Ir para configurações",
|
"go_to_settings": "Ir para configurações",
|
||||||
@ -2699,6 +2703,11 @@
|
|||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"auto_translate_with_space": "Traduzir com três espaços rápidos",
|
"auto_translate_with_space": "Traduzir com três espaços rápidos",
|
||||||
|
"clear": {
|
||||||
|
"all": "[to be translated]:清除",
|
||||||
|
"knowledge_base": "[to be translated]:清除选中的知识库",
|
||||||
|
"models": "[to be translated]:清除@的所有模型"
|
||||||
|
},
|
||||||
"show_translate_confirm": "Mostrar diálogo de confirmação de tradução",
|
"show_translate_confirm": "Mostrar diálogo de confirmação de tradução",
|
||||||
"target_language": {
|
"target_language": {
|
||||||
"chinese": "Chinês simplificado",
|
"chinese": "Chinês simplificado",
|
||||||
|
|||||||
@ -58,8 +58,6 @@ import styled from 'styled-components'
|
|||||||
import NarrowLayout from '../Messages/NarrowLayout'
|
import NarrowLayout from '../Messages/NarrowLayout'
|
||||||
import AttachmentPreview from './AttachmentPreview'
|
import AttachmentPreview from './AttachmentPreview'
|
||||||
import InputbarTools, { InputbarToolsRef } from './InputbarTools'
|
import InputbarTools, { InputbarToolsRef } from './InputbarTools'
|
||||||
import KnowledgeBaseInput from './KnowledgeBaseInput'
|
|
||||||
import MentionModelsInput from './MentionModelsInput'
|
|
||||||
import SendMessageButton from './SendMessageButton'
|
import SendMessageButton from './SendMessageButton'
|
||||||
import TokenCount from './TokenCount'
|
import TokenCount from './TokenCount'
|
||||||
|
|
||||||
@ -439,11 +437,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableBackspaceDeleteModel && event.key === 'Backspace' && text.trim() === '' && mentionedModels.length > 0) {
|
|
||||||
setMentionedModels((prev) => prev.slice(0, -1))
|
|
||||||
return event.preventDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableBackspaceDeleteModel && event.key === 'Backspace' && text.trim() === '' && files.length > 0) {
|
if (enableBackspaceDeleteModel && event.key === 'Backspace' && text.trim() === '' && files.length > 0) {
|
||||||
setFiles((prev) => prev.slice(0, -1))
|
setFiles((prev) => prev.slice(0, -1))
|
||||||
return event.preventDefault()
|
return event.preventDefault()
|
||||||
@ -766,19 +759,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
setSelectedKnowledgeBases(bases ?? [])
|
setSelectedKnowledgeBases(bases ?? [])
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRemoveModel = (model: Model) => {
|
|
||||||
setMentionedModels(mentionedModels.filter((m) => m.id !== model.id))
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleRemoveKnowledgeBase = (knowledgeBase: KnowledgeBase) => {
|
|
||||||
const newKnowledgeBases = assistant.knowledge_bases?.filter((kb) => kb.id !== knowledgeBase.id)
|
|
||||||
updateAssistant({
|
|
||||||
...assistant,
|
|
||||||
knowledge_bases: newKnowledgeBases
|
|
||||||
})
|
|
||||||
setSelectedKnowledgeBases(newKnowledgeBases ?? [])
|
|
||||||
}
|
|
||||||
|
|
||||||
const onEnableGenerateImage = () => {
|
const onEnableGenerateImage = () => {
|
||||||
updateAssistant({ ...assistant, enableGenerateImage: !assistant.enableGenerateImage })
|
updateAssistant({ ...assistant, enableGenerateImage: !assistant.enableGenerateImage })
|
||||||
}
|
}
|
||||||
@ -858,15 +838,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
className={classNames('inputbar-container', inputFocus && 'focus', isFileDragging && 'file-dragging')}
|
className={classNames('inputbar-container', inputFocus && 'focus', isFileDragging && 'file-dragging')}
|
||||||
ref={containerRef}>
|
ref={containerRef}>
|
||||||
{files.length > 0 && <AttachmentPreview files={files} setFiles={setFiles} />}
|
{files.length > 0 && <AttachmentPreview files={files} setFiles={setFiles} />}
|
||||||
{selectedKnowledgeBases.length > 0 && (
|
|
||||||
<KnowledgeBaseInput
|
|
||||||
selectedKnowledgeBases={selectedKnowledgeBases}
|
|
||||||
onRemoveKnowledgeBase={handleRemoveKnowledgeBase}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{mentionedModels.length > 0 && (
|
|
||||||
<MentionModelsInput selectedModels={mentionedModels} onRemoveModel={handleRemoveModel} />
|
|
||||||
)}
|
|
||||||
<Textarea
|
<Textarea
|
||||||
value={text}
|
value={text}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@ -923,6 +894,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
resizeTextArea={resizeTextArea}
|
resizeTextArea={resizeTextArea}
|
||||||
mentionModels={mentionedModels}
|
mentionModels={mentionedModels}
|
||||||
onMentionModel={onMentionModel}
|
onMentionModel={onMentionModel}
|
||||||
|
onClearMentionModels={() => setMentionedModels([])}
|
||||||
couldMentionNotVisionModel={couldMentionNotVisionModel}
|
couldMentionNotVisionModel={couldMentionNotVisionModel}
|
||||||
couldAddImageFile={couldAddImageFile}
|
couldAddImageFile={couldAddImageFile}
|
||||||
onEnableGenerateImage={onEnableGenerateImage}
|
onEnableGenerateImage={onEnableGenerateImage}
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import {
|
|||||||
CircleChevronRight,
|
CircleChevronRight,
|
||||||
FileSearch,
|
FileSearch,
|
||||||
Globe,
|
Globe,
|
||||||
|
Hammer,
|
||||||
Languages,
|
Languages,
|
||||||
Link,
|
Link,
|
||||||
LucideSquareTerminal,
|
|
||||||
Maximize,
|
Maximize,
|
||||||
MessageSquareDiff,
|
MessageSquareDiff,
|
||||||
Minimize,
|
Minimize,
|
||||||
@ -67,6 +67,7 @@ export interface InputbarToolsProps {
|
|||||||
resizeTextArea: () => void
|
resizeTextArea: () => void
|
||||||
mentionModels: Model[]
|
mentionModels: Model[]
|
||||||
onMentionModel: (model: Model) => void
|
onMentionModel: (model: Model) => void
|
||||||
|
onClearMentionModels: () => void
|
||||||
couldMentionNotVisionModel: boolean
|
couldMentionNotVisionModel: boolean
|
||||||
couldAddImageFile: boolean
|
couldAddImageFile: boolean
|
||||||
onEnableGenerateImage: () => void
|
onEnableGenerateImage: () => void
|
||||||
@ -108,6 +109,7 @@ const InputbarTools = ({
|
|||||||
resizeTextArea,
|
resizeTextArea,
|
||||||
mentionModels,
|
mentionModels,
|
||||||
onMentionModel,
|
onMentionModel,
|
||||||
|
onClearMentionModels,
|
||||||
couldMentionNotVisionModel,
|
couldMentionNotVisionModel,
|
||||||
couldAddImageFile,
|
couldAddImageFile,
|
||||||
onEnableGenerateImage,
|
onEnableGenerateImage,
|
||||||
@ -200,7 +202,7 @@ const InputbarTools = ({
|
|||||||
{
|
{
|
||||||
label: t('settings.mcp.title'),
|
label: t('settings.mcp.title'),
|
||||||
description: t('settings.mcp.not_support'),
|
description: t('settings.mcp.not_support'),
|
||||||
icon: <LucideSquareTerminal />,
|
icon: <Hammer />,
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
action: () => {
|
action: () => {
|
||||||
mcpToolsButtonRef.current?.openQuickPanel()
|
mcpToolsButtonRef.current?.openQuickPanel()
|
||||||
@ -209,7 +211,7 @@ const InputbarTools = ({
|
|||||||
{
|
{
|
||||||
label: `MCP ${t('settings.mcp.tabs.prompts')}`,
|
label: `MCP ${t('settings.mcp.tabs.prompts')}`,
|
||||||
description: '',
|
description: '',
|
||||||
icon: <LucideSquareTerminal />,
|
icon: <Hammer />,
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
action: () => {
|
action: () => {
|
||||||
mcpToolsButtonRef.current?.openPromptList()
|
mcpToolsButtonRef.current?.openPromptList()
|
||||||
@ -218,7 +220,7 @@ const InputbarTools = ({
|
|||||||
{
|
{
|
||||||
label: `MCP ${t('settings.mcp.tabs.resources')}`,
|
label: `MCP ${t('settings.mcp.tabs.resources')}`,
|
||||||
description: '',
|
description: '',
|
||||||
icon: <LucideSquareTerminal />,
|
icon: <Hammer />,
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
action: () => {
|
action: () => {
|
||||||
mcpToolsButtonRef.current?.openResourcesList()
|
mcpToolsButtonRef.current?.openResourcesList()
|
||||||
@ -394,6 +396,7 @@ const InputbarTools = ({
|
|||||||
ref={mentionModelsButtonRef}
|
ref={mentionModelsButtonRef}
|
||||||
mentionedModels={mentionModels}
|
mentionedModels={mentionModels}
|
||||||
onMentionModel={onMentionModel}
|
onMentionModel={onMentionModel}
|
||||||
|
onClearMentionModels={onClearMentionModels}
|
||||||
ToolbarButton={ToolbarButton}
|
ToolbarButton={ToolbarButton}
|
||||||
couldMentionNotVisionModel={couldMentionNotVisionModel}
|
couldMentionNotVisionModel={couldMentionNotVisionModel}
|
||||||
files={files}
|
files={files}
|
||||||
@ -464,6 +467,7 @@ const InputbarTools = ({
|
|||||||
mentionModels,
|
mentionModels,
|
||||||
model,
|
model,
|
||||||
newTopicShortcut,
|
newTopicShortcut,
|
||||||
|
onClearMentionModels,
|
||||||
onEnableGenerateImage,
|
onEnableGenerateImage,
|
||||||
onMentionModel,
|
onMentionModel,
|
||||||
onNewContext,
|
onNewContext,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { QuickPanelListItem, useQuickPanel } from '@renderer/components/QuickPan
|
|||||||
import { useAppSelector } from '@renderer/store'
|
import { useAppSelector } from '@renderer/store'
|
||||||
import { KnowledgeBase } from '@renderer/types'
|
import { KnowledgeBase } from '@renderer/types'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { FileSearch, Plus } from 'lucide-react'
|
import { CircleX, FileSearch, Plus } from 'lucide-react'
|
||||||
import { FC, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
import { FC, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useNavigate } from 'react-router'
|
import { useNavigate } from 'react-router'
|
||||||
@ -44,28 +44,41 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
|||||||
)
|
)
|
||||||
|
|
||||||
const baseItems = useMemo<QuickPanelListItem[]>(() => {
|
const baseItems = useMemo<QuickPanelListItem[]>(() => {
|
||||||
const newList: QuickPanelListItem[] = knowledgeState.bases.map((base) => ({
|
const items: QuickPanelListItem[] = knowledgeState.bases.map((base) => ({
|
||||||
label: base.name,
|
label: base.name,
|
||||||
description: `${base.items.length} ${t('files.count')}`,
|
description: `${base.items.length} ${t('files.count')}`,
|
||||||
icon: <FileSearch />,
|
icon: <FileSearch />,
|
||||||
action: () => handleBaseSelect(base),
|
action: () => handleBaseSelect(base),
|
||||||
isSelected: selectedBases?.some((selected) => selected.id === base.id)
|
isSelected: selectedBases?.some((selected) => selected.id === base.id)
|
||||||
}))
|
}))
|
||||||
newList.push({
|
|
||||||
|
items.push({
|
||||||
label: t('knowledge.add.title') + '...',
|
label: t('knowledge.add.title') + '...',
|
||||||
icon: <Plus />,
|
icon: <Plus />,
|
||||||
action: () => navigate('/knowledge'),
|
action: () => navigate('/knowledge'),
|
||||||
isSelected: false
|
isSelected: false
|
||||||
})
|
})
|
||||||
return newList
|
|
||||||
}, [knowledgeState.bases, handleBaseSelect, selectedBases, t, navigate])
|
items.unshift({
|
||||||
|
label: t('settings.input.clear.all'),
|
||||||
|
description: t('settings.input.clear.knowledge_base'),
|
||||||
|
icon: <CircleX />,
|
||||||
|
isSelected: false,
|
||||||
|
action: () => {
|
||||||
|
onSelect([])
|
||||||
|
quickPanel.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return items
|
||||||
|
}, [knowledgeState.bases, t, selectedBases, handleBaseSelect, navigate, onSelect, quickPanel])
|
||||||
|
|
||||||
const openQuickPanel = useCallback(() => {
|
const openQuickPanel = useCallback(() => {
|
||||||
quickPanel.open({
|
quickPanel.open({
|
||||||
title: t('chat.input.knowledge_base'),
|
title: t('chat.input.knowledge_base'),
|
||||||
list: baseItems,
|
list: baseItems,
|
||||||
symbol: '#',
|
symbol: '#',
|
||||||
multiple: false,
|
multiple: true,
|
||||||
afterAction({ item }) {
|
afterAction({ item }) {
|
||||||
item.isSelected = !item.isSelected
|
item.isSelected = !item.isSelected
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
|||||||
import { EventEmitter } from '@renderer/services/EventService'
|
import { EventEmitter } from '@renderer/services/EventService'
|
||||||
import { Assistant, MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
|
import { Assistant, MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
|
||||||
import { Form, Input, Tooltip } from 'antd'
|
import { Form, Input, Tooltip } from 'antd'
|
||||||
import { CircleX, Plus, SquareTerminal } from 'lucide-react'
|
import { CircleX, Hammer, Plus } from 'lucide-react'
|
||||||
import React, { FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
import React, { FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useNavigate } from 'react-router'
|
import { useNavigate } from 'react-router'
|
||||||
@ -168,7 +168,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
|||||||
const newList: QuickPanelListItem[] = activedMcpServers.map((server) => ({
|
const newList: QuickPanelListItem[] = activedMcpServers.map((server) => ({
|
||||||
label: server.name,
|
label: server.name,
|
||||||
description: server.description || server.baseUrl,
|
description: server.description || server.baseUrl,
|
||||||
icon: <SquareTerminal />,
|
icon: <Hammer />,
|
||||||
action: () => EventEmitter.emit('mcp-server-select', server),
|
action: () => EventEmitter.emit('mcp-server-select', server),
|
||||||
isSelected: assistantMcpServers.some((s) => s.id === server.id)
|
isSelected: assistantMcpServers.some((s) => s.id === server.id)
|
||||||
}))
|
}))
|
||||||
@ -180,7 +180,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
|||||||
})
|
})
|
||||||
|
|
||||||
newList.unshift({
|
newList.unshift({
|
||||||
label: t('common.close'),
|
label: t('settings.input.clear.all'),
|
||||||
description: t('settings.mcp.disable.description'),
|
description: t('settings.mcp.disable.description'),
|
||||||
icon: <CircleX />,
|
icon: <CircleX />,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
@ -335,7 +335,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
|||||||
return prompts.map((prompt) => ({
|
return prompts.map((prompt) => ({
|
||||||
label: prompt.name,
|
label: prompt.name,
|
||||||
description: prompt.description,
|
description: prompt.description,
|
||||||
icon: <SquareTerminal />,
|
icon: <Hammer />,
|
||||||
action: () => handlePromptSelect(prompt as MCPPromptWithArgs)
|
action: () => handlePromptSelect(prompt as MCPPromptWithArgs)
|
||||||
}))
|
}))
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@ -415,7 +415,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
|||||||
resources.map((resource) => ({
|
resources.map((resource) => ({
|
||||||
label: resource.name,
|
label: resource.name,
|
||||||
description: resource.description,
|
description: resource.description,
|
||||||
icon: <SquareTerminal />,
|
icon: <Hammer />,
|
||||||
action: () => handleResourceSelect(resource)
|
action: () => handleResourceSelect(resource)
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
@ -456,7 +456,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
|||||||
return (
|
return (
|
||||||
<Tooltip placement="top" title={t('settings.mcp.title')} mouseLeaveDelay={0} arrow>
|
<Tooltip placement="top" title={t('settings.mcp.title')} mouseLeaveDelay={0} arrow>
|
||||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||||
<SquareTerminal
|
<Hammer
|
||||||
size={18}
|
size={18}
|
||||||
color={assistant.mcpServers && assistant.mcpServers.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)'}
|
color={assistant.mcpServers && assistant.mcpServers.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)'}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { getFancyProviderName } from '@renderer/utils'
|
|||||||
import { Avatar, Tooltip } from 'antd'
|
import { Avatar, Tooltip } from 'antd'
|
||||||
import { useLiveQuery } from 'dexie-react-hooks'
|
import { useLiveQuery } from 'dexie-react-hooks'
|
||||||
import { first, sortBy } from 'lodash'
|
import { first, sortBy } from 'lodash'
|
||||||
import { AtSign, Plus } from 'lucide-react'
|
import { AtSign, CircleX, Plus } from 'lucide-react'
|
||||||
import { FC, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
import { FC, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useNavigate } from 'react-router'
|
import { useNavigate } from 'react-router'
|
||||||
@ -24,6 +24,7 @@ interface Props {
|
|||||||
ref?: React.RefObject<MentionModelsButtonRef | null>
|
ref?: React.RefObject<MentionModelsButtonRef | null>
|
||||||
mentionedModels: Model[]
|
mentionedModels: Model[]
|
||||||
onMentionModel: (model: Model) => void
|
onMentionModel: (model: Model) => void
|
||||||
|
onClearMentionModels: () => void
|
||||||
couldMentionNotVisionModel: boolean
|
couldMentionNotVisionModel: boolean
|
||||||
files: FileType[]
|
files: FileType[]
|
||||||
ToolbarButton: any
|
ToolbarButton: any
|
||||||
@ -34,6 +35,7 @@ const MentionModelsButton: FC<Props> = ({
|
|||||||
ref,
|
ref,
|
||||||
mentionedModels,
|
mentionedModels,
|
||||||
onMentionModel,
|
onMentionModel,
|
||||||
|
onClearMentionModels,
|
||||||
couldMentionNotVisionModel,
|
couldMentionNotVisionModel,
|
||||||
files,
|
files,
|
||||||
ToolbarButton,
|
ToolbarButton,
|
||||||
@ -134,8 +136,29 @@ const MentionModelsButton: FC<Props> = ({
|
|||||||
isSelected: false
|
isSelected: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
items.unshift({
|
||||||
|
label: t('settings.input.clear.all'),
|
||||||
|
description: t('settings.input.clear.models'),
|
||||||
|
icon: <CircleX />,
|
||||||
|
isSelected: false,
|
||||||
|
action: () => {
|
||||||
|
onClearMentionModels()
|
||||||
|
quickPanel.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return items
|
return items
|
||||||
}, [pinnedModels, providers, t, couldMentionNotVisionModel, mentionedModels, onMentionModel, navigate])
|
}, [
|
||||||
|
pinnedModels,
|
||||||
|
providers,
|
||||||
|
t,
|
||||||
|
couldMentionNotVisionModel,
|
||||||
|
mentionedModels,
|
||||||
|
onMentionModel,
|
||||||
|
navigate,
|
||||||
|
quickPanel,
|
||||||
|
onClearMentionModels
|
||||||
|
])
|
||||||
|
|
||||||
const openQuickPanel = useCallback(
|
const openQuickPanel = useCallback(
|
||||||
(triggerInfo?: { type: 'input' | 'button'; position?: number; originalText?: string }) => {
|
(triggerInfo?: { type: 'input' | 'button'; position?: number; originalText?: string }) => {
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
|
||||||
import { useProviders } from '@renderer/hooks/useProvider'
|
|
||||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
|
||||||
import { Model } from '@renderer/types'
|
|
||||||
import { getFancyProviderName } from '@renderer/utils'
|
|
||||||
import { FC } from 'react'
|
|
||||||
import styled from 'styled-components'
|
|
||||||
|
|
||||||
const MentionModelsInput: FC<{
|
|
||||||
selectedModels: Model[]
|
|
||||||
onRemoveModel: (model: Model) => void
|
|
||||||
}> = ({ selectedModels, onRemoveModel }) => {
|
|
||||||
const { providers } = useProviders()
|
|
||||||
|
|
||||||
const getProviderName = (model: Model) => {
|
|
||||||
const provider = providers.find((p) => p.id === model?.provider)
|
|
||||||
return provider ? getFancyProviderName(provider) : ''
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
{selectedModels.map((model) => (
|
|
||||||
<CustomTag
|
|
||||||
icon={<i className="iconfont icon-at" />}
|
|
||||||
color="#1677ff"
|
|
||||||
key={getModelUniqId(model)}
|
|
||||||
closable
|
|
||||||
onClose={() => onRemoveModel(model)}>
|
|
||||||
{model.name} ({getProviderName(model)})
|
|
||||||
</CustomTag>
|
|
||||||
))}
|
|
||||||
</Container>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Container = styled.div`
|
|
||||||
width: 100%;
|
|
||||||
padding: 5px 15px 5px 15px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 4px 4px;
|
|
||||||
`
|
|
||||||
|
|
||||||
export default MentionModelsInput
|
|
||||||
@ -8,13 +8,13 @@ import {
|
|||||||
Cloud,
|
Cloud,
|
||||||
Command,
|
Command,
|
||||||
FileCode,
|
FileCode,
|
||||||
|
Hammer,
|
||||||
HardDrive,
|
HardDrive,
|
||||||
Info,
|
Info,
|
||||||
MonitorCog,
|
MonitorCog,
|
||||||
Package,
|
Package,
|
||||||
PictureInPicture2,
|
PictureInPicture2,
|
||||||
Settings2,
|
Settings2,
|
||||||
SquareTerminal,
|
|
||||||
TextCursorInput,
|
TextCursorInput,
|
||||||
Zap
|
Zap
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
@ -84,7 +84,7 @@ const SettingsPage: FC = () => {
|
|||||||
<Divider />
|
<Divider />
|
||||||
<MenuItemLink to="/settings/mcp">
|
<MenuItemLink to="/settings/mcp">
|
||||||
<MenuItem className={isRoute('/settings/mcp')}>
|
<MenuItem className={isRoute('/settings/mcp')}>
|
||||||
<SquareTerminal size={18} />
|
<Hammer size={18} />
|
||||||
{t('settings.mcp.title')}
|
{t('settings.mcp.title')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user