commit
216b21de2a
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
[](https://discord.gg/bu54382uBd)
|
[](https://discord.gg/bu54382uBd)
|
||||||
|
|
||||||
Page Assist is an open-source Chrome Extension that provides a Sidebar and Web UI for your Local AI model. It allows you to interact with your model from any webpage.
|
Page Assist is an open-source browser extension that provides a sidebar and web UI for your local AI model. It allows you to interact with your model from any webpage.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Page Assist supports Chromium-based browsers like Chrome, Brave, and Edge, as well as Firefox.
|
Page Assist supports Chromium-based browsers like Chrome, Brave, and Edge, as well as Firefox.
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Venligst vælg en model for at forsæætte",
|
"validationSelectModel": "Venligst vælg en model for at forsæætte",
|
||||||
"deleteHistoryConfirmation": "Er du sikker på at du vil slette denne historik?",
|
"deleteHistoryConfirmation": "Er du sikker på at du vil slette denne historik?",
|
||||||
"editHistoryTitle": "Indtast en ny titel",
|
"editHistoryTitle": "Indtast en ny titel",
|
||||||
"temporaryChat": "Midlertidig Chat"
|
"temporaryChat": "Midlertidig Chat",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Kopier",
|
||||||
|
"asText": "Kopier som tekst",
|
||||||
|
"asMarkdown": "Kopier som Markdown",
|
||||||
|
"success": "Kopieret til udklipsholder!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Download",
|
||||||
|
"text": "Tekstfil (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON-fil (.json)"
|
||||||
|
},
|
||||||
|
"share": "Del"
|
||||||
|
}
|
||||||
}
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API Nøgle",
|
||||||
|
"placeholder": "Indtast din Brave API nøgle"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Systemindstillinger",
|
"heading": "Systemindstillinger",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Slet Chathistorik",
|
"label": "System Nulstilling",
|
||||||
"button": "Slet",
|
"button": "Nulstil Alt",
|
||||||
"confirm": "Er du sikker på, at du vil slette din chathistorik? Denne handling kan ikke fortrydes."
|
"confirm": "Er du sikker på, at du vil udføre en systemnulstilling? Dette vil slette alle data og kan ikke fortrydes."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Eksporter chathistorik, vidensbase og prompts",
|
"label": "Eksporter chathistorik, vidensbase og prompts",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Bitte wähle ein Modell aus, um fortzufahren",
|
"validationSelectModel": "Bitte wähle ein Modell aus, um fortzufahren",
|
||||||
"deleteHistoryConfirmation": "Bist du sicher, dass du diesen Verlauf löschen möchtest?",
|
"deleteHistoryConfirmation": "Bist du sicher, dass du diesen Verlauf löschen möchtest?",
|
||||||
"editHistoryTitle": "Gib einen neuen Titel ein",
|
"editHistoryTitle": "Gib einen neuen Titel ein",
|
||||||
"temporaryChat": "Temporärer Chat"
|
"temporaryChat": "Temporärer Chat",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Kopieren",
|
||||||
|
"asText": "Als Text kopieren",
|
||||||
|
"asMarkdown": "Als Markdown kopieren",
|
||||||
|
"success": "In die Zwischenablage kopiert!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Herunterladen",
|
||||||
|
"text": "Textdatei (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON-Datei (.json)"
|
||||||
|
},
|
||||||
|
"share": "Teilen"
|
||||||
|
}
|
||||||
}
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG-URL"
|
"label": "SearXNG-URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API-Schlüssel",
|
||||||
|
"placeholder": "Geben Sie Ihren Brave API-Schlüssel ein"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Systemeinstellungen",
|
"heading": "Systemeinstellungen",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Chatverlauf löschen",
|
"label": "System zurücksetzen",
|
||||||
"button": "Löschen",
|
"button": "Alles zurücksetzen",
|
||||||
"confirm": "Sind Sie sicher, dass Sie Ihren Chatverlauf löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden."
|
"confirm": "Sind Sie sicher, dass Sie einen Systemreset durchführen möchten? Dies löscht alle Daten und kann nicht rückgängig gemacht werden."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Chatverlauf, Wissensbasis und Prompts exportieren",
|
"label": "Chatverlauf, Wissensbasis und Prompts exportieren",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Please select a model to continue",
|
"validationSelectModel": "Please select a model to continue",
|
||||||
"deleteHistoryConfirmation": "Are you sure you want to delete this history?",
|
"deleteHistoryConfirmation": "Are you sure you want to delete this history?",
|
||||||
"editHistoryTitle": "Enter a new title",
|
"editHistoryTitle": "Enter a new title",
|
||||||
"temporaryChat": "Temporary Chat"
|
"temporaryChat": "Temporary Chat",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Copy",
|
||||||
|
"asText": "Copy as Text",
|
||||||
|
"asMarkdown": "Copy as Markdown",
|
||||||
|
"success": "Copied to clipboard!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Download",
|
||||||
|
"text": "Text File (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON File (.json)"
|
||||||
|
},
|
||||||
|
"share": "Share"
|
||||||
|
}
|
||||||
}
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API Key",
|
||||||
|
"placeholder": "Enter your Brave API key"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "System Settings",
|
"heading": "System Settings",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Delete Chat History",
|
"label": "System Reset",
|
||||||
"button": "Delete",
|
"button": "Reset All",
|
||||||
"confirm": "Are you sure you want to delete your chat history? This action cannot be undone."
|
"confirm": "Are you sure you want to perform a system reset? This will clear all data and cannot be undone."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Export Chat History, Knowledge Base, and Prompts",
|
"label": "Export Chat History, Knowledge Base, and Prompts",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Selecione un modelo para continuar",
|
"validationSelectModel": "Selecione un modelo para continuar",
|
||||||
"deleteHistoryConfirmation": "¿Esta seguro que quiere borrar éste histórico?",
|
"deleteHistoryConfirmation": "¿Esta seguro que quiere borrar éste histórico?",
|
||||||
"editHistoryTitle": "Ingrese un nuevo título",
|
"editHistoryTitle": "Ingrese un nuevo título",
|
||||||
"temporaryChat": "Chat Temporal"
|
"temporaryChat": "Chat Temporal",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Copiar",
|
||||||
|
"asText": "Copiar como Texto",
|
||||||
|
"asMarkdown": "Copiar como Markdown",
|
||||||
|
"success": "¡Copiado al portapapeles!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Descargar",
|
||||||
|
"text": "Archivo de Texto (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "Archivo JSON (.json)"
|
||||||
|
},
|
||||||
|
"share": "Compartir"
|
||||||
|
}
|
||||||
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "URL de SearXNG"
|
"label": "URL de SearXNG"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Clave API de Brave",
|
||||||
|
"placeholder": "Ingrese su clave API de Brave"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Configuraciones del Sistema",
|
"heading": "Configuraciones del Sistema",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Borrar Histórico del Chat",
|
"label": "Reinicio del Sistema",
|
||||||
"button": "Borrar",
|
"button": "Reiniciar Todo",
|
||||||
"confirm": "¿Esta seguro que desea borrar su histórico del chat? Esta acción no podra ser desecha."
|
"confirm": "¿Está seguro de que desea realizar un reinicio del sistema? Esto borrará todos los datos y no se puede deshacer."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Exportar Histórico del Chat, Base de Conocimiento y Prompts",
|
"label": "Exportar Histórico del Chat, Base de Conocimiento y Prompts",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "لطفا یک مدل را برای ادامه انتخاب کنید",
|
"validationSelectModel": "لطفا یک مدل را برای ادامه انتخاب کنید",
|
||||||
"deleteHistoryConfirmation": "آیا مطمئن هستید که می خواهید این تاریخچه را حذف کنید؟",
|
"deleteHistoryConfirmation": "آیا مطمئن هستید که می خواهید این تاریخچه را حذف کنید؟",
|
||||||
"editHistoryTitle": "یک عنوان جدید وارد کنید",
|
"editHistoryTitle": "یک عنوان جدید وارد کنید",
|
||||||
"temporaryChat": "گپ موقت"
|
"temporaryChat": "گپ موقت",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "کپی",
|
||||||
|
"asText": "کپی به صورت متن",
|
||||||
|
"asMarkdown": "کپی به صورت مارکداون",
|
||||||
|
"success": "در کلیپبورد کپی شد!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "دانلود",
|
||||||
|
"text": "فایل متنی (.txt)",
|
||||||
|
"markdown": "مارکداون (.md)",
|
||||||
|
"json": "فایل JSON (.json)"
|
||||||
|
},
|
||||||
|
"share": "اشتراکگذاری"
|
||||||
|
}
|
||||||
|
}
|
@ -67,14 +67,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "آدرس SearXNG"
|
"label": "آدرس SearXNG"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "کلید API بریو",
|
||||||
|
"placeholder": "کلید API بریو خود را وارد کنید"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "تنظیمات سیستم",
|
"heading": "تنظیمات سیستم",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "حذف تاریخچه گفتگو",
|
"label": "بازنشانی سیستم",
|
||||||
"button": "حذف",
|
"button": "بازنشانی همه",
|
||||||
"confirm": "آیا مطمئن هستید که می خواهید تاریخچه گفتگوهای خود را حذف کنید؟ این عمل قابل برگشت نیست."
|
"confirm": "آیا مطمئن هستید که میخواهید بازنشانی سیستم را انجام دهید؟ این کار تمام دادهها را پاک میکند و غیرقابل برگشت است."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "تاریخچه گپ، پایگاه دانش و پرامپتها را اکسپورت کنید",
|
"label": "تاریخچه گپ، پایگاه دانش و پرامپتها را اکسپورت کنید",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Veuillez sélectionner un modèle pour continuer",
|
"validationSelectModel": "Veuillez sélectionner un modèle pour continuer",
|
||||||
"deleteHistoryConfirmation": "Êtes-vous sûr de vouloir supprimer cette historique ?",
|
"deleteHistoryConfirmation": "Êtes-vous sûr de vouloir supprimer cette historique ?",
|
||||||
"editHistoryTitle": "Entrez un nouveau titre",
|
"editHistoryTitle": "Entrez un nouveau titre",
|
||||||
"temporaryChat": "Chat temporaire"
|
"temporaryChat": "Chat temporaire",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Copier",
|
||||||
|
"asText": "Copier en texte",
|
||||||
|
"asMarkdown": "Copier en Markdown",
|
||||||
|
"success": "Copié dans le presse-papiers !"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Télécharger",
|
||||||
|
"text": "Fichier texte (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "Fichier JSON (.json)"
|
||||||
|
},
|
||||||
|
"share": "Partager"
|
||||||
|
}
|
||||||
}
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "URL SearXNG"
|
"label": "URL SearXNG"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Clé API Brave",
|
||||||
|
"placeholder": "Entrez votre clé API Brave"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Les paramètres du système",
|
"heading": "Les paramètres du système",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Supprimer l'historique du chat",
|
"label": "Réinitialisation du système",
|
||||||
"button": "Supprimer",
|
"button": "Tout réinitialiser",
|
||||||
"confirm": "Êtes-vous sûr de vouloir supprimer l'historique de votre chat? Cette action ne peut pas être annulée."
|
"confirm": "Êtes-vous sûr de vouloir effectuer une réinitialisation du système ? Cela effacera toutes les données et ne pourra pas être annulé."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Exporter l'historique du chat, la base de connaissances et les invites",
|
"label": "Exporter l'historique du chat, la base de connaissances et les invites",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Scegliere un modello per continuare",
|
"validationSelectModel": "Scegliere un modello per continuare",
|
||||||
"deleteHistoryConfirmation": "Sei sicuro che vuoi eliminare la cronologia?",
|
"deleteHistoryConfirmation": "Sei sicuro che vuoi eliminare la cronologia?",
|
||||||
"editHistoryTitle": "Inserisci un nuovo titolo",
|
"editHistoryTitle": "Inserisci un nuovo titolo",
|
||||||
"temporaryChat": "Chat Temporanea"
|
"temporaryChat": "Chat Temporanea",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Copia",
|
||||||
|
"asText": "Copia come Testo",
|
||||||
|
"asMarkdown": "Copia come Markdown",
|
||||||
|
"success": "Copiato negli appunti!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Scarica",
|
||||||
|
"text": "File di Testo (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "File JSON (.json)"
|
||||||
|
},
|
||||||
|
"share": "Condividi"
|
||||||
|
}
|
||||||
}
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "URL SearXNG"
|
"label": "URL SearXNG"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Chiave API Brave",
|
||||||
|
"placeholder": "Inserisci la tua chiave API Brave"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Impostazioni di Sistema",
|
"heading": "Impostazioni di Sistema",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Elimina cronologia Chat",
|
"label": "Reset del Sistema",
|
||||||
"button": "Elimina",
|
"button": "Reset Totale",
|
||||||
"confirm": "Sei sicuro che vuoi eliminare la tua cronologia delle chat? Questa azione non può essere annullata."
|
"confirm": "Sei sicuro di voler eseguire un reset del sistema? Questa operazione cancellerà tutti i dati e non può essere annullata."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Esporta la cronologia Chat, Base di Conoscenza, e Prompts",
|
"label": "Esporta la cronologia Chat, Base di Conoscenza, e Prompts",
|
||||||
|
@ -1,13 +1,28 @@
|
|||||||
{
|
{
|
||||||
"newChat": "新しいチャット",
|
"newChat": "新しいチャット",
|
||||||
"selectAPrompt": "プロンプトを選択",
|
"selectAPrompt": "プロンプトを選択",
|
||||||
"githubRepository": "GitHubリポジトリ",
|
"githubRepository": "GitHubリポジトリ",
|
||||||
"settings": "設定",
|
"settings": "設定",
|
||||||
"sidebarTitle": "チャット履歴",
|
"sidebarTitle": "チャット履歴",
|
||||||
"error": "エラー",
|
"error": "エラー",
|
||||||
"somethingWentWrong": "何かが間違っています",
|
"somethingWentWrong": "何かが間違っています",
|
||||||
"validationSelectModel": "続行するにはモデルを選択してください",
|
"validationSelectModel": "続行するにはモデルを選択してください",
|
||||||
"deleteHistoryConfirmation": "この履歴を削除しますか?",
|
"deleteHistoryConfirmation": "この履歴を削除しますか?",
|
||||||
"editHistoryTitle": "新しいタイトルを入力",
|
"editHistoryTitle": "新しいタイトルを入力",
|
||||||
"temporaryChat": "一時的なチャット"
|
"temporaryChat": "一時的なチャット",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "コピー",
|
||||||
|
"asText": "テキストとしてコピー",
|
||||||
|
"asMarkdown": "Markdownとしてコピー",
|
||||||
|
"success": "クリップボードにコピーしました!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "ダウンロード",
|
||||||
|
"text": "テキストファイル (.txt)",
|
||||||
|
"markdown": "Markdownファイル (.md)",
|
||||||
|
"json": "JSONファイル (.json)"
|
||||||
|
},
|
||||||
|
"share": "共有"
|
||||||
|
}
|
||||||
|
}
|
@ -73,14 +73,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave APIキー",
|
||||||
|
"placeholder": "Brave APIキーを入力してください"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "システム設定",
|
"heading": "システム設定",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "チャット履歴を削除する",
|
"label": "システムリセット",
|
||||||
"button": "削除",
|
"button": "すべてリセット",
|
||||||
"confirm": "チャット履歴を削除してもよろしいですか?この操作は元に戻せません。"
|
"confirm": "システムリセットを実行してもよろしいですか?すべてのデータが消去され、元に戻すことはできません。"
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "チャット履歴、知識ベース、プロンプトをエクスポート",
|
"label": "チャット履歴、知識ベース、プロンプトをエクスポート",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "계속하려면 모델을 선택하세요",
|
"validationSelectModel": "계속하려면 모델을 선택하세요",
|
||||||
"deleteHistoryConfirmation": "이 기록을 삭제하시겠습니까?",
|
"deleteHistoryConfirmation": "이 기록을 삭제하시겠습니까?",
|
||||||
"editHistoryTitle": "새 제목 입력",
|
"editHistoryTitle": "새 제목 입력",
|
||||||
"temporaryChat": "임시 채팅"
|
"temporaryChat": "임시 채팅",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "복사",
|
||||||
|
"asText": "텍스트로 복사",
|
||||||
|
"asMarkdown": "마크다운으로 복사",
|
||||||
|
"success": "클립보드에 복사되었습니다!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "다운로드",
|
||||||
|
"text": "텍스트 파일 (.txt)",
|
||||||
|
"markdown": "마크다운 (.md)",
|
||||||
|
"json": "JSON 파일 (.json)"
|
||||||
|
},
|
||||||
|
"share": "공유"
|
||||||
|
}
|
||||||
|
}
|
@ -73,14 +73,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API 키",
|
||||||
|
"placeholder": "Brave API 키를 입력하세요"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "시스템 설정",
|
"heading": "시스템 설정",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "채팅 기록 삭제",
|
"label": "시스템 초기화",
|
||||||
"button": "삭제",
|
"button": "전체 초기화",
|
||||||
"confirm": "채팅 기록을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다."
|
"confirm": "시스템을 초기화하시겠습니까? 모든 데이터가 삭제되며 되돌릴 수 없습니다."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "채팅 기록, 지식 베이스, 프롬프트 내보내기",
|
"label": "채팅 기록, 지식 베이스, 프롬프트 내보내기",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"deleteHistoryConfirmation": "നിങ്ങളുടെ ചാറ്റ് ചരിത്രം ഇല്ലാതാക്കണമെന്ന് തീർച്ചയാണോ?",
|
"deleteHistoryConfirmation": "നിങ്ങളുടെ ചാറ്റ് ചരിത്രം ഇല്ലാതാക്കണമെന്ന് തീർച്ചയാണോ?",
|
||||||
"editHistoryTitle": "ചാറ്റ് title എഡിറ്റുചെയ്യുക",
|
"editHistoryTitle": "ചാറ്റ് title എഡിറ്റുചെയ്യുക",
|
||||||
"validationSelectModel": "തുടരുന്നതിന് ഒരു മോഡല് തിരഞ്ഞെടുക്കുക",
|
"validationSelectModel": "തുടരുന്നതിന് ഒരു മോഡല് തിരഞ്ഞെടുക്കുക",
|
||||||
"temporaryChat": "താൽക്കാലിക ചാറ്റ്"
|
"temporaryChat": "താൽക്കാലിക ചാറ്റ്",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "പകർത്തുക",
|
||||||
|
"asText": "ടെക്സ്റ്റായി പകർത്തുക",
|
||||||
|
"asMarkdown": "മാർക്ക്ഡൗൺ ആയി പകർത്തുക",
|
||||||
|
"success": "ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തി!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "ഡൗൺലോഡ്",
|
||||||
|
"text": "ടെക്സ്റ്റ് ഫയൽ (.txt)",
|
||||||
|
"markdown": "മാർക്ക്ഡൗൺ (.md)",
|
||||||
|
"json": "JSON ഫയൽ (.json)"
|
||||||
|
},
|
||||||
|
"share": "പങ്കുവയ്ക്കുക"
|
||||||
|
}
|
||||||
}
|
}
|
@ -73,14 +73,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "ബ്രേവ് API കീ",
|
||||||
|
"placeholder": "നിങ്ങളുടെ ബ്രേവ് API കീ നൽകുക"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "സിസ്റ്റം ക്രമീകരണങ്ങൾ",
|
"heading": "സിസ്റ്റം ക്രമീകരണങ്ങൾ",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "ചാറ്റ് ചരിത്രം ഇല്ലാതാക്കുക",
|
"label": "സിസ്റ്റം റീസെറ്റ്",
|
||||||
"button": "ഇല്ലാതാക്കുക",
|
"button": "എല്ലാം റീസെറ്റ് ചെയ്യുക",
|
||||||
"confirm": "നിങ്ങളുടെ ചാറ്റ് ചരിത്രം ഇല്ലാതാക്കണമെന്ന് ഉറപ്പാണോ? ഈ പ്രവർത്തനം പിന്നീട് പിന്വലിക്കാനാവില്ല."
|
"confirm": "നിങ്ങൾക്ക് സിസ്റ്റം റീസെറ്റ് നടത്താൻ തീർച്ചയാണോ? ഇത് എല്ലാ ഡാറ്റയും മായ്ക്കും, പിന്നീട് പുനഃസ്ഥാപിക്കാൻ കഴിയില്ല."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "ചാറ്റ് ചരിത്രം, അറിവ് അടിസ്ഥാനം, പ്രോംപ്റ്റുകൾ എക്സ്പോർട്ട് ചെയ്യുക",
|
"label": "ചാറ്റ് ചരിത്രം, അറിവ് അടിസ്ഥാനം, പ്രോംപ്റ്റുകൾ എക്സ്പോർട്ട് ചെയ്യുക",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Vennligst velg en modell for å fortsette",
|
"validationSelectModel": "Vennligst velg en modell for å fortsette",
|
||||||
"deleteHistoryConfirmation": "Er du sikker på at du vil slette denne historikken?",
|
"deleteHistoryConfirmation": "Er du sikker på at du vil slette denne historikken?",
|
||||||
"editHistoryTitle": "Skriv inn en ny tittel",
|
"editHistoryTitle": "Skriv inn en ny tittel",
|
||||||
"temporaryChat": "Midlertidig Chat"
|
"temporaryChat": "Midlertidig Chat",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Kopier",
|
||||||
|
"asText": "Kopier som tekst",
|
||||||
|
"asMarkdown": "Kopier som Markdown",
|
||||||
|
"success": "Kopiert til utklippstavlen!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Last ned",
|
||||||
|
"text": "Tekstfil (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON-fil (.json)"
|
||||||
|
},
|
||||||
|
"share": "Del"
|
||||||
|
}
|
||||||
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API Nøkkel",
|
||||||
|
"placeholder": "Skriv inn din Brave API nøkkel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Systeminnstillinger",
|
"heading": "Systeminnstillinger",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Slett Chathistorikk",
|
"label": "System Tilbakestilling",
|
||||||
"button": "Slett",
|
"button": "Tilbakestill Alt",
|
||||||
"confirm": "Er du sikker på at du vil slette chathistorikken din? Denne handlingen kan ikke angres."
|
"confirm": "Er du sikker på at du vil utføre en system tilbakestilling? Dette vil slette alle data og kan ikke angres."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Eksporter chathistorikk, kunnskapsbase og prompts",
|
"label": "Eksporter chathistorikk, kunnskapsbase og prompts",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Por favor, selecione um modelo para continuar",
|
"validationSelectModel": "Por favor, selecione um modelo para continuar",
|
||||||
"deleteHistoryConfirmation": "Tem certeza de que deseja excluir este histórico?",
|
"deleteHistoryConfirmation": "Tem certeza de que deseja excluir este histórico?",
|
||||||
"editHistoryTitle": "Digite um novo título",
|
"editHistoryTitle": "Digite um novo título",
|
||||||
"temporaryChat": "Chat Temporário"
|
"temporaryChat": "Chat Temporário",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Copiar",
|
||||||
|
"asText": "Copiar como Texto",
|
||||||
|
"asMarkdown": "Copiar como Markdown",
|
||||||
|
"success": "Copiado para área de transferência!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Baixar",
|
||||||
|
"text": "Arquivo de Texto (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "Arquivo JSON (.json)"
|
||||||
|
},
|
||||||
|
"share": "Compartilhar"
|
||||||
|
}
|
||||||
}
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "URL do SearXNG"
|
"label": "URL do SearXNG"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Chave da API do Brave",
|
||||||
|
"placeholder": "Digite sua chave da API do Brave"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Configurações do Sistema",
|
"heading": "Configurações do Sistema",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Excluir Histórico de Chat",
|
"label": "Reiniciar Sistema",
|
||||||
"button": "Excluir",
|
"button": "Reiniciar Tudo",
|
||||||
"confirm": "Tem certeza de que deseja excluir seu histórico de chat? Esta ação não pode ser desfeita."
|
"confirm": "Tem certeza que deseja realizar um reinício do sistema? Isso irá apagar todos os dados e não poderá ser desfeito."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Exportar Histórico de Chat, Base de Conhecimento e Prompts",
|
"label": "Exportar Histórico de Chat, Base de Conhecimento e Prompts",
|
||||||
|
@ -9,5 +9,19 @@
|
|||||||
"validationSelectModel": "Пожалуйста, выберите модель, чтобы продолжить",
|
"validationSelectModel": "Пожалуйста, выберите модель, чтобы продолжить",
|
||||||
"deleteHistoryConfirmation": "Вы уверены, что хотите удалить эту историю?",
|
"deleteHistoryConfirmation": "Вы уверены, что хотите удалить эту историю?",
|
||||||
"editHistoryTitle": "Введите новое название",
|
"editHistoryTitle": "Введите новое название",
|
||||||
"temporaryChat": "Временный чат"
|
"temporaryChat": "Временный чат",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Копировать",
|
||||||
|
"asText": "Копировать как текст",
|
||||||
|
"asMarkdown": "Копировать как Markdown",
|
||||||
|
"success": "Скопировано в буфер обмена!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Скачать",
|
||||||
|
"text": "Текстовый файл (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON файл (.json)"
|
||||||
|
},
|
||||||
|
"share": "Поделиться"
|
||||||
|
}}
|
||||||
|
@ -71,14 +71,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "URL-адрес SearXNG"
|
"label": "URL-адрес SearXNG"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "API-ключ Brave",
|
||||||
|
"placeholder": "Введите ваш API-ключ Brave"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Настройки системы",
|
"heading": "Настройки системы",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Удалить историю чата",
|
"label": "Сброс системы",
|
||||||
"button": "Удалить",
|
"button": "Сбросить все",
|
||||||
"confirm": "Вы уверены, что хотите удалить историю чата? Это действие нельзя отменить."
|
"confirm": "Вы уверены, что хотите выполнить сброс системы? Это удалит все данные без возможности восстановления."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Экспорт истории чата, базы знаний и подсказок",
|
"label": "Экспорт истории чата, базы знаний и подсказок",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Vänligen välj en modell för att fortsätta",
|
"validationSelectModel": "Vänligen välj en modell för att fortsätta",
|
||||||
"deleteHistoryConfirmation": "Är du säker på att du vill radera denna historik?",
|
"deleteHistoryConfirmation": "Är du säker på att du vill radera denna historik?",
|
||||||
"editHistoryTitle": "Ange en ny titel",
|
"editHistoryTitle": "Ange en ny titel",
|
||||||
"temporaryChat": "Tillfällig chatt"
|
"temporaryChat": "Tillfällig chatt",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Kopiera",
|
||||||
|
"asText": "Kopiera som text",
|
||||||
|
"asMarkdown": "Kopiera som Markdown",
|
||||||
|
"success": "Kopierat till urklipp!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Ladda ner",
|
||||||
|
"text": "Textfil (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON-fil (.json)"
|
||||||
|
},
|
||||||
|
"share": "Dela"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL"
|
"label": "SearXNG URL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API-nyckel",
|
||||||
|
"placeholder": "Ange din Brave API-nyckel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Systeminställningar",
|
"heading": "Systeminställningar",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Radera Chatt Historik",
|
"label": "Systemåterställning",
|
||||||
"button": "Radera",
|
"button": "Återställ Allt",
|
||||||
"confirm": "Är du säker på att du vill radera din chatthistorik? Denna åtgärd kan inte ångras."
|
"confirm": "Är du säker på att du vill utföra en systemåterställning? Detta kommer att radera all data och kan inte ångras."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Exportera chatthistorik, kunskapsbas och instruktioner",
|
"label": "Exportera chatthistorik, kunskapsbas och instruktioner",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "Будь ласка, виберіть модель для продовження",
|
"validationSelectModel": "Будь ласка, виберіть модель для продовження",
|
||||||
"deleteHistoryConfirmation": "Ви впевнені, що хочете видалити цю історію?",
|
"deleteHistoryConfirmation": "Ви впевнені, що хочете видалити цю історію?",
|
||||||
"editHistoryTitle": "Введіть нову назву",
|
"editHistoryTitle": "Введіть нову назву",
|
||||||
"temporaryChat": "Тимчасовий чат"
|
"temporaryChat": "Тимчасовий чат",
|
||||||
}
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "Копіювати",
|
||||||
|
"asText": "Копіювати як текст",
|
||||||
|
"asMarkdown": "Копіювати як Markdown",
|
||||||
|
"success": "Скопійовано в буфер обміну!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "Завантажити",
|
||||||
|
"text": "Текстовий файл (.txt)",
|
||||||
|
"markdown": "Markdown (.md)",
|
||||||
|
"json": "JSON файл (.json)"
|
||||||
|
},
|
||||||
|
"share": "Поділитися"
|
||||||
|
}
|
||||||
|
}
|
@ -70,14 +70,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG URL-адреса"
|
"label": "SearXNG URL-адреса"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Ключ API Brave",
|
||||||
|
"placeholder": "Введіть ваш ключ API Brave"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "Системні налаштування",
|
"heading": "Системні налаштування",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "Видалити історію чату",
|
"label": "Скидання системи",
|
||||||
"button": "Видалити",
|
"button": "Скинути все",
|
||||||
"confirm": "Ви впевнені, що хочете видалити історію чату? Ця дія не може бути відвернута."
|
"confirm": "Ви впевнені, що хочете виконати скидання системи? Це призведе до видалення всіх даних, і цю дію неможливо буде скасувати."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "Експорт історії чату, бази знань та запитів",
|
"label": "Експорт історії чату, бази знань та запитів",
|
||||||
|
@ -9,5 +9,20 @@
|
|||||||
"validationSelectModel": "请选择一个模型以继续",
|
"validationSelectModel": "请选择一个模型以继续",
|
||||||
"deleteHistoryConfirmation": "你确定要删除这个历史记录吗?",
|
"deleteHistoryConfirmation": "你确定要删除这个历史记录吗?",
|
||||||
"editHistoryTitle": "输入一个新的标题",
|
"editHistoryTitle": "输入一个新的标题",
|
||||||
"temporaryChat": "临时聊天"
|
"temporaryChat": "临时聊天",
|
||||||
|
"more": {
|
||||||
|
"copy": {
|
||||||
|
"group": "复制",
|
||||||
|
"asText": "复制为文本",
|
||||||
|
"asMarkdown": "复制为 Markdown",
|
||||||
|
"success": "已复制到剪贴板!"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"group": "下载",
|
||||||
|
"text": "文本文件 (.txt)",
|
||||||
|
"markdown": "Markdown 文件 (.md)",
|
||||||
|
"json": "JSON 文件 (.json)"
|
||||||
|
},
|
||||||
|
"share": "分享"
|
||||||
|
}
|
||||||
}
|
}
|
@ -73,14 +73,18 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"label": "SearXNG 网址"
|
"label": "SearXNG 网址"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"braveApi": {
|
||||||
|
"label": "Brave API 密钥",
|
||||||
|
"placeholder": "输入您的 Brave API 密钥"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"heading": "系统设置",
|
"heading": "系统设置",
|
||||||
"deleteChatHistory": {
|
"deleteChatHistory": {
|
||||||
"label": "删除聊天记录",
|
"label": "系统重置",
|
||||||
"button": "删除",
|
"button": "全部重置",
|
||||||
"confirm": "您确定要删除聊天记录吗?此操作无法撤销。"
|
"confirm": "您确定要执行系统重置吗?这将清除所有数据且无法撤消。"
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"label": "导出聊天记录、知识库和提示",
|
"label": "导出聊天记录、知识库和提示",
|
||||||
|
@ -14,6 +14,8 @@ import fetcher from "@/libs/fetcher"
|
|||||||
type Props = {
|
type Props = {
|
||||||
messages: Message[]
|
messages: Message[]
|
||||||
historyId: string
|
historyId: string
|
||||||
|
open: boolean
|
||||||
|
setOpen: (state: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const reformatMessages = (messages: Message[], username: string) => {
|
const reformatMessages = (messages: Message[], username: string) => {
|
||||||
@ -77,9 +79,13 @@ export const PlaygroundMessage = (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShareBtn: React.FC<Props> = ({ messages, historyId }) => {
|
export const ShareModal: React.FC<Props> = ({
|
||||||
|
messages,
|
||||||
|
historyId,
|
||||||
|
open,
|
||||||
|
setOpen
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation("common")
|
const { t } = useTranslation("common")
|
||||||
const [open, setOpen] = useState(false)
|
|
||||||
const [form] = Form.useForm()
|
const [form] = Form.useForm()
|
||||||
const name = Form.useWatch("name", form)
|
const name = Form.useWatch("name", form)
|
||||||
|
|
||||||
@ -142,75 +148,55 @@ export const ShareBtn: React.FC<Props> = ({ messages, historyId }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Modal
|
||||||
<Tooltip title={t("share.tooltip.share")}>
|
title={t("share.modal.title")}
|
||||||
<button
|
open={open}
|
||||||
onClick={() => setOpen(true)}
|
footer={null}
|
||||||
className="!text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
|
width={600}
|
||||||
<Share className="w-6 h-6" />
|
onCancel={() => setOpen(false)}>
|
||||||
</button>
|
<Form
|
||||||
</Tooltip>
|
form={form}
|
||||||
|
layout="vertical"
|
||||||
|
onFinish={createShareLink}
|
||||||
|
initialValues={{
|
||||||
|
title: t("share.form.defaultValue.title"),
|
||||||
|
name: t("share.form.defaultValue.name")
|
||||||
|
}}>
|
||||||
|
<Form.Item
|
||||||
|
name="title"
|
||||||
|
label={t("share.form.title.label")}
|
||||||
|
rules={[{ required: true, message: t("share.form.title.required") }]}>
|
||||||
|
<Input size="large" placeholder={t("share.form.title.placeholder")} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label={t("share.form.name.label")}
|
||||||
|
rules={[{ required: true, message: t("share.form.name.required") }]}>
|
||||||
|
<Input size="large" placeholder={t("share.form.name.placeholder")} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Modal
|
<Form.Item>
|
||||||
title={t("share.modal.title")}
|
<div className="max-h-[180px] overflow-x-auto border dark:border-gray-700 rounded-md p-2">
|
||||||
open={open}
|
<div className="flex flex-col p-3">
|
||||||
footer={null}
|
{messages.map((message, index) => (
|
||||||
width={600}
|
<PlaygroundMessage key={index} {...message} username={name} />
|
||||||
onCancel={() => setOpen(false)}>
|
))}
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
layout="vertical"
|
|
||||||
onFinish={createShareLink}
|
|
||||||
initialValues={{
|
|
||||||
title: t("share.form.defaultValue.title"),
|
|
||||||
name: t("share.form.defaultValue.name")
|
|
||||||
}}>
|
|
||||||
<Form.Item
|
|
||||||
name="title"
|
|
||||||
label={t("share.form.title.label")}
|
|
||||||
rules={[
|
|
||||||
{ required: true, message: t("share.form.title.required") }
|
|
||||||
]}>
|
|
||||||
<Input
|
|
||||||
size="large"
|
|
||||||
placeholder={t("share.form.title.placeholder")}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
name="name"
|
|
||||||
label={t("share.form.name.label")}
|
|
||||||
rules={[
|
|
||||||
{ required: true, message: t("share.form.name.required") }
|
|
||||||
]}>
|
|
||||||
<Input
|
|
||||||
size="large"
|
|
||||||
placeholder={t("share.form.name.placeholder")}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item>
|
|
||||||
<div className="max-h-[180px] overflow-x-auto border dark:border-gray-700 rounded-md p-2">
|
|
||||||
<div className="flex flex-col p-3">
|
|
||||||
{messages.map((message, index) => (
|
|
||||||
<PlaygroundMessage key={index} {...message} username={name} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="inline-flex items-center rounded-md border border-transparent bg-black px-2 py-2.5 text-md font-medium leading-4 text-white shadow-sm dark:bg-white dark:text-gray-800 disabled:opacity-50 ">
|
className="inline-flex items-center rounded-md border border-transparent bg-black px-2 py-2.5 text-md font-medium leading-4 text-white shadow-sm dark:bg-white dark:text-gray-800 disabled:opacity-50 ">
|
||||||
{isPending
|
{isPending
|
||||||
? t("share.form.btn.saving")
|
? t("share.form.btn.saving")
|
||||||
: t("share.form.btn.save")}
|
: t("share.form.btn.save")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -19,10 +19,10 @@ import { fetchChatModels } from "~/services/ollama"
|
|||||||
import { useMessageOption } from "~/hooks/useMessageOption"
|
import { useMessageOption } from "~/hooks/useMessageOption"
|
||||||
import { Select, Tooltip } from "antd"
|
import { Select, Tooltip } from "antd"
|
||||||
import { getAllPrompts } from "@/db"
|
import { getAllPrompts } from "@/db"
|
||||||
import { ShareBtn } from "~/components/Common/ShareBtn"
|
|
||||||
import { ProviderIcons } from "../Common/ProviderIcon"
|
import { ProviderIcons } from "../Common/ProviderIcon"
|
||||||
import { NewChat } from "./NewChat"
|
import { NewChat } from "./NewChat"
|
||||||
import { PageAssistSelect } from "../Select"
|
import { PageAssistSelect } from "../Select"
|
||||||
|
import { MoreOptions } from "./MoreOptions"
|
||||||
type Props = {
|
type Props = {
|
||||||
setSidebarOpen: (open: boolean) => void
|
setSidebarOpen: (open: boolean) => void
|
||||||
setOpenModelSettings: (open: boolean) => void
|
setOpenModelSettings: (open: boolean) => void
|
||||||
@ -50,7 +50,11 @@ export const Header: React.FC<Props> = ({
|
|||||||
historyId,
|
historyId,
|
||||||
temporaryChat
|
temporaryChat
|
||||||
} = useMessageOption()
|
} = useMessageOption()
|
||||||
const { data: models, isLoading: isModelsLoading, refetch } = useQuery({
|
const {
|
||||||
|
data: models,
|
||||||
|
isLoading: isModelsLoading,
|
||||||
|
refetch
|
||||||
|
} = useQuery({
|
||||||
queryKey: ["fetchModel"],
|
queryKey: ["fetchModel"],
|
||||||
queryFn: () => fetchChatModels({ returnEmpty: true }),
|
queryFn: () => fetchChatModels({ returnEmpty: true }),
|
||||||
refetchIntervalInBackground: false,
|
refetchIntervalInBackground: false,
|
||||||
@ -134,7 +138,6 @@ export const Header: React.FC<Props> = ({
|
|||||||
),
|
),
|
||||||
value: model.model
|
value: model.model
|
||||||
}))}
|
}))}
|
||||||
|
|
||||||
onRefresh={() => {
|
onRefresh={() => {
|
||||||
refetch()
|
refetch()
|
||||||
}}
|
}}
|
||||||
@ -189,6 +192,19 @@ export const Header: React.FC<Props> = ({
|
|||||||
<div className="flex flex-1 justify-end px-4">
|
<div className="flex flex-1 justify-end px-4">
|
||||||
<div className="ml-4 flex items-center md:ml-6">
|
<div className="ml-4 flex items-center md:ml-6">
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex gap-4 items-center">
|
||||||
|
{/* {pathname === "/" &&
|
||||||
|
messages.length > 0 &&
|
||||||
|
!streaming &&
|
||||||
|
shareModeEnabled && (
|
||||||
|
<ShareBtn historyId={historyId} messages={messages} />
|
||||||
|
)} */}
|
||||||
|
{messages.length > 0 && !streaming && (
|
||||||
|
<MoreOptions
|
||||||
|
shareModeEnabled={shareModeEnabled}
|
||||||
|
historyId={historyId}
|
||||||
|
messages={messages}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{!hideCurrentChatModelSettings && (
|
{!hideCurrentChatModelSettings && (
|
||||||
<Tooltip title={t("common:currentChatModelSettings")}>
|
<Tooltip title={t("common:currentChatModelSettings")}>
|
||||||
<button
|
<button
|
||||||
@ -198,12 +214,6 @@ export const Header: React.FC<Props> = ({
|
|||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{pathname === "/" &&
|
|
||||||
messages.length > 0 &&
|
|
||||||
!streaming &&
|
|
||||||
shareModeEnabled && (
|
|
||||||
<ShareBtn historyId={historyId} messages={messages} />
|
|
||||||
)}
|
|
||||||
<Tooltip title={t("githubRepository")}>
|
<Tooltip title={t("githubRepository")}>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/n4ze3m/page-assist"
|
href="https://github.com/n4ze3m/page-assist"
|
||||||
|
163
src/components/Layouts/MoreOptions.tsx
Normal file
163
src/components/Layouts/MoreOptions.tsx
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
import {
|
||||||
|
MoreHorizontal,
|
||||||
|
FileText,
|
||||||
|
Share2,
|
||||||
|
FileJson,
|
||||||
|
FileCode
|
||||||
|
} from "lucide-react"
|
||||||
|
import { Dropdown, MenuProps, message } from "antd"
|
||||||
|
import { Message } from "@/types/message"
|
||||||
|
import { useState } from "react"
|
||||||
|
import { ShareModal } from "../Common/ShareModal"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
|
interface MoreOptionsProps {
|
||||||
|
messages: Message[]
|
||||||
|
historyId: string
|
||||||
|
shareModeEnabled: boolean
|
||||||
|
}
|
||||||
|
const formatAsText = (messages: Message[]) => {
|
||||||
|
return messages
|
||||||
|
.map((msg) => {
|
||||||
|
const text = `${msg.isBot ? msg.name : "You"}: ${msg.message}`
|
||||||
|
return text
|
||||||
|
})
|
||||||
|
.join("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatAsMarkdown = (messages: Message[]) => {
|
||||||
|
return messages
|
||||||
|
.map((msg) => {
|
||||||
|
let content = `**${msg.isBot ? msg.name : "You"}**:\n${msg.message}`
|
||||||
|
|
||||||
|
if (msg.images && msg.images.length > 0) {
|
||||||
|
const imageMarkdown = msg.images
|
||||||
|
.filter((img) => img.length > 0)
|
||||||
|
.map((img) => `\n\n`)
|
||||||
|
.join("\n")
|
||||||
|
content += imageMarkdown
|
||||||
|
}
|
||||||
|
|
||||||
|
return content
|
||||||
|
})
|
||||||
|
.join("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadFile = (content: string, filename: string) => {
|
||||||
|
const blob = new Blob([content], { type: "text/plain;charset=utf-8" })
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement("a")
|
||||||
|
link.href = url
|
||||||
|
link.download = filename
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MoreOptions = ({
|
||||||
|
shareModeEnabled = false,
|
||||||
|
historyId,
|
||||||
|
messages
|
||||||
|
}: MoreOptionsProps) => {
|
||||||
|
const { t } = useTranslation("option")
|
||||||
|
const [onShareOpen, setOnShareOpen] = useState(false)
|
||||||
|
const baseItems: MenuProps["items"] = [
|
||||||
|
{
|
||||||
|
type: "group",
|
||||||
|
label: t("more.copy.group"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: "copy-text",
|
||||||
|
label: t("more.copy.asText"),
|
||||||
|
icon: <FileText className="w-4 h-4" />,
|
||||||
|
onClick: () => {
|
||||||
|
navigator.clipboard.writeText(formatAsText(messages))
|
||||||
|
message.success(t("more.copy.success"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "copy-markdown",
|
||||||
|
label: t("more.copy.asMarkdown"),
|
||||||
|
icon: <FileCode className="w-4 h-4" />,
|
||||||
|
onClick: () => {
|
||||||
|
navigator.clipboard.writeText(formatAsMarkdown(messages))
|
||||||
|
message.success(t("more.copy.success"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "divider"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "group",
|
||||||
|
label: t("more.download.group"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: "download-txt",
|
||||||
|
label: t("more.download.text"),
|
||||||
|
icon: <FileText className="w-4 h-4" />,
|
||||||
|
onClick: () => {
|
||||||
|
downloadFile(formatAsText(messages), "chat.txt")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "download-md",
|
||||||
|
label: t("more.download.markdown"),
|
||||||
|
icon: <FileCode className="w-4 h-4" />,
|
||||||
|
onClick: () => {
|
||||||
|
downloadFile(formatAsMarkdown(messages), "chat.md")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "download-json",
|
||||||
|
label: t("more.download.json"),
|
||||||
|
icon: <FileJson className="w-4 h-4" />,
|
||||||
|
onClick: () => {
|
||||||
|
const jsonContent = JSON.stringify(messages, null, 2)
|
||||||
|
downloadFile(jsonContent, "chat.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const shareItem = {
|
||||||
|
type: "divider"
|
||||||
|
} as const
|
||||||
|
|
||||||
|
const shareOption = {
|
||||||
|
key: "share",
|
||||||
|
label: t("more.share"),
|
||||||
|
icon: <Share2 className="w-4 h-4" />,
|
||||||
|
onClick: () => {
|
||||||
|
setOnShareOpen(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = shareModeEnabled
|
||||||
|
? [...baseItems, shareItem, shareOption]
|
||||||
|
: baseItems
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
items
|
||||||
|
}}
|
||||||
|
trigger={["click"]}
|
||||||
|
placement="bottomRight">
|
||||||
|
<button className="!text-gray-500 dark:text-gray-300 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
|
||||||
|
<MoreHorizontal className="w-6 h-6" />
|
||||||
|
</button>
|
||||||
|
</Dropdown>
|
||||||
|
<ShareModal
|
||||||
|
open={onShareOpen}
|
||||||
|
historyId={historyId}
|
||||||
|
messages={messages}
|
||||||
|
setOpen={setOnShareOpen}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -27,7 +27,7 @@ export const PlaygroundChat = () => {
|
|||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className="custom-scrollbar grow flex flex-col md:translate-x-0 transition-transform duration-300 ease-in-out overflow-y-auto h-[calc(100vh-160px)]">
|
className="custom-scrollbar grow flex flex-col md:translate-x-0 transition-transform duration-300 ease-in-out overflow-y-auto h-[calc(100vh-160px)]">
|
||||||
{messages.length === 0 && (
|
{messages.length === 0 && (
|
||||||
<div className="mt-32">
|
<div className="mt-32">
|
||||||
<PlaygroundEmpty />
|
<PlaygroundEmpty />
|
||||||
|
@ -220,30 +220,7 @@ export const GeneralSettings = () => {
|
|||||||
</h2>
|
</h2>
|
||||||
<div className="border border-b border-gray-200 dark:border-gray-600 mt-3"></div>
|
<div className="border border-b border-gray-200 dark:border-gray-600 mt-3"></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row mb-3 justify-between">
|
|
||||||
<span className="text-gray-700 dark:text-neutral-50 ">
|
|
||||||
{t("generalSettings.system.deleteChatHistory.label")}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={async () => {
|
|
||||||
const confirm = window.confirm(
|
|
||||||
t("generalSettings.system.deleteChatHistory.confirm")
|
|
||||||
)
|
|
||||||
|
|
||||||
if (confirm) {
|
|
||||||
const db = new PageAssitDatabase()
|
|
||||||
await db.deleteAllChatHistory()
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: ["fetchChatHistory"]
|
|
||||||
})
|
|
||||||
clearChat()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="bg-red-500 dark:bg-red-600 text-white dark:text-gray-200 px-4 py-2 rounded-md">
|
|
||||||
{t("generalSettings.system.deleteChatHistory.button")}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row mb-3 justify-between">
|
<div className="flex flex-row mb-3 justify-between">
|
||||||
<span className="text-gray-700 dark:text-neutral-50 ">
|
<span className="text-gray-700 dark:text-neutral-50 ">
|
||||||
{t("generalSettings.system.export.label")}
|
{t("generalSettings.system.export.label")}
|
||||||
@ -275,6 +252,38 @@ export const GeneralSettings = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-row mb-3 justify-between">
|
||||||
|
<span className="text-gray-700 dark:text-neutral-50 ">
|
||||||
|
{t("generalSettings.system.deleteChatHistory.label")}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
const confirm = window.confirm(
|
||||||
|
t("generalSettings.system.deleteChatHistory.confirm")
|
||||||
|
)
|
||||||
|
|
||||||
|
if (confirm) {
|
||||||
|
const db = new PageAssitDatabase()
|
||||||
|
await db.deleteAllChatHistory()
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ["fetchChatHistory"]
|
||||||
|
})
|
||||||
|
clearChat()
|
||||||
|
try {
|
||||||
|
await browser.storage.sync.clear()
|
||||||
|
await browser.storage.local.clear()
|
||||||
|
await browser.storage.session.clear()
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error clearing storage:", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="bg-red-500 dark:bg-red-600 text-white dark:text-gray-200 px-4 py-2 rounded-md">
|
||||||
|
{t("generalSettings.system.deleteChatHistory.button")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,7 @@ import { SaveButton } from "@/components/Common/SaveButton"
|
|||||||
import { getSearchSettings, setSearchSettings } from "@/services/search"
|
import { getSearchSettings, setSearchSettings } from "@/services/search"
|
||||||
import { SUPPORTED_SERACH_PROVIDERS } from "@/utils/search-provider"
|
import { SUPPORTED_SERACH_PROVIDERS } from "@/utils/search-provider"
|
||||||
import { useForm } from "@mantine/form"
|
import { useForm } from "@mantine/form"
|
||||||
import { useQuery, useQueryClient } from "@tanstack/react-query"
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { Select, Skeleton, Switch, InputNumber, Input } from "antd"
|
import { Select, Skeleton, Switch, InputNumber, Input } from "antd"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
@ -16,7 +16,8 @@ export const SearchModeSettings = () => {
|
|||||||
totalSearchResults: 0,
|
totalSearchResults: 0,
|
||||||
visitSpecificWebsite: false,
|
visitSpecificWebsite: false,
|
||||||
searxngURL: "",
|
searxngURL: "",
|
||||||
searxngJSONMode: false
|
searxngJSONMode: false,
|
||||||
|
braveApiKey: "",
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -81,6 +82,25 @@ export const SearchModeSettings = () => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{form.values.searchProvider === "brave-api" && (
|
||||||
|
<>
|
||||||
|
<div className="flex sm:flex-row flex-col space-y-4 sm:space-y-0 sm:justify-between">
|
||||||
|
<span className="text-gray-700 dark:text-neutral-50">
|
||||||
|
{t("generalSettings.webSearch.braveApi.label")}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<Input.Password
|
||||||
|
placeholder={t(
|
||||||
|
"generalSettings.webSearch.braveApi.placeholder"
|
||||||
|
)}
|
||||||
|
required
|
||||||
|
className="w-full mt-4 sm:mt-0 sm:w-[200px]"
|
||||||
|
{...form.getInputProps("braveApiKey")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className="flex sm:flex-row flex-col space-y-4 sm:space-y-0 sm:justify-between">
|
<div className="flex sm:flex-row flex-col space-y-4 sm:space-y-0 sm:justify-between">
|
||||||
<span className="text-gray-700 dark:text-neutral-50 ">
|
<span className="text-gray-700 dark:text-neutral-50 ">
|
||||||
{t("generalSettings.webSearch.searchMode.label")}
|
{t("generalSettings.webSearch.searchMode.label")}
|
||||||
|
@ -145,6 +145,12 @@ export const getKnowledgeById = async (id: string) => {
|
|||||||
export const updateKnowledgeStatus = async (id: string, status: string) => {
|
export const updateKnowledgeStatus = async (id: string, status: string) => {
|
||||||
const db = new PageAssistKnowledge()
|
const db = new PageAssistKnowledge()
|
||||||
const knowledge = await db.getById(id)
|
const knowledge = await db.getById(id)
|
||||||
|
if(status === "finished") {
|
||||||
|
knowledge.source = knowledge.source.map(e => ({
|
||||||
|
...e,
|
||||||
|
content: undefined,
|
||||||
|
}))
|
||||||
|
}
|
||||||
await db.update({
|
await db.update({
|
||||||
...knowledge,
|
...knowledge,
|
||||||
status
|
status
|
||||||
|
@ -108,7 +108,7 @@ export const saveMessageOnError = async ({
|
|||||||
setHistoryId(newHistoryId.id)
|
setHistoryId(newHistoryId.id)
|
||||||
await setLastUsedChatModel(newHistoryId.id, selectedModel)
|
await setLastUsedChatModel(newHistoryId.id, selectedModel)
|
||||||
if (prompt_id || prompt_content) {
|
if (prompt_id || prompt_content) {
|
||||||
await setLastUsedChatSystemPrompt(historyId, { prompt_content, prompt_id })
|
await setLastUsedChatSystemPrompt(newHistoryId.id, { prompt_content, prompt_id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ export const saveMessageOnSuccess = async ({
|
|||||||
setHistoryId(newHistoryId.id)
|
setHistoryId(newHistoryId.id)
|
||||||
await setLastUsedChatModel(newHistoryId.id, selectedModel!)
|
await setLastUsedChatModel(newHistoryId.id, selectedModel!)
|
||||||
if (prompt_id || prompt_content) {
|
if (prompt_id || prompt_content) {
|
||||||
await setLastUsedChatSystemPrompt(historyId, { prompt_content, prompt_id })
|
await setLastUsedChatSystemPrompt(newHistoryId.id, { prompt_content, prompt_id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { Storage } from "@plasmohq/storage"
|
import { Storage } from "@plasmohq/storage"
|
||||||
const storage = new Storage()
|
const storage = new Storage({
|
||||||
|
area: "local"
|
||||||
|
})
|
||||||
|
|
||||||
type ModelSettings = {
|
type ModelSettings = {
|
||||||
f16KV?: boolean
|
f16KV?: boolean
|
||||||
@ -63,7 +65,7 @@ const keys = [
|
|||||||
"vocabOnly"
|
"vocabOnly"
|
||||||
]
|
]
|
||||||
|
|
||||||
const getAllModelSettings = async () => {
|
export const getAllModelSettings = async () => {
|
||||||
try {
|
try {
|
||||||
const settings: ModelSettings = {}
|
const settings: ModelSettings = {}
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
@ -80,7 +82,7 @@ const getAllModelSettings = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setModelSetting = async (
|
export const setModelSetting = async (
|
||||||
key: string,
|
key: string,
|
||||||
value: string | number | boolean
|
value: string | number | boolean
|
||||||
) => {
|
) => {
|
||||||
@ -144,4 +146,3 @@ export const setLastUsedChatSystemPrompt = async (
|
|||||||
await storage.set(`lastUsedChatSystemPrompt-${historyId}`, prompt)
|
await storage.set(`lastUsedChatSystemPrompt-${historyId}`, prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getAllModelSettings, setModelSetting }
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { Storage } from "@plasmohq/storage"
|
import { Storage } from "@plasmohq/storage"
|
||||||
|
|
||||||
const storage = new Storage()
|
const storage = new Storage()
|
||||||
|
const storage2 = new Storage({
|
||||||
|
area: "local"
|
||||||
|
})
|
||||||
|
|
||||||
const TOTAL_SEARCH_RESULTS = 2
|
const TOTAL_SEARCH_RESULTS = 2
|
||||||
const DEFAULT_PROVIDER = "google"
|
const DEFAULT_PROVIDER = "google"
|
||||||
@ -80,10 +83,20 @@ export const setSearxngURL = async (searxngURL: string) => {
|
|||||||
await storage.set("searxngURL", searxngURL)
|
await storage.set("searxngURL", searxngURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getBraveApiKey = async () => {
|
||||||
|
const braveApiKey = await storage2.get("braveApiKey")
|
||||||
|
return braveApiKey || ""
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setBraveApiKey = async (braveApiKey: string) => {
|
||||||
|
await storage2.set("braveApiKey", braveApiKey)
|
||||||
|
}
|
||||||
|
|
||||||
export const getSearchSettings = async () => {
|
export const getSearchSettings = async () => {
|
||||||
const [isSimpleInternetSearch, searchProvider, totalSearchResult, visitSpecificWebsite,
|
const [isSimpleInternetSearch, searchProvider, totalSearchResult, visitSpecificWebsite,
|
||||||
searxngURL,
|
searxngURL,
|
||||||
searxngJSONMode
|
searxngJSONMode,
|
||||||
|
braveApiKey
|
||||||
] =
|
] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
getIsSimpleInternetSearch(),
|
getIsSimpleInternetSearch(),
|
||||||
@ -91,7 +104,8 @@ export const getSearchSettings = async () => {
|
|||||||
totalSearchResults(),
|
totalSearchResults(),
|
||||||
getIsVisitSpecificWebsite(),
|
getIsVisitSpecificWebsite(),
|
||||||
getSearxngURL(),
|
getSearxngURL(),
|
||||||
isSearxngJSONMode()
|
isSearxngJSONMode(),
|
||||||
|
getBraveApiKey()
|
||||||
])
|
])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -100,7 +114,8 @@ export const getSearchSettings = async () => {
|
|||||||
totalSearchResults: totalSearchResult,
|
totalSearchResults: totalSearchResult,
|
||||||
visitSpecificWebsite,
|
visitSpecificWebsite,
|
||||||
searxngURL,
|
searxngURL,
|
||||||
searxngJSONMode
|
searxngJSONMode,
|
||||||
|
braveApiKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,14 +125,16 @@ export const setSearchSettings = async ({
|
|||||||
totalSearchResults,
|
totalSearchResults,
|
||||||
visitSpecificWebsite,
|
visitSpecificWebsite,
|
||||||
searxngJSONMode,
|
searxngJSONMode,
|
||||||
searxngURL
|
searxngURL,
|
||||||
|
braveApiKey
|
||||||
}: {
|
}: {
|
||||||
isSimpleInternetSearch: boolean
|
isSimpleInternetSearch: boolean
|
||||||
searchProvider: string
|
searchProvider: string
|
||||||
totalSearchResults: number
|
totalSearchResults: number
|
||||||
visitSpecificWebsite: boolean
|
visitSpecificWebsite: boolean
|
||||||
searxngURL: string
|
searxngURL: string
|
||||||
searxngJSONMode: boolean
|
searxngJSONMode: boolean,
|
||||||
|
braveApiKey: string
|
||||||
}) => {
|
}) => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
setIsSimpleInternetSearch(isSimpleInternetSearch),
|
setIsSimpleInternetSearch(isSimpleInternetSearch),
|
||||||
@ -125,6 +142,7 @@ export const setSearchSettings = async ({
|
|||||||
setTotalSearchResults(totalSearchResults),
|
setTotalSearchResults(totalSearchResults),
|
||||||
setIsVisitSpecificWebsite(visitSpecificWebsite),
|
setIsVisitSpecificWebsite(visitSpecificWebsite),
|
||||||
setSearxngJSONMode(searxngJSONMode),
|
setSearxngJSONMode(searxngJSONMode),
|
||||||
setSearxngURL(searxngURL)
|
setSearxngURL(searxngURL),
|
||||||
|
setBraveApiKey(braveApiKey)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -18,5 +18,9 @@ export const SUPPORTED_SERACH_PROVIDERS = [
|
|||||||
{
|
{
|
||||||
label: "Searxng",
|
label: "Searxng",
|
||||||
value: "searxng"
|
value: "searxng"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Brave Search API",
|
||||||
|
value: "brave-api"
|
||||||
}
|
}
|
||||||
]
|
]
|
128
src/web/search-engines/brave-api.ts
Normal file
128
src/web/search-engines/brave-api.ts
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import { cleanUrl } from "~/libs/clean-url"
|
||||||
|
import { getIsSimpleInternetSearch, totalSearchResults, getBraveApiKey } from "@/services/search"
|
||||||
|
import { pageAssistEmbeddingModel } from "@/models/embedding"
|
||||||
|
import type { Document } from "@langchain/core/documents"
|
||||||
|
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"
|
||||||
|
import { MemoryVectorStore } from "langchain/vectorstores/memory"
|
||||||
|
import { PageAssistHtmlLoader } from "~/loader/html"
|
||||||
|
import {
|
||||||
|
defaultEmbeddingChunkOverlap,
|
||||||
|
defaultEmbeddingChunkSize,
|
||||||
|
defaultEmbeddingModelForRag,
|
||||||
|
getOllamaURL
|
||||||
|
} from "~/services/ollama"
|
||||||
|
|
||||||
|
interface BraveAPIResult {
|
||||||
|
title: string
|
||||||
|
url: string
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BraveAPIResponse {
|
||||||
|
web: {
|
||||||
|
results: BraveAPIResult[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const braveAPISearch = async (query: string) => {
|
||||||
|
const braveApiKey = await getBraveApiKey()
|
||||||
|
if (!braveApiKey || braveApiKey.trim() === "") {
|
||||||
|
throw new Error("Brave API key not configured")
|
||||||
|
}
|
||||||
|
const results = await apiBraveSearch(braveApiKey, query)
|
||||||
|
const TOTAL_SEARCH_RESULTS = await totalSearchResults()
|
||||||
|
|
||||||
|
const searchResults = results.slice(0, TOTAL_SEARCH_RESULTS)
|
||||||
|
|
||||||
|
const isSimpleMode = await getIsSimpleInternetSearch()
|
||||||
|
|
||||||
|
if (isSimpleMode) {
|
||||||
|
await getOllamaURL()
|
||||||
|
return searchResults.map((result) => {
|
||||||
|
return {
|
||||||
|
url: result.link,
|
||||||
|
content: result.content
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const docs: Document<Record<string, any>>[] = []
|
||||||
|
try {
|
||||||
|
for (const result of searchResults) {
|
||||||
|
const loader = new PageAssistHtmlLoader({
|
||||||
|
html: "",
|
||||||
|
url: result.link
|
||||||
|
})
|
||||||
|
|
||||||
|
const documents = await loader.loadByURL()
|
||||||
|
documents.forEach((doc) => {
|
||||||
|
docs.push(doc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ollamaUrl = await getOllamaURL()
|
||||||
|
const embeddingModel = await defaultEmbeddingModelForRag()
|
||||||
|
const ollamaEmbedding = await pageAssistEmbeddingModel({
|
||||||
|
model: embeddingModel || "",
|
||||||
|
baseUrl: cleanUrl(ollamaUrl)
|
||||||
|
})
|
||||||
|
|
||||||
|
const chunkSize = await defaultEmbeddingChunkSize()
|
||||||
|
const chunkOverlap = await defaultEmbeddingChunkOverlap()
|
||||||
|
const textSplitter = new RecursiveCharacterTextSplitter({
|
||||||
|
chunkSize,
|
||||||
|
chunkOverlap
|
||||||
|
})
|
||||||
|
|
||||||
|
const chunks = await textSplitter.splitDocuments(docs)
|
||||||
|
const store = new MemoryVectorStore(ollamaEmbedding)
|
||||||
|
await store.addDocuments(chunks)
|
||||||
|
|
||||||
|
const resultsWithEmbeddings = await store.similaritySearch(query, 3)
|
||||||
|
|
||||||
|
const searchResult = resultsWithEmbeddings.map((result) => {
|
||||||
|
return {
|
||||||
|
url: result.metadata.url,
|
||||||
|
content: result.pageContent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return searchResult
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiBraveSearch = async (braveApiKey: string, query: string) => {
|
||||||
|
const TOTAL_SEARCH_RESULTS = await totalSearchResults()
|
||||||
|
|
||||||
|
const searchURL = `https://api.search.brave.com/res/v1/web/search?q=${query}&count=${TOTAL_SEARCH_RESULTS}`
|
||||||
|
|
||||||
|
const abortController = new AbortController()
|
||||||
|
setTimeout(() => abortController.abort(), 20000)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(searchURL, {
|
||||||
|
signal: abortController.signal,
|
||||||
|
headers: {
|
||||||
|
"X-Subscription-Token": braveApiKey,
|
||||||
|
Accept: "application/json",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json() as BraveAPIResponse
|
||||||
|
|
||||||
|
return data?.web?.results.map(result => ({
|
||||||
|
title: result.title,
|
||||||
|
link: result.url,
|
||||||
|
content: result.description
|
||||||
|
}))
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Brave API search failed:', error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import { webSogouSearch } from "./search-engines/sogou"
|
|||||||
import { webBraveSearch } from "./search-engines/brave"
|
import { webBraveSearch } from "./search-engines/brave"
|
||||||
import { getWebsiteFromQuery, processSingleWebsite } from "./website"
|
import { getWebsiteFromQuery, processSingleWebsite } from "./website"
|
||||||
import { searxngSearch } from "./search-engines/searxng"
|
import { searxngSearch } from "./search-engines/searxng"
|
||||||
|
import { braveAPISearch } from "./search-engines/brave-api"
|
||||||
|
|
||||||
const getHostName = (url: string) => {
|
const getHostName = (url: string) => {
|
||||||
try {
|
try {
|
||||||
@ -26,6 +27,8 @@ const searchWeb = (provider: string, query: string) => {
|
|||||||
return webBraveSearch(query)
|
return webBraveSearch(query)
|
||||||
case "searxng":
|
case "searxng":
|
||||||
return searxngSearch(query)
|
return searxngSearch(query)
|
||||||
|
case "brave-api":
|
||||||
|
return braveAPISearch(query)
|
||||||
default:
|
default:
|
||||||
return webGoogleSearch(query)
|
return webGoogleSearch(query)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export default defineConfig({
|
|||||||
outDir: "build",
|
outDir: "build",
|
||||||
|
|
||||||
manifest: {
|
manifest: {
|
||||||
version: "1.3.7",
|
version: "1.3.8",
|
||||||
name:
|
name:
|
||||||
process.env.TARGET === "firefox"
|
process.env.TARGET === "firefox"
|
||||||
? "Page Assist - A Web UI for Local AI Models"
|
? "Page Assist - A Web UI for Local AI Models"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user