commit
0a15e83b6f
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Søger på internettet",
|
"webSearch": "Søger på internettet",
|
||||||
"regenerate": "Regenerer",
|
"regenerate": "Regenerer",
|
||||||
"edit": "Ændre",
|
"edit": "Ændre",
|
||||||
|
"delete": "Slet",
|
||||||
"saveAndSubmit": "Gem & Indsend",
|
"saveAndSubmit": "Gem & Indsend",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Skriv en besked..."
|
"placeholder": "Skriv en besked..."
|
||||||
@ -101,5 +102,15 @@
|
|||||||
"translate": "Oversæt",
|
"translate": "Oversæt",
|
||||||
"custom": "Brugerdefineret"
|
"custom": "Brugerdefineret"
|
||||||
},
|
},
|
||||||
"citations": "Citater"
|
"citations": "Citater",
|
||||||
|
"downloadCode": "Download Kode",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Fastgjort",
|
||||||
|
"today": "I dag",
|
||||||
|
"yesterday": "I går",
|
||||||
|
"last7Days": "Sidste 7 dage",
|
||||||
|
"older": "Ældre"
|
||||||
|
},
|
||||||
|
"pin": "Fastgør",
|
||||||
|
"unpin": "Frigør"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Navn"
|
"name": "Navn"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Slet"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Er du sikker på du vil slette denne viden?"
|
"delete": "Er du sikker på du vil slette denne viden?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Web durchsuchen",
|
"webSearch": "Web durchsuchen",
|
||||||
"regenerate": "Neu generieren",
|
"regenerate": "Neu generieren",
|
||||||
"edit": "Bearbeiten",
|
"edit": "Bearbeiten",
|
||||||
|
"delete": "Löschen",
|
||||||
"saveAndSubmit": "Speichern & Absenden",
|
"saveAndSubmit": "Speichern & Absenden",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Nachricht eingeben..."
|
"placeholder": "Nachricht eingeben..."
|
||||||
@ -101,5 +102,15 @@
|
|||||||
"translate": "Übersetzen",
|
"translate": "Übersetzen",
|
||||||
"custom": "Benutzerdefiniert"
|
"custom": "Benutzerdefiniert"
|
||||||
},
|
},
|
||||||
"citations": "Zitate"
|
"citations": "Zitate",
|
||||||
|
"downloadCode": "Code herunterladen",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Angepinnt",
|
||||||
|
"today": "Heute",
|
||||||
|
"yesterday": "Gestern",
|
||||||
|
"last7Days": "Letzte 7 Tage",
|
||||||
|
"older": "Älter"
|
||||||
|
},
|
||||||
|
"pin": "Anheften",
|
||||||
|
"unpin": "Losheften"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Name"
|
"name": "Name"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Löschen"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Sind Sie sicher, dass Sie dieses Wissen löschen möchten?"
|
"delete": "Sind Sie sicher, dass Sie dieses Wissen löschen möchten?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Searching the web",
|
"webSearch": "Searching the web",
|
||||||
"regenerate": "Regenerate",
|
"regenerate": "Regenerate",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
|
"delete": "Delete",
|
||||||
"saveAndSubmit": "Save & Submit",
|
"saveAndSubmit": "Save & Submit",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Type a message..."
|
"placeholder": "Type a message..."
|
||||||
@ -105,5 +106,15 @@
|
|||||||
"segmented": {
|
"segmented": {
|
||||||
"ollama": "Ollama Models",
|
"ollama": "Ollama Models",
|
||||||
"custom": "Custom Models"
|
"custom": "Custom Models"
|
||||||
}
|
},
|
||||||
|
"downloadCode": "Download Code",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Pinned",
|
||||||
|
"today": "Today",
|
||||||
|
"yesterday": "Yesterday",
|
||||||
|
"last7Days": "Last 7 Days",
|
||||||
|
"older": "Older"
|
||||||
|
},
|
||||||
|
"pin": "Pin",
|
||||||
|
"unpin": "Unpin"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Name"
|
"name": "Name"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Delete"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Are you sure you want to delete this knowledge?"
|
"delete": "Are you sure you want to delete this knowledge?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Buscando en la web",
|
"webSearch": "Buscando en la web",
|
||||||
"regenerate": "Regenerar",
|
"regenerate": "Regenerar",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
|
"delete": "Borrar",
|
||||||
"saveAndSubmit": "Guardar y Enviar",
|
"saveAndSubmit": "Guardar y Enviar",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Ingresar un mensaje..."
|
"placeholder": "Ingresar un mensaje..."
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "Reformular",
|
"rephrase": "Reformular",
|
||||||
"translate": "Traducir"
|
"translate": "Traducir"
|
||||||
},
|
},
|
||||||
"citations": "Citas"
|
"citations": "Citas",
|
||||||
|
"downloadCode": "Descargar Código",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Fijado",
|
||||||
|
"today": "Hoy",
|
||||||
|
"yesterday": "Ayer",
|
||||||
|
"last7Days": "Últimos 7 días",
|
||||||
|
"older": "Más antiguo"
|
||||||
|
},
|
||||||
|
"pin": "Fijar",
|
||||||
|
"unpin": "Desfijar"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Nombre"
|
"name": "Nombre"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Borrar"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "¿Esta seguro que desea borrar este conocimiento?"
|
"delete": "¿Esta seguro que desea borrar este conocimiento?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "جستجوی وب",
|
"webSearch": "جستجوی وب",
|
||||||
"regenerate": "ایجاد مجدد",
|
"regenerate": "ایجاد مجدد",
|
||||||
"edit": "ویرایش",
|
"edit": "ویرایش",
|
||||||
|
"delete": "حذف",
|
||||||
"saveAndSubmit": "ذخیره و ارسال",
|
"saveAndSubmit": "ذخیره و ارسال",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "یک پیام وارد کنید..."
|
"placeholder": "یک پیام وارد کنید..."
|
||||||
@ -94,5 +95,15 @@
|
|||||||
},
|
},
|
||||||
"advanced": "تنظیمات بیشتر مدل"
|
"advanced": "تنظیمات بیشتر مدل"
|
||||||
},
|
},
|
||||||
"citations": "منابع"
|
"citations": "منابع",
|
||||||
|
"downloadCode": "دانلود کد",
|
||||||
|
"date": {
|
||||||
|
"pinned": "پین شده",
|
||||||
|
"today": "امروز",
|
||||||
|
"yesterday": "دیروز",
|
||||||
|
"last7Days": "۷ روز گذشته",
|
||||||
|
"older": "قدیمیتر"
|
||||||
|
},
|
||||||
|
"pin": "پین کردن",
|
||||||
|
"unpin": "حذف پین"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "نام"
|
"name": "نام"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "حذف"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "آیا مطمئن هستید که می خواهید این دانش را حذف کنید؟"
|
"delete": "آیا مطمئن هستید که می خواهید این دانش را حذف کنید؟"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Recherche sur le Web",
|
"webSearch": "Recherche sur le Web",
|
||||||
"regenerate": "Régénérer",
|
"regenerate": "Régénérer",
|
||||||
"edit": "Modifier",
|
"edit": "Modifier",
|
||||||
|
"delete": "Supprimer",
|
||||||
"saveAndSubmit": "Enregistrer et soumettre",
|
"saveAndSubmit": "Enregistrer et soumettre",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Tapez un message..."
|
"placeholder": "Tapez un message..."
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "Reformuler",
|
"rephrase": "Reformuler",
|
||||||
"translate": "Traduire"
|
"translate": "Traduire"
|
||||||
},
|
},
|
||||||
"citations": "Citations"
|
"citations": "Citations",
|
||||||
|
"downloadCode": "Télécharger le code",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Épinglé",
|
||||||
|
"today": "Aujourd'hui",
|
||||||
|
"yesterday": "Hier",
|
||||||
|
"last7Days": "7 derniers jours",
|
||||||
|
"older": "Plus ancien"
|
||||||
|
},
|
||||||
|
"pin": "Épingler",
|
||||||
|
"unpin": "Désépingler"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Nom"
|
"name": "Nom"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Supprimer"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Êtes-vous sûr de vouloir supprimer ces connaissances ?"
|
"delete": "Êtes-vous sûr de vouloir supprimer ces connaissances ?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Ricerca nel Web",
|
"webSearch": "Ricerca nel Web",
|
||||||
"regenerate": "Rigenera",
|
"regenerate": "Rigenera",
|
||||||
"edit": "Modifica",
|
"edit": "Modifica",
|
||||||
|
"delete": "Elimina",
|
||||||
"saveAndSubmit": "Salva e Invia",
|
"saveAndSubmit": "Salva e Invia",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Scrivi un messaggio..."
|
"placeholder": "Scrivi un messaggio..."
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "Riformulare",
|
"rephrase": "Riformulare",
|
||||||
"translate": "Tradurre"
|
"translate": "Tradurre"
|
||||||
},
|
},
|
||||||
"citations": "Citazioni"
|
"citations": "Citazioni",
|
||||||
|
"downloadCode": "Scarica Codice",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Fissato",
|
||||||
|
"today": "Oggi",
|
||||||
|
"yesterday": "Ieri",
|
||||||
|
"last7Days": "Ultimi 7 Giorni",
|
||||||
|
"older": "Più Vecchi"
|
||||||
|
},
|
||||||
|
"pin": "Fissa",
|
||||||
|
"unpin": "Rimuovi"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Nome"
|
"name": "Nome"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Elimina"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Sei sicuro di voler eliminare questa Knowledge Base?"
|
"delete": "Sei sicuro di voler eliminare questa Knowledge Base?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "ウェブを検索中",
|
"webSearch": "ウェブを検索中",
|
||||||
"regenerate": "再生成",
|
"regenerate": "再生成",
|
||||||
"edit": "編集",
|
"edit": "編集",
|
||||||
|
"delete": "削除",
|
||||||
"saveAndSubmit": "保存して送信",
|
"saveAndSubmit": "保存して送信",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "メッセージを入力..."
|
"placeholder": "メッセージを入力..."
|
||||||
@ -87,9 +88,9 @@
|
|||||||
"placeholder": "GPU(s)に送信するレイヤー数を入力してください"
|
"placeholder": "GPU(s)に送信するレイヤー数を入力してください"
|
||||||
},
|
},
|
||||||
"systemPrompt": {
|
"systemPrompt": {
|
||||||
"label": "一時的なシステムプロンプト",
|
"label": "一時的なシステムプロンプト",
|
||||||
"placeholder": "システムプロンプトを入力",
|
"placeholder": "システムプロンプトを入力",
|
||||||
"help": "これは現在のチャットでシステムプロンプトを素早く設定する方法で、選択されたシステムプロンプトが存在する場合はそれを上書きします。"
|
"help": "これは現在のチャットでシステムプロンプトを素早く設定する方法で、選択されたシステムプロンプトが存在する場合はそれを上書きします。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"advanced": "その他のモデル設定"
|
"advanced": "その他のモデル設定"
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "言い換え",
|
"rephrase": "言い換え",
|
||||||
"translate": "翻訳"
|
"translate": "翻訳"
|
||||||
},
|
},
|
||||||
"citations": "引用"
|
"citations": "引用",
|
||||||
|
"downloadCode": "コードをダウンロード",
|
||||||
|
"date": {
|
||||||
|
"pinned": "固定",
|
||||||
|
"today": "今日",
|
||||||
|
"yesterday": "昨日",
|
||||||
|
"last7Days": "過去7日間",
|
||||||
|
"older": "それ以前"
|
||||||
|
},
|
||||||
|
"pin": "固定",
|
||||||
|
"unpin": "固定解除"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "名前"
|
"name": "名前"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "削除"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "この知識を削除してもよろしいですか?"
|
"delete": "この知識を削除してもよろしいですか?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "വെബ് തിരയുന്നു",
|
"webSearch": "വെബ് തിരയുന്നു",
|
||||||
"regenerate": "വീണ്ടും ജനറേറ്റ് ചെയ്യുക",
|
"regenerate": "വീണ്ടും ജനറേറ്റ് ചെയ്യുക",
|
||||||
"edit": "എഡിറ്റ് ചെയ്യുക",
|
"edit": "എഡിറ്റ് ചെയ്യുക",
|
||||||
|
"delete": "ഇല്ലാതാക്കുക",
|
||||||
"saveAndSubmit": "സേവ് ചെയ്ത് സമര്പ്പിക്കുക",
|
"saveAndSubmit": "സേവ് ചെയ്ത് സമര്പ്പിക്കുക",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "ഒരു സന്ദേശം ടൈപ്പ് ചെയ്യുക..."
|
"placeholder": "ഒരു സന്ദേശം ടൈപ്പ് ചെയ്യുക..."
|
||||||
@ -99,5 +100,15 @@
|
|||||||
"rephrase": "പുനഃരൂപീകരിക്കുക",
|
"rephrase": "പുനഃരൂപീകരിക്കുക",
|
||||||
"translate": "വിവർത്തനം ചെയ്യുക"
|
"translate": "വിവർത്തനം ചെയ്യുക"
|
||||||
},
|
},
|
||||||
"citations": "ഉദ്ധരണികൾ"
|
"citations": "ഉദ്ധരണികൾ",
|
||||||
|
"downloadCode": "കോഡ് ഡൗൺലോഡ് ചെയ്യുക",
|
||||||
|
"date": {
|
||||||
|
"pinned": "പിൻ ചെയ്തത്",
|
||||||
|
"today": "ഇന്ന്",
|
||||||
|
"yesterday": "ഇന്നലെ",
|
||||||
|
"last7Days": "കഴിഞ്ഞ 7 ദിവസം",
|
||||||
|
"older": "പഴയത്"
|
||||||
|
},
|
||||||
|
"pin": "പിൻ ചെയ്യുക",
|
||||||
|
"unpin": "അൺപിൻ ചെയ്യുക"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "നാമം"
|
"name": "നാമം"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "ഇല്ലാതാക്കുക"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "നിങ്ങൾക്ക് ഈ വിജ്ഞാനം ഇല്ലാതാക്കണമെന്ന് ഉറപ്പാണോ?"
|
"delete": "നിങ്ങൾക്ക് ഈ വിജ്ഞാനം ഇല്ലാതാക്കണമെന്ന് ഉറപ്പാണോ?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Søker på internett",
|
"webSearch": "Søker på internett",
|
||||||
"regenerate": "Regenerer",
|
"regenerate": "Regenerer",
|
||||||
"edit": "Endre",
|
"edit": "Endre",
|
||||||
|
"delete": "Slett",
|
||||||
"saveAndSubmit": "Lagre & Send inn",
|
"saveAndSubmit": "Lagre & Send inn",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Skriv en melding..."
|
"placeholder": "Skriv en melding..."
|
||||||
@ -101,5 +102,15 @@
|
|||||||
"translate": "Oversett",
|
"translate": "Oversett",
|
||||||
"custom": "Egendefinert"
|
"custom": "Egendefinert"
|
||||||
},
|
},
|
||||||
"citations": "Sitater"
|
"citations": "Sitater",
|
||||||
|
"downloadCode": "Last ned kode",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Festet",
|
||||||
|
"today": "I dag",
|
||||||
|
"yesterday": "I går",
|
||||||
|
"last7Days": "Siste 7 dager",
|
||||||
|
"older": "Eldre"
|
||||||
|
},
|
||||||
|
"pin": "Fest",
|
||||||
|
"unpin": "Løsne"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Navn"
|
"name": "Navn"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Slett"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Er du sikker på at du vil slette denne kunnskapen?"
|
"delete": "Er du sikker på at du vil slette denne kunnskapen?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Pesquisando na web",
|
"webSearch": "Pesquisando na web",
|
||||||
"regenerate": "Gerar Novamente",
|
"regenerate": "Gerar Novamente",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
|
"delete": "Excluir",
|
||||||
"saveAndSubmit": "Salvar & Enviar",
|
"saveAndSubmit": "Salvar & Enviar",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Digite uma mensagem..."
|
"placeholder": "Digite uma mensagem..."
|
||||||
@ -83,13 +84,13 @@
|
|||||||
"placeholder": "Digite o valor do Top P (ex: 0.9, 0.95)"
|
"placeholder": "Digite o valor do Top P (ex: 0.9, 0.95)"
|
||||||
},
|
},
|
||||||
"numGpu": {
|
"numGpu": {
|
||||||
"label": "Num GPUs",
|
"label": "Num GPUs",
|
||||||
"placeholder": "Digite o número de camadas para enviar para a(s) GPU(s)"
|
"placeholder": "Digite o número de camadas para enviar para a(s) GPU(s)"
|
||||||
},
|
},
|
||||||
"systemPrompt": {
|
"systemPrompt": {
|
||||||
"label": "Prompt do Sistema Temporário",
|
"label": "Prompt do Sistema Temporário",
|
||||||
"placeholder": "Digite o Prompt do Sistema",
|
"placeholder": "Digite o Prompt do Sistema",
|
||||||
"help": "Esta é uma maneira rápida de definir o prompt do sistema no chat atual, que substituirá o prompt do sistema selecionado, se existir."
|
"help": "Esta é uma maneira rápida de definir o prompt do sistema no chat atual, que substituirá o prompt do sistema selecionado, se existir."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"advanced": "Mais Configurações do Modelo"
|
"advanced": "Mais Configurações do Modelo"
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "Reformular",
|
"rephrase": "Reformular",
|
||||||
"translate": "Traduzir"
|
"translate": "Traduzir"
|
||||||
},
|
},
|
||||||
"citations": "Citações"
|
"citations": "Citações",
|
||||||
|
"downloadCode": "Baixar Código",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Fixado",
|
||||||
|
"today": "Hoje",
|
||||||
|
"yesterday": "Ontem",
|
||||||
|
"last7Days": "Últimos 7 Dias",
|
||||||
|
"older": "Mais Antigos"
|
||||||
|
},
|
||||||
|
"pin": "Fixar",
|
||||||
|
"unpin": "Desafixar"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Nome"
|
"name": "Nome"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Excluir"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Tem certeza de que deseja excluir este conhecimento?"
|
"delete": "Tem certeza de que deseja excluir este conhecimento?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "Поиск в интернете",
|
"webSearch": "Поиск в интернете",
|
||||||
"regenerate": "Пересоздать",
|
"regenerate": "Пересоздать",
|
||||||
"edit": "Редактировать",
|
"edit": "Редактировать",
|
||||||
|
"delete": "Удалить",
|
||||||
"saveAndSubmit": "Сохранить и отправить",
|
"saveAndSubmit": "Сохранить и отправить",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "Введите сообщение..."
|
"placeholder": "Введите сообщение..."
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "Перефразировать",
|
"rephrase": "Перефразировать",
|
||||||
"translate": "Перевести"
|
"translate": "Перевести"
|
||||||
},
|
},
|
||||||
"citations": "Цитаты"
|
"citations": "Цитаты",
|
||||||
|
"downloadCode": "Скачать код",
|
||||||
|
"date": {
|
||||||
|
"pinned": "Закреплено",
|
||||||
|
"today": "Сегодня",
|
||||||
|
"yesterday": "Вчера",
|
||||||
|
"last7Days": "Последние 7 дней",
|
||||||
|
"older": "Ранее"
|
||||||
|
},
|
||||||
|
"pin": "Закрепить",
|
||||||
|
"unpin": "Открепить"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "Имя"
|
"name": "Имя"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "Удалить"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Вы уверены, что хотите удалить это знание?"
|
"delete": "Вы уверены, что хотите удалить это знание?"
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"webSearch": "搜索网络",
|
"webSearch": "搜索网络",
|
||||||
"regenerate": "重新生成",
|
"regenerate": "重新生成",
|
||||||
"edit": "编辑",
|
"edit": "编辑",
|
||||||
|
"delete": "删除",
|
||||||
"saveAndSubmit": "保存 & 提交",
|
"saveAndSubmit": "保存 & 提交",
|
||||||
"editMessage": {
|
"editMessage": {
|
||||||
"placeholder": "输入一条消息..."
|
"placeholder": "输入一条消息..."
|
||||||
@ -100,5 +101,15 @@
|
|||||||
"rephrase": "重述",
|
"rephrase": "重述",
|
||||||
"translate": "翻译"
|
"translate": "翻译"
|
||||||
},
|
},
|
||||||
"citations": "引用"
|
"citations": "引用",
|
||||||
|
"downloadCode": "下载代码",
|
||||||
|
"date": {
|
||||||
|
"pinned": "已置顶",
|
||||||
|
"today": "今天",
|
||||||
|
"yesterday": "昨天",
|
||||||
|
"last7Days": "最近7天",
|
||||||
|
"older": "更早"
|
||||||
|
},
|
||||||
|
"pin": "置顶",
|
||||||
|
"unpin": "取消置顶"
|
||||||
}
|
}
|
@ -10,9 +10,6 @@
|
|||||||
"expandedColumns": {
|
"expandedColumns": {
|
||||||
"name": "名称"
|
"name": "名称"
|
||||||
},
|
},
|
||||||
"tooltip": {
|
|
||||||
"delete": "删除"
|
|
||||||
},
|
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "您确定要删除此知识吗?"
|
"delete": "您确定要删除此知识吗?"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Tooltip } from "antd"
|
import { programmingLanguages } from "@/utils/langauge-extension"
|
||||||
import { CheckIcon, ClipboardIcon } from "lucide-react"
|
import { Tooltip, Modal } from "antd"
|
||||||
import { FC, useState } from "react"
|
import { CheckIcon, ClipboardIcon, DownloadIcon } from "lucide-react"
|
||||||
|
import { FC, useState } from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||||
import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism"
|
import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism"
|
||||||
@ -10,26 +11,53 @@ interface Props {
|
|||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CodeBlock: FC<Props> =({ language, value }) => {
|
export const CodeBlock: FC<Props> = ({ language, value }) => {
|
||||||
const [isBtnPressed, setIsBtnPressed] = useState(false)
|
const [isBtnPressed, setIsBtnPressed] = useState(false)
|
||||||
|
const [previewVisible, setPreviewVisible] = useState(false)
|
||||||
const { t } = useTranslation("common")
|
const { t } = useTranslation("common")
|
||||||
|
|
||||||
|
const handleCopy = () => {
|
||||||
|
navigator.clipboard.writeText(value)
|
||||||
|
setIsBtnPressed(true)
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsBtnPressed(false)
|
||||||
|
}, 4000)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePreviewClose = () => {
|
||||||
|
setPreviewVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDownload = () => {
|
||||||
|
const blob = new Blob([value], { type: "text/plain" })
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const a = document.createElement("a")
|
||||||
|
a.href = url
|
||||||
|
a.download = `code_${new Date().toISOString().replace(/[:.]/g, "-")}.${programmingLanguages[language] || language}`
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a)
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="code relative text-base font-sans codeblock bg-zinc-950 rounded-md overflow-hidden">
|
<div className="code relative text-base font-sans codeblock bg-zinc-950 rounded-md overflow-hidden">
|
||||||
<div className="flex bg-gray-800 items-center justify-between py-1.5 px-4">
|
<div className="flex bg-gray-800 items-center justify-between py-1.5 px-4">
|
||||||
<span className="text-xs lowercase text-gray-200">{language}</span>
|
<span className="text-xs lowercase text-gray-200">{language}</span>
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center gap-2">
|
||||||
|
<Tooltip title={t("downloadCode")}>
|
||||||
|
<button
|
||||||
|
onClick={handleDownload}
|
||||||
|
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none">
|
||||||
|
<DownloadIcon className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
<Tooltip title={t("copyToClipboard")}>
|
<Tooltip title={t("copyToClipboard")}>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={handleCopy}
|
||||||
navigator.clipboard.writeText(value)
|
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none">
|
||||||
setIsBtnPressed(true)
|
|
||||||
setTimeout(() => {
|
|
||||||
setIsBtnPressed(false)
|
|
||||||
}, 4000)
|
|
||||||
}}
|
|
||||||
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 focus:ring-offset-gray-100">
|
|
||||||
{!isBtnPressed ? (
|
{!isBtnPressed ? (
|
||||||
<ClipboardIcon className="h-4 w-4" />
|
<ClipboardIcon className="h-4 w-4" />
|
||||||
) : (
|
) : (
|
||||||
@ -61,6 +89,28 @@ export const CodeBlock: FC<Props> =({ language, value }) => {
|
|||||||
{value}
|
{value}
|
||||||
</SyntaxHighlighter>
|
</SyntaxHighlighter>
|
||||||
</div>
|
</div>
|
||||||
|
{previewVisible && (
|
||||||
|
<Modal
|
||||||
|
open={previewVisible}
|
||||||
|
onCancel={handlePreviewClose}
|
||||||
|
footer={null}
|
||||||
|
width="80%"
|
||||||
|
zIndex={999999}
|
||||||
|
centered
|
||||||
|
styles={{
|
||||||
|
body: {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<div className="relative w-full h-[80vh]">
|
||||||
|
<iframe
|
||||||
|
srcDoc={value}
|
||||||
|
title="HTML Preview"
|
||||||
|
className="w-full h-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,8 @@ export const PlaygroundMessage = (props: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="group w-full text-gray-800 dark:text-gray-100">
|
<div className="group w-full text-gray-800 dark:text-gray-100">
|
||||||
<div className="text-base md:max-w-2xl lg:max-w-xl xl:max-w-3xl flex lg:px-0 m-auto w-full">
|
<div className="text-base md:max-w-2xl lg:max-w-xl xl:max-w-3xl flex lg:px-0 m-auto w-full">
|
||||||
<div className="flex flex-row gap-4 md:gap-6 md:max-w-2xl lg:max-w-xl xl:max-w-3xl p-4 md:py-6 lg:px-0 m-auto w-full">
|
<div className="flex flex-row gap-4 md:gap-6 p-4 md:py-6 lg:px-0 m-auto w-full">
|
||||||
<div className="w-8 flex flex-col relative items-end">
|
<div className="w-8 flex flex-col relative items-end">
|
||||||
<div className="relative h-7 w-7 p-1 rounded-sm text-white flex items-center justify-center text-opacity-100r">
|
<div className="relative h-7 w-7 p-1 rounded-sm text-white flex items-center justify-center text-opacity-100r">
|
||||||
{props.isBot ? (
|
{props.isBot ? (
|
||||||
|
@ -12,7 +12,7 @@ export const FireworksMonoIcon = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}>
|
{...props}>
|
||||||
<path
|
<path
|
||||||
fill="#fff"
|
fill="#6720FF"
|
||||||
d="M318.563 221.755c-17.7 0-33.584-10.508-40.357-26.777L196.549 0h47.793l74.5 178.361L393.273 0h47.793L358.92 195.048c-6.808 16.199-22.657 26.707-40.357 26.707zM425.111 314.933c-17.63 0-33.444-10.439-40.287-26.567-6.877-16.269-3.317-34.842 9.112-47.445l148.721-150.64 18.572 43.813-136.153 137.654 194.071-1.082 18.573 43.813-212.574.524-.07-.07h.035zM0 314.408l18.573-43.813 194.07 1.082L76.525 133.988l18.573-43.813 148.721 150.641c12.428 12.568 16.024 31.21 9.111 47.444-6.842 16.164-22.727 26.567-40.287 26.567L.07 314.339l-.07.069z"></path>
|
d="M318.563 221.755c-17.7 0-33.584-10.508-40.357-26.777L196.549 0h47.793l74.5 178.361L393.273 0h47.793L358.92 195.048c-6.808 16.199-22.657 26.707-40.357 26.707zM425.111 314.933c-17.63 0-33.444-10.439-40.287-26.567-6.877-16.269-3.317-34.842 9.112-47.445l148.721-150.64 18.572 43.813-136.153 137.654 194.071-1.082 18.573 43.813-212.574.524-.07-.07h.035zM0 314.408l18.573-43.813 194.07 1.082L76.525 133.988l18.573-43.813 148.721 150.641c12.428 12.568 16.024 31.21 9.111 47.444-6.842 16.164-22.727 26.567-40.287 26.567L.07 314.339l-.07.069z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
|
@ -54,14 +54,14 @@ export default function OptionLayout({
|
|||||||
if (confirm) {
|
if (confirm) {
|
||||||
const db = new PageAssitDatabase()
|
const db = new PageAssitDatabase()
|
||||||
await db.deleteAllChatHistory()
|
await db.deleteAllChatHistory()
|
||||||
queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: ["fetchChatHistory"]
|
queryKey: ["fetchChatHistory"]
|
||||||
})
|
})
|
||||||
clearChat()
|
clearChat()
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="text-gray-600 hover:text-gray-800 dark:text-gray-300 dark:hover:text-gray-100">
|
className="text-gray-600 hover:text-gray-800 dark:text-gray-300 dark:hover:text-gray-100">
|
||||||
<EraserIcon className="size-5" />
|
<EraserIcon className="size-5" />
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -93,7 +93,7 @@ export const KnowledgeSettings = () => {
|
|||||||
key: "action",
|
key: "action",
|
||||||
render: (text: string, record: any) => (
|
render: (text: string, record: any) => (
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<Tooltip title={t("tooltip.delete")}>
|
<Tooltip title={t("common:delete")}>
|
||||||
<button
|
<button
|
||||||
disabled={isDeleting}
|
disabled={isDeleting}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -20,6 +20,7 @@ export const AddOllamaModelModal: React.FC<Props> = ({ open, setOpen }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const pullModel = async (modelName: string) => {
|
const pullModel = async (modelName: string) => {
|
||||||
|
modelName.replaceAll("ollama pull", "").replaceAll("ollama run", "").trim()
|
||||||
notification.info({
|
notification.info({
|
||||||
message: t("manageModels.notification.pullModel"),
|
message: t("manageModels.notification.pullModel"),
|
||||||
description: t("manageModels.notification.pullModelDescription", {
|
description: t("manageModels.notification.pullModelDescription", {
|
||||||
@ -52,7 +53,7 @@ export const AddOllamaModelModal: React.FC<Props> = ({ open, setOpen }) => {
|
|||||||
<Input
|
<Input
|
||||||
{...form.getInputProps("model")}
|
{...form.getInputProps("model")}
|
||||||
required
|
required
|
||||||
placeholder={t("manageModels.modal.placeholder")}
|
placeholder={"qwen2.5:3b"}
|
||||||
size="large"
|
size="large"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -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-200px)]">
|
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 />
|
||||||
@ -61,10 +61,10 @@ export const PlaygroundChat = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!isAtBottom && (
|
{!isAtBottom && (
|
||||||
<div className="fixed md:bottom-44 bottom-36 z-[9999999] left-0 right-0 flex justify-center">
|
<div className="fixed bottom-36 z-20 left-0 right-0 flex justify-center">
|
||||||
<button
|
<button
|
||||||
onClick={scrollToBottom}
|
onClick={scrollToBottom}
|
||||||
className="bg-gray-100 dark:bg-gray-800 p-1 rounded-full shadow-md hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200">
|
className="bg-white border border-gray-100 dark:border-none dark:bg-white/20 p-1.5 rounded-full pointer-events-auto">
|
||||||
<ChevronDown className="size-4 text-gray-600 dark:text-gray-300" />
|
<ChevronDown className="size-4 text-gray-600 dark:text-gray-300" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -190,7 +190,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-3 pt-3 md:px-6 md:pt-6 bg-gray-50 dark:bg-[#262626] border rounded-t-xl dark:border-gray-600">
|
<div className="px-3 pt-3 md:px-4 md:pt-4 bg-gray-100 dark:bg-[#262626] border rounded-t-xl dark:border-gray-600">
|
||||||
<div
|
<div
|
||||||
className={`h-full rounded-md shadow relative ${
|
className={`h-full rounded-md shadow relative ${
|
||||||
form.values.image.length === 0 ? "hidden" : "block"
|
form.values.image.length === 0 ? "hidden" : "block"
|
||||||
@ -213,7 +213,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex bg-white dark:bg-transparent">
|
<div className="flex rounded-t-xl bg-white dark:bg-transparent">
|
||||||
<form
|
<form
|
||||||
onSubmit={form.onSubmit(async (value) => {
|
onSubmit={form.onSubmit(async (value) => {
|
||||||
stopListening()
|
stopListening()
|
||||||
@ -264,7 +264,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
required
|
required
|
||||||
onPaste={handlePaste}
|
onPaste={handlePaste}
|
||||||
rows={1}
|
rows={1}
|
||||||
style={{ minHeight: "60px" }}
|
style={{ minHeight: "40px" }}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
placeholder={t("form.textarea.placeholder")}
|
placeholder={t("form.textarea.placeholder")}
|
||||||
{...form.getInputProps("message")}
|
{...form.getInputProps("message")}
|
||||||
@ -286,7 +286,23 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex !justify-end gap-3">
|
<div className="flex !justify-end gap-3">
|
||||||
<KnowledgeSelect />
|
|
||||||
|
|
||||||
|
{!selectedKnowledge && (
|
||||||
|
<Tooltip title={t("tooltip.uploadImage")}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
inputRef.current?.click()
|
||||||
|
}}
|
||||||
|
className={`flex items-center justify-center dark:text-gray-300 ${
|
||||||
|
chatMode === "rag" ? "hidden" : "block"
|
||||||
|
}`}>
|
||||||
|
<ImageIcon className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
{browserSupportsSpeechRecognition && (
|
{browserSupportsSpeechRecognition && (
|
||||||
<Tooltip title={t("tooltip.speechToText")}>
|
<Tooltip title={t("tooltip.speechToText")}>
|
||||||
<button
|
<button
|
||||||
@ -314,21 +330,8 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
<KnowledgeSelect />
|
||||||
|
|
||||||
{!selectedKnowledge && (
|
|
||||||
<Tooltip title={t("tooltip.uploadImage")}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
inputRef.current?.click()
|
|
||||||
}}
|
|
||||||
className={`flex items-center justify-center dark:text-gray-300 ${
|
|
||||||
chatMode === "rag" ? "hidden" : "block"
|
|
||||||
}`}>
|
|
||||||
<ImageIcon className="h-5 w-5" />
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
{!isSending ? (
|
{!isSending ? (
|
||||||
<Dropdown.Button
|
<Dropdown.Button
|
||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
|
@ -4,11 +4,18 @@ import {
|
|||||||
formatToChatHistory,
|
formatToChatHistory,
|
||||||
formatToMessage,
|
formatToMessage,
|
||||||
deleteByHistoryId,
|
deleteByHistoryId,
|
||||||
updateHistory
|
updateHistory,
|
||||||
|
pinHistory
|
||||||
} from "@/db"
|
} from "@/db"
|
||||||
import { Empty, Skeleton } from "antd"
|
import { Empty, Skeleton, Dropdown, Menu } from "antd"
|
||||||
import { useMessageOption } from "~/hooks/useMessageOption"
|
import { useMessageOption } from "~/hooks/useMessageOption"
|
||||||
import { PencilIcon, Trash2 } from "lucide-react"
|
import {
|
||||||
|
PencilIcon,
|
||||||
|
Trash2,
|
||||||
|
MoreVertical,
|
||||||
|
PinIcon,
|
||||||
|
PinOffIcon
|
||||||
|
} from "lucide-react"
|
||||||
import { useNavigate } from "react-router-dom"
|
import { useNavigate } from "react-router-dom"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import {
|
import {
|
||||||
@ -38,7 +45,46 @@ export const Sidebar = ({ onClose }: Props) => {
|
|||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const db = new PageAssitDatabase()
|
const db = new PageAssitDatabase()
|
||||||
const history = await db.getChatHistories()
|
const history = await db.getChatHistories()
|
||||||
return history
|
|
||||||
|
const now = new Date()
|
||||||
|
const today = new Date(now.setHours(0, 0, 0, 0))
|
||||||
|
const yesterday = new Date(today)
|
||||||
|
yesterday.setDate(yesterday.getDate() - 1)
|
||||||
|
const lastWeek = new Date(today)
|
||||||
|
lastWeek.setDate(lastWeek.getDate() - 7)
|
||||||
|
|
||||||
|
const pinnedItems = history.filter((item) => item.is_pinned)
|
||||||
|
const todayItems = history.filter(
|
||||||
|
(item) => !item.is_pinned && new Date(item?.createdAt) >= today
|
||||||
|
)
|
||||||
|
const yesterdayItems = history.filter(
|
||||||
|
(item) =>
|
||||||
|
!item.is_pinned &&
|
||||||
|
new Date(item?.createdAt) >= yesterday &&
|
||||||
|
new Date(item?.createdAt) < today
|
||||||
|
)
|
||||||
|
const lastWeekItems = history.filter(
|
||||||
|
(item) =>
|
||||||
|
!item.is_pinned &&
|
||||||
|
new Date(item?.createdAt) >= lastWeek &&
|
||||||
|
new Date(item?.createdAt) < yesterday
|
||||||
|
)
|
||||||
|
const olderItems = history.filter(
|
||||||
|
(item) => !item.is_pinned && new Date(item?.createdAt) < lastWeek
|
||||||
|
)
|
||||||
|
|
||||||
|
const groups = []
|
||||||
|
|
||||||
|
if (pinnedItems.length)
|
||||||
|
groups.push({ label: "pinned", items: pinnedItems })
|
||||||
|
if (todayItems.length) groups.push({ label: "today", items: todayItems })
|
||||||
|
if (yesterdayItems.length)
|
||||||
|
groups.push({ label: "yesterday", items: yesterdayItems })
|
||||||
|
if (lastWeekItems.length)
|
||||||
|
groups.push({ label: "last7days", items: lastWeekItems })
|
||||||
|
if (olderItems.length) groups.push({ label: "older", items: olderItems })
|
||||||
|
|
||||||
|
return groups
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -67,6 +113,18 @@ export const Sidebar = ({ onClose }: Props) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { mutate: pinChatHistory, isPending: pinLoading } = useMutation({
|
||||||
|
mutationKey: ["pinHistory"],
|
||||||
|
mutationFn: async (data: { id: string; is_pinned: boolean }) => {
|
||||||
|
return await pinHistory(data.id, data.is_pinned)
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
client.invalidateQueries({
|
||||||
|
queryKey: ["fetchChatHistory"]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overflow-y-auto z-99">
|
<div className="overflow-y-auto z-99">
|
||||||
{status === "success" && chatHistories.length === 0 && (
|
{status === "success" && chatHistories.length === 0 && (
|
||||||
@ -86,51 +144,99 @@ export const Sidebar = ({ onClose }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{status === "success" && chatHistories.length > 0 && (
|
{status === "success" && chatHistories.length > 0 && (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{chatHistories.map((chat, index) => (
|
{chatHistories.map((group, groupIndex) => (
|
||||||
<div
|
<div key={groupIndex}>
|
||||||
key={index}
|
<h3 className="px-2 text-sm font-medium text-gray-500">
|
||||||
className="flex py-2 px-2 items-start gap-3 relative rounded-md truncate hover:pr-4 group transition-opacity duration-300 ease-in-out bg-gray-100 dark:bg-[#232222] dark:text-gray-100 text-gray-800 border hover:bg-gray-200 dark:hover:bg-[#2d2d2d] dark:border-gray-800">
|
{t(`common:date:${group.label}`)}
|
||||||
<button
|
</h3>
|
||||||
className="flex-1 overflow-hidden break-all text-start truncate w-full"
|
<div className="flex flex-col gap-2 mt-2">
|
||||||
onClick={async () => {
|
{group.items.map((chat, index) => (
|
||||||
const db = new PageAssitDatabase()
|
<div
|
||||||
const history = await db.getChatHistory(chat.id)
|
key={index}
|
||||||
setHistoryId(chat.id)
|
className="flex py-2 px-2 items-start gap-3 relative rounded-md truncate hover:pr-4 group transition-opacity duration-300 ease-in-out bg-gray-100 dark:bg-[#232222] dark:text-gray-100 text-gray-800 border hover:bg-gray-200 dark:hover:bg-[#2d2d2d] dark:border-gray-800">
|
||||||
setHistory(formatToChatHistory(history))
|
<button
|
||||||
setMessages(formatToMessage(history))
|
className="flex-1 overflow-hidden break-all text-start truncate w-full"
|
||||||
const isLastUsedChatModel = await lastUsedChatModelEnabled()
|
onClick={async () => {
|
||||||
if (isLastUsedChatModel) {
|
const db = new PageAssitDatabase()
|
||||||
const currentChatModel = await getLastUsedChatModel(chat.id)
|
const history = await db.getChatHistory(chat.id)
|
||||||
if (currentChatModel) {
|
setHistoryId(chat.id)
|
||||||
setSelectedModel(currentChatModel)
|
setHistory(formatToChatHistory(history))
|
||||||
}
|
setMessages(formatToMessage(history))
|
||||||
}
|
const isLastUsedChatModel =
|
||||||
navigate("/")
|
await lastUsedChatModelEnabled()
|
||||||
onClose()
|
if (isLastUsedChatModel) {
|
||||||
}}>
|
const currentChatModel = await getLastUsedChatModel(
|
||||||
<span className="flex-grow truncate">{chat.title}</span>
|
chat.id
|
||||||
</button>
|
)
|
||||||
<div className="flex flex-row gap-3">
|
if (currentChatModel) {
|
||||||
<button
|
setSelectedModel(currentChatModel)
|
||||||
onClick={() => {
|
}
|
||||||
const newTitle = prompt(t("editHistoryTitle"), chat.title)
|
}
|
||||||
|
navigate("/")
|
||||||
if (newTitle) {
|
onClose()
|
||||||
editHistory({ id: chat.id, title: newTitle })
|
}}>
|
||||||
}
|
<span className="flex-grow truncate">{chat.title}</span>
|
||||||
}}
|
</button>
|
||||||
className="text-gray-500 dark:text-gray-400 opacity-80">
|
<div className="flex items-center gap-2">
|
||||||
<PencilIcon className="w-4 h-4" />
|
<Dropdown
|
||||||
</button>
|
overlay={
|
||||||
|
<Menu>
|
||||||
<button
|
<Menu.Item
|
||||||
onClick={() => {
|
key="pin"
|
||||||
if (!confirm(t("deleteHistoryConfirmation"))) return
|
icon={
|
||||||
deleteHistory(chat.id)
|
chat.is_pinned ? (
|
||||||
}}
|
<PinOffIcon className="w-4 h-4" />
|
||||||
className="text-red-500 dark:text-red-400 opacity-80">
|
) : (
|
||||||
<Trash2 className=" w-4 h-4 " />
|
<PinIcon className="w-4 h-4" />
|
||||||
</button>
|
)
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
pinChatHistory({
|
||||||
|
id: chat.id,
|
||||||
|
is_pinned: !chat.is_pinned
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={pinLoading}>
|
||||||
|
{chat.is_pinned
|
||||||
|
? t("common:unpin")
|
||||||
|
: t("common:pin")}
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
key="edit"
|
||||||
|
icon={<PencilIcon className="w-4 h-4" />}
|
||||||
|
onClick={() => {
|
||||||
|
const newTitle = prompt(
|
||||||
|
t("editHistoryTitle"),
|
||||||
|
chat.title
|
||||||
|
)
|
||||||
|
if (newTitle) {
|
||||||
|
editHistory({ id: chat.id, title: newTitle })
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{t("common:edit")}
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
key="delete"
|
||||||
|
icon={<Trash2 className="w-4 h-4" />}
|
||||||
|
danger
|
||||||
|
onClick={() => {
|
||||||
|
if (!confirm(t("deleteHistoryConfirmation")))
|
||||||
|
return
|
||||||
|
deleteHistory(chat.id)
|
||||||
|
}}>
|
||||||
|
{t("common:delete")}
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
trigger={["click"]}
|
||||||
|
placement="bottomRight">
|
||||||
|
<button className="text-gray-500 dark:text-gray-400 opacity-80 hover:opacity-100">
|
||||||
|
<MoreVertical className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -8,6 +8,7 @@ type HistoryInfo = {
|
|||||||
title: string
|
title: string
|
||||||
is_rag: boolean
|
is_rag: boolean
|
||||||
message_source?: "copilot" | "web-ui"
|
message_source?: "copilot" | "web-ui"
|
||||||
|
is_pinned?: boolean
|
||||||
createdAt: number
|
createdAt: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +233,11 @@ export const generateID = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const saveHistory = async (title: string, is_rag?: boolean, message_source?: "copilot" | "web-ui") => {
|
export const saveHistory = async (
|
||||||
|
title: string,
|
||||||
|
is_rag?: boolean,
|
||||||
|
message_source?: "copilot" | "web-ui"
|
||||||
|
) => {
|
||||||
const id = generateID()
|
const id = generateID()
|
||||||
const createdAt = Date.now()
|
const createdAt = Date.now()
|
||||||
const history = { id, title, createdAt, is_rag, message_source }
|
const history = { id, title, createdAt, is_rag, message_source }
|
||||||
@ -317,6 +322,18 @@ export const updateHistory = async (id: string, title: string) => {
|
|||||||
db.db.set({ chatHistories: newChatHistories })
|
db.db.set({ chatHistories: newChatHistories })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const pinHistory = async (id: string, is_pinned: boolean) => {
|
||||||
|
const db = new PageAssitDatabase()
|
||||||
|
const chatHistories = await db.getChatHistories()
|
||||||
|
const newChatHistories = chatHistories.map((history) => {
|
||||||
|
if (history.id === id) {
|
||||||
|
history.is_pinned = is_pinned
|
||||||
|
}
|
||||||
|
return history
|
||||||
|
})
|
||||||
|
db.db.set({ chatHistories: newChatHistories })
|
||||||
|
}
|
||||||
|
|
||||||
export const removeMessageUsingHistoryId = async (history_id: string) => {
|
export const removeMessageUsingHistoryId = async (history_id: string) => {
|
||||||
const db = new PageAssitDatabase()
|
const db = new PageAssitDatabase()
|
||||||
const chatHistory = await db.getChatHistory(history_id)
|
const chatHistory = await db.getChatHistory(history_id)
|
||||||
@ -490,7 +507,6 @@ export const getRecentChatFromCopilot = async () => {
|
|||||||
return { history, messages }
|
return { history, messages }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const getTitleById = async (id: string) => {
|
export const getTitleById = async (id: string) => {
|
||||||
const db = new PageAssitDatabase()
|
const db = new PageAssitDatabase()
|
||||||
const title = await db.getChatHistoryTitleById(id)
|
const title = await db.getChatHistoryTitleById(id)
|
||||||
|
93
src/entries/hf-pull.content.ts
Normal file
93
src/entries/hf-pull.content.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
export default defineContentScript({
|
||||||
|
main(ctx) {
|
||||||
|
const downloadModel = async (modelName: string) => {
|
||||||
|
const ok = confirm(
|
||||||
|
`[Page Assist Extension] Do you want to pull the ${modelName} model? This has nothing to do with the huggingface.co website. The model will be pulled locally once you confirm. Make sure Ollama is running.`
|
||||||
|
)
|
||||||
|
if (ok) {
|
||||||
|
alert(
|
||||||
|
`[Page Assist Extension] Pulling ${modelName} model. For more details, check the extension icon.`
|
||||||
|
)
|
||||||
|
|
||||||
|
await browser.runtime.sendMessage({
|
||||||
|
type: "pull_model",
|
||||||
|
modelName
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadSVG = `
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24" width="16" height="16">
|
||||||
|
<path d="M12 16l-6-6h4V4h4v6h4l-6 6z"/>
|
||||||
|
<path d="M4 20h16v-2H4v2z"/>
|
||||||
|
</svg>
|
||||||
|
`
|
||||||
|
|
||||||
|
const injectDownloadButton = (modal: HTMLElement) => {
|
||||||
|
const copyButton = modal.querySelector(
|
||||||
|
'button[title="Copy snippet to clipboard"]'
|
||||||
|
)
|
||||||
|
if (copyButton && !modal.querySelector(".pageassist-download-button")) {
|
||||||
|
const downloadButton = copyButton.cloneNode(true) as HTMLElement
|
||||||
|
downloadButton.classList.add("pageassist-download-button")
|
||||||
|
downloadButton.querySelector("svg")!.outerHTML = downloadSVG
|
||||||
|
downloadButton.querySelector("span")!.textContent =
|
||||||
|
"Pull from Page Assist"
|
||||||
|
downloadButton.addEventListener("click", async () => {
|
||||||
|
const preElement = modal.querySelector("pre")
|
||||||
|
if (preElement) {
|
||||||
|
let modelCommand = ""
|
||||||
|
preElement.childNodes.forEach((node) => {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
modelCommand += node.textContent
|
||||||
|
} else if (node instanceof HTMLSelectElement) {
|
||||||
|
modelCommand += node.value
|
||||||
|
} else if (node instanceof HTMLElement) {
|
||||||
|
const selectElement = node.querySelector(
|
||||||
|
"select"
|
||||||
|
) as HTMLSelectElement
|
||||||
|
if (selectElement) {
|
||||||
|
modelCommand += selectElement.value
|
||||||
|
} else {
|
||||||
|
modelCommand += node.textContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
modelCommand = modelCommand.trim()
|
||||||
|
|
||||||
|
await downloadModel(
|
||||||
|
modelCommand
|
||||||
|
?.replaceAll("ollama run", "")
|
||||||
|
?.replaceAll("ollama pull", "")
|
||||||
|
?.trim()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
copyButton.parentElement!.insertBefore(
|
||||||
|
downloadButton,
|
||||||
|
copyButton.nextSibling
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
mutation.addedNodes.forEach((node) => {
|
||||||
|
if (node instanceof HTMLElement) {
|
||||||
|
const modal = node.querySelector(".shadow-alternate") as HTMLElement
|
||||||
|
if (modal) {
|
||||||
|
injectDownloadButton(modal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true })
|
||||||
|
},
|
||||||
|
allFrames: true,
|
||||||
|
matches: ["*://huggingface.co/*"]
|
||||||
|
})
|
@ -8,7 +8,7 @@ import {
|
|||||||
systemPromptForNonRagOption
|
systemPromptForNonRagOption
|
||||||
} from "~/services/ollama"
|
} from "~/services/ollama"
|
||||||
import { type ChatHistory, type Message } from "~/store/option"
|
import { type ChatHistory, type Message } from "~/store/option"
|
||||||
import { HumanMessage, SystemMessage } from "@langchain/core/messages"
|
import { SystemMessage } from "@langchain/core/messages"
|
||||||
import { useStoreMessageOption } from "~/store/option"
|
import { useStoreMessageOption } from "~/store/option"
|
||||||
import {
|
import {
|
||||||
deleteChatForEdit,
|
deleteChatForEdit,
|
||||||
|
@ -13,12 +13,9 @@ import { fa } from "./lang/fa";
|
|||||||
import { de } from "./lang/de";
|
import { de } from "./lang/de";
|
||||||
import { da } from "./lang/da";
|
import { da } from "./lang/da";
|
||||||
import { no } from "./lang/no";
|
import { no } from "./lang/no";
|
||||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
||||||
|
|
||||||
const supportedLanguages = ['en', 'zh', 'ja', 'fa', 'de', 'da', 'no', 'es', 'fr', 'it', 'ml', 'pt-BR', 'ru', 'zh-CN', 'ru-RU', 'ja-JP'];
|
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(LanguageDetector)
|
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
.init({
|
.init({
|
||||||
resources: {
|
resources: {
|
||||||
|
29
src/utils/langauge-extension.ts
Normal file
29
src/utils/langauge-extension.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export const programmingLanguages = {
|
||||||
|
html: "html",
|
||||||
|
javascript: "js",
|
||||||
|
typescript: "ts",
|
||||||
|
python: "py",
|
||||||
|
java: "java",
|
||||||
|
cpp: "cpp",
|
||||||
|
c: "c",
|
||||||
|
csharp: "cs",
|
||||||
|
ruby: "rb",
|
||||||
|
php: "php",
|
||||||
|
swift: "swift",
|
||||||
|
go: "go",
|
||||||
|
rust: "rs",
|
||||||
|
kotlin: "kt",
|
||||||
|
sql: "sql",
|
||||||
|
shell: "sh",
|
||||||
|
markdown: "md",
|
||||||
|
json: "json",
|
||||||
|
yaml: "yml",
|
||||||
|
xml: "xml",
|
||||||
|
css: "css",
|
||||||
|
scss: "scss",
|
||||||
|
jsx: "jsx",
|
||||||
|
tsx: "tsx",
|
||||||
|
vue: "vue",
|
||||||
|
dart: "dart",
|
||||||
|
lua: "lua"
|
||||||
|
}
|
@ -50,7 +50,7 @@ export default defineConfig({
|
|||||||
outDir: "build",
|
outDir: "build",
|
||||||
|
|
||||||
manifest: {
|
manifest: {
|
||||||
version: "1.3.0",
|
version: "1.3.1",
|
||||||
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