commit
0542b8a6d3
13
src/assets/locale/de/chrome.json
Normal file
13
src/assets/locale/de/chrome.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"heading": "Chrome AI konfigurieren",
|
||||||
|
"status": {
|
||||||
|
"label": "Chrome AI-Unterstützung für Page Assist aktivieren oder deaktivieren"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"browser_not_supported": "Diese Version von Chrome wird vom Gemini Nano-Modell nicht unterstützt. Bitte aktualisieren Sie auf Version 127 oder höher",
|
||||||
|
"ai_not_supported": "Die Einstellung chrome://flags/#prompt-api-for-gemini-nano ist nicht aktiviert. Bitte aktivieren Sie sie.",
|
||||||
|
"ai_not_ready": "Gemini Nano ist noch nicht bereit; Sie müssen die Chrome-Einstellungen überprüfen.",
|
||||||
|
"internal_error": "Ein interner Fehler ist aufgetreten. Bitte versuchen Sie es später erneut."
|
||||||
|
},
|
||||||
|
"errorDescription": "Um Chrome AI zu nutzen, benötigen Sie eine Browserversion höher als 127, die derzeit in den Dev- und Canary-Kanälen verfügbar ist. Nach dem Herunterladen der unterstützten Version folgen Sie diesen Schritten:\n\n1. Gehen Sie zu `chrome://flags/#prompt-api-for-gemini-nano` und wählen Sie \"Aktivieren\".\n2. Gehen Sie zu `chrome://flags/#optimization-guide-on-device-model` und wählen Sie \"EnabledBypassPrefRequirement\".\n3. Gehen Sie zu `chrome://components`, suchen Sie nach \"Optimization Guide On Device Model\" und klicken Sie auf \"Nach Update suchen\". Dies wird das Modell herunterladen. Wenn Sie die Einstellungen nicht sehen, wiederholen Sie die Schritte 1 und 2 und starten Sie Ihren Browser neu."
|
||||||
|
}
|
100
src/assets/locale/de/common.json
Normal file
100
src/assets/locale/de/common.json
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"pageAssist": "Page Assist",
|
||||||
|
"selectAModel": "Modell auswählen",
|
||||||
|
"save": "Speichern",
|
||||||
|
"saved": "Gespeichert",
|
||||||
|
"cancel": "Abbrechen",
|
||||||
|
"retry": "Erneut versuchen",
|
||||||
|
"share": {
|
||||||
|
"tooltip": {
|
||||||
|
"share": "Teilen"
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"title": "Link zum Chat teilen"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"defaultValue": {
|
||||||
|
"name": "Anonym",
|
||||||
|
"title": "Unbenannter Chat"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"label": "Chat-Titel",
|
||||||
|
"placeholder": "Chat-Titel eingeben",
|
||||||
|
"required": "Chat-Titel ist erforderlich"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"label": "Ihr Name",
|
||||||
|
"placeholder": "Geben Sie Ihren Namen ein",
|
||||||
|
"required": "Ihr Name ist erforderlich"
|
||||||
|
},
|
||||||
|
"btn": {
|
||||||
|
"save": "Link generieren",
|
||||||
|
"saving": "Link wird generiert..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"successGenerate": "Link in die Zwischenablage kopiert",
|
||||||
|
"failGenerate": "Link konnte nicht generiert werden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copyToClipboard": "In die Zwischenablage kopieren",
|
||||||
|
"webSearch": "Web durchsuchen",
|
||||||
|
"regenerate": "Neu generieren",
|
||||||
|
"edit": "Bearbeiten",
|
||||||
|
"saveAndSubmit": "Speichern & Absenden",
|
||||||
|
"editMessage": {
|
||||||
|
"placeholder": "Nachricht eingeben..."
|
||||||
|
},
|
||||||
|
"submit": "Absenden",
|
||||||
|
"noData": "Keine Daten",
|
||||||
|
"noHistory": "Kein Chat-Verlauf",
|
||||||
|
"chatWithCurrentPage": "Mit aktueller Seite chatten",
|
||||||
|
"beta": "Beta",
|
||||||
|
"tts": "Vorlesen",
|
||||||
|
"currentChatModelSettings": "Aktuelle Chat-Modell-Einstellungen",
|
||||||
|
"modelSettings": {
|
||||||
|
"label": "Modell-Einstellungen",
|
||||||
|
"description": "Legen Sie die Modelloptionen global für alle Chats fest",
|
||||||
|
"form": {
|
||||||
|
"keepAlive": {
|
||||||
|
"label": "Aktiv halten",
|
||||||
|
"help": "Steuert, wie lange das Modell nach der Anfrage im Speicher geladen bleibt (Standard: 5m)",
|
||||||
|
"placeholder": "Geben Sie die Dauer für Aktiv halten ein (z.B. 5m, 10m, 1h)"
|
||||||
|
},
|
||||||
|
"temperature": {
|
||||||
|
"label": "Temperatur",
|
||||||
|
"placeholder": "Geben Sie den Temperaturwert ein (z.B. 0.7, 1.0)"
|
||||||
|
},
|
||||||
|
"numCtx": {
|
||||||
|
"label": "Anzahl der Kontexte",
|
||||||
|
"placeholder": "Geben Sie die Anzahl der Kontexte ein (Standard: 2048)"
|
||||||
|
},
|
||||||
|
"seed": {
|
||||||
|
"label": "Seed",
|
||||||
|
"placeholder": "Geben Sie den Seed-Wert ein (z.B. 1234)",
|
||||||
|
"help": "Reproduzierbarkeit der Modellausgabe"
|
||||||
|
},
|
||||||
|
"topK": {
|
||||||
|
"label": "Top K",
|
||||||
|
"placeholder": "Geben Sie den Top-K-Wert ein (z.B. 40, 100)"
|
||||||
|
},
|
||||||
|
"topP": {
|
||||||
|
"label": "Top P",
|
||||||
|
"placeholder": "Geben Sie den Top-P-Wert ein (z.B. 0.9, 0.95)"
|
||||||
|
},
|
||||||
|
"numGpu": {
|
||||||
|
"label": "Anzahl GPUs",
|
||||||
|
"placeholder": "Geben Sie die Anzahl der Ebenen ein, die an GPU(s) gesendet werden sollen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"advanced": "Weitere Modell-Einstellungen"
|
||||||
|
},
|
||||||
|
"copilot": {
|
||||||
|
"summary": "Zusammenfassen",
|
||||||
|
"explain": "Erklären",
|
||||||
|
"rephrase": "Umformulieren",
|
||||||
|
"translate": "Übersetzen",
|
||||||
|
"custom": "Benutzerdefiniert"
|
||||||
|
},
|
||||||
|
"citations": "Zitate"
|
||||||
|
}
|
43
src/assets/locale/de/knowledge.json
Normal file
43
src/assets/locale/de/knowledge.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"addBtn": "Neues Wissen hinzufügen",
|
||||||
|
"columns": {
|
||||||
|
"title": "Titel",
|
||||||
|
"status": "Status",
|
||||||
|
"embeddings": "Einbettungsmodell",
|
||||||
|
"createdAt": "Erstellt am",
|
||||||
|
"action": "Aktionen"
|
||||||
|
},
|
||||||
|
"expandedColumns": {
|
||||||
|
"name": "Name"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"delete": "Löschen"
|
||||||
|
},
|
||||||
|
"confirm": {
|
||||||
|
"delete": "Sind Sie sicher, dass Sie dieses Wissen löschen möchten?"
|
||||||
|
},
|
||||||
|
"deleteSuccess": "Wissen erfolgreich gelöscht",
|
||||||
|
"status": {
|
||||||
|
"pending": "Ausstehend",
|
||||||
|
"finished": "Abgeschlossen",
|
||||||
|
"processing": "In Bearbeitung",
|
||||||
|
"failed": "Fehlgeschlagen"
|
||||||
|
},
|
||||||
|
"addKnowledge": "Wissen hinzufügen",
|
||||||
|
"form": {
|
||||||
|
"title": {
|
||||||
|
"label": "Wissenstitel",
|
||||||
|
"placeholder": "Wissenstitel eingeben",
|
||||||
|
"required": "Wissenstitel ist erforderlich"
|
||||||
|
},
|
||||||
|
"uploadFile": {
|
||||||
|
"label": "Datei hochladen",
|
||||||
|
"uploadText": "Ziehen Sie eine Datei hierher oder klicken Sie zum Hochladen",
|
||||||
|
"uploadHint": "Unterstützte Dateitypen: .pdf, .csv, .txt, .md, .docx",
|
||||||
|
"required": "Datei ist erforderlich"
|
||||||
|
},
|
||||||
|
"submit": "Absenden",
|
||||||
|
"success": "Wissen erfolgreich hinzugefügt"
|
||||||
|
},
|
||||||
|
"noEmbeddingModel": "Bitte fügen Sie zuerst ein Einbettungsmodell von der RAG-Einstellungsseite hinzu"
|
||||||
|
}
|
12
src/assets/locale/de/option.json
Normal file
12
src/assets/locale/de/option.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"newChat": "Neuer Chat",
|
||||||
|
"selectAPrompt": "Wähle eine Eingabeaufforderung",
|
||||||
|
"githubRepository": "GitHub-Repository",
|
||||||
|
"settings": "Einstellungen",
|
||||||
|
"sidebarTitle": "Chat-Verlauf",
|
||||||
|
"error": "Fehler",
|
||||||
|
"somethingWentWrong": "Etwas ist schiefgelaufen",
|
||||||
|
"validationSelectModel": "Bitte wähle ein Modell aus, um fortzufahren",
|
||||||
|
"deleteHistoryConfirmation": "Bist du sicher, dass du diesen Verlauf löschen möchtest?",
|
||||||
|
"editHistoryTitle": "Gib einen neuen Titel ein"
|
||||||
|
}
|
29
src/assets/locale/de/playground.json
Normal file
29
src/assets/locale/de/playground.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"ollamaState": {
|
||||||
|
"searching": "Suche nach Ihrem Ollama 🦙",
|
||||||
|
"running": "Ollama läuft 🦙",
|
||||||
|
"notRunning": "Verbindung zu Ollama nicht möglich 🦙",
|
||||||
|
"connectionError": "Es scheint, dass Sie ein Verbindungsproblem haben. Bitte beachten Sie diese <anchor>Dokumentation</anchor> zur Fehlerbehebung."
|
||||||
|
},
|
||||||
|
"formError": {
|
||||||
|
"noModel": "Bitte wählen Sie ein Modell aus",
|
||||||
|
"noEmbeddingModel": "Bitte legen Sie ein Embedding-Modell auf der Seite Einstellungen > RAG fest"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"textarea": {
|
||||||
|
"placeholder": "Nachricht eingeben..."
|
||||||
|
},
|
||||||
|
"webSearch": {
|
||||||
|
"on": "An",
|
||||||
|
"off": "Aus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"searchInternet": "Internet durchsuchen",
|
||||||
|
"speechToText": "Sprache zu Text",
|
||||||
|
"uploadImage": "Bild hochladen",
|
||||||
|
"stopStreaming": "Streaming stoppen",
|
||||||
|
"knowledge": "Wissen"
|
||||||
|
},
|
||||||
|
"sendWhenEnter": "Senden bei Drücken der Eingabetaste"
|
||||||
|
}
|
341
src/assets/locale/de/settings.json
Normal file
341
src/assets/locale/de/settings.json
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
{
|
||||||
|
"generalSettings": {
|
||||||
|
"title": "Allgemeine Einstellungen",
|
||||||
|
"settings": {
|
||||||
|
"heading": "Web-UI-Einstellungen",
|
||||||
|
"speechRecognitionLang": {
|
||||||
|
"label": "Spracherkennungssprache",
|
||||||
|
"placeholder": "Sprache auswählen"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"label": "Sprache",
|
||||||
|
"placeholder": "Sprache auswählen"
|
||||||
|
},
|
||||||
|
"darkMode": {
|
||||||
|
"label": "Design ändern",
|
||||||
|
"options": {
|
||||||
|
"light": "Hell",
|
||||||
|
"dark": "Dunkel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copilotResumeLastChat": {
|
||||||
|
"label": "Letzten Chat beim Öffnen des Seitenpanels fortsetzen (Copilot)"
|
||||||
|
},
|
||||||
|
"hideCurrentChatModelSettings": {
|
||||||
|
"label": "Aktuelle Chat-Modell-Einstellungen ausblenden"
|
||||||
|
},
|
||||||
|
"restoreLastChatModel": {
|
||||||
|
"label": "Zuletzt verwendetes Modell für vorherige Chats wiederherstellen"
|
||||||
|
},
|
||||||
|
"sendNotificationAfterIndexing": {
|
||||||
|
"label": "Benachrichtigung nach Abschluss der Wissensbasis-Verarbeitung senden"
|
||||||
|
},
|
||||||
|
"generateTitle" :{
|
||||||
|
"label": "Titel mit KI generieren"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sidepanelRag": {
|
||||||
|
"heading": "Copilot Chat mit Website-Einstellungen",
|
||||||
|
"ragEnabled": {
|
||||||
|
"label": "Chat mit Website unter Verwendung von Vektor-Embeddings"
|
||||||
|
},
|
||||||
|
"maxWebsiteContext": {
|
||||||
|
"label": "Normaler Modus Website-Inhaltsgröße",
|
||||||
|
"placeholder": "Inhaltsgröße (Standard 4028)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webSearch": {
|
||||||
|
"heading": "Websuche verwalten",
|
||||||
|
"searchMode": {
|
||||||
|
"label": "Einfache Internetsuche durchführen"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"label": "Suchmaschine",
|
||||||
|
"placeholder": "Suchmaschine auswählen"
|
||||||
|
},
|
||||||
|
"totalSearchResults": {
|
||||||
|
"label": "Gesamtanzahl der Suchergebnisse",
|
||||||
|
"placeholder": "Gesamtanzahl der Suchergebnisse eingeben"
|
||||||
|
},
|
||||||
|
"visitSpecificWebsite": {
|
||||||
|
"label": "Die in der Nachricht erwähnte Website besuchen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system": {
|
||||||
|
"heading": "Systemeinstellungen",
|
||||||
|
"deleteChatHistory": {
|
||||||
|
"label": "Chatverlauf löschen",
|
||||||
|
"button": "Löschen",
|
||||||
|
"confirm": "Sind Sie sicher, dass Sie Ihren Chatverlauf löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden."
|
||||||
|
},
|
||||||
|
"export": {
|
||||||
|
"label": "Chatverlauf, Wissensbasis und Prompts exportieren",
|
||||||
|
"button": "Daten exportieren",
|
||||||
|
"success": "Export erfolgreich"
|
||||||
|
},
|
||||||
|
"import": {
|
||||||
|
"label": "Chatverlauf, Wissensbasis und Prompts importieren",
|
||||||
|
"button": "Daten importieren",
|
||||||
|
"success": "Import erfolgreich",
|
||||||
|
"error": "Importfehler"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tts": {
|
||||||
|
"heading": "Text-zu-Sprache-Einstellungen",
|
||||||
|
"ttsEnabled": {
|
||||||
|
"label": "Text-zu-Sprache aktivieren"
|
||||||
|
},
|
||||||
|
"ttsProvider": {
|
||||||
|
"label": "Text-zu-Sprache-Anbieter",
|
||||||
|
"placeholder": "Anbieter auswählen"
|
||||||
|
},
|
||||||
|
"ttsVoice": {
|
||||||
|
"label": "Text-zu-Sprache-Stimme",
|
||||||
|
"placeholder": "Stimme auswählen"
|
||||||
|
},
|
||||||
|
"ssmlEnabled": {
|
||||||
|
"label": "SSML (Speech Synthesis Markup Language) aktivieren"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"manageModels": {
|
||||||
|
"title": "Modelle verwalten",
|
||||||
|
"addBtn": "Neues Modell hinzufügen",
|
||||||
|
"columns": {
|
||||||
|
"name": "Name",
|
||||||
|
"digest": "Digest",
|
||||||
|
"modifiedAt": "Zuletzt geändert",
|
||||||
|
"size": "Größe",
|
||||||
|
"actions": "Aktionen"
|
||||||
|
},
|
||||||
|
"expandedColumns": {
|
||||||
|
"parentModel": "Übergeordnetes Modell",
|
||||||
|
"format": "Format",
|
||||||
|
"family": "Familie",
|
||||||
|
"parameterSize": "Parametergröße",
|
||||||
|
"quantizationLevel": "Quantisierungsstufe"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"delete": "Modell löschen",
|
||||||
|
"repull": "Modell erneut herunterladen"
|
||||||
|
},
|
||||||
|
"confirm": {
|
||||||
|
"delete": "Sind Sie sicher, dass Sie dieses Modell löschen möchten?",
|
||||||
|
"repull": "Sind Sie sicher, dass Sie dieses Modell erneut herunterladen möchten?"
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"title": "Neues Modell hinzufügen",
|
||||||
|
"placeholder": "Modellnamen eingeben",
|
||||||
|
"pull": "Modell herunterladen"
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"pullModel": "Modell wird heruntergeladen",
|
||||||
|
"pullModelDescription": "Das Modell {{modelName}} wird heruntergeladen. Weitere Details finden Sie im Erweiterungssymbol.",
|
||||||
|
"success": "Erfolgreich",
|
||||||
|
"error": "Fehler",
|
||||||
|
"successDescription": "Das Modell wurde erfolgreich heruntergeladen",
|
||||||
|
"successDeleteDescription": "Das Modell wurde erfolgreich gelöscht",
|
||||||
|
"someError": "Etwas ist schiefgelaufen. Bitte versuchen Sie es später erneut"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"managePrompts": {
|
||||||
|
"title": "Prompts verwalten",
|
||||||
|
"addBtn": "Neuen Prompt hinzufügen",
|
||||||
|
"option1": "Normal",
|
||||||
|
"option2": "RAG",
|
||||||
|
"questionPrompt": "Frage-Prompt",
|
||||||
|
"segmented": {
|
||||||
|
"custom": "Benutzerdefinierte Prompts",
|
||||||
|
"copilot": "Copilot-Prompts"
|
||||||
|
},
|
||||||
|
"columns": {
|
||||||
|
"title": "Titel",
|
||||||
|
"prompt": "Prompt",
|
||||||
|
"type": "Prompt-Typ",
|
||||||
|
"actions": "Aktionen"
|
||||||
|
},
|
||||||
|
"systemPrompt": "System-Prompt",
|
||||||
|
"quickPrompt": "Schnell-Prompt",
|
||||||
|
"tooltip": {
|
||||||
|
"delete": "Prompt löschen",
|
||||||
|
"edit": "Prompt bearbeiten"
|
||||||
|
},
|
||||||
|
"confirm": {
|
||||||
|
"delete": "Sind Sie sicher, dass Sie diesen Prompt löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden."
|
||||||
|
},
|
||||||
|
"modal": {
|
||||||
|
"addTitle": "Neuen Prompt hinzufügen",
|
||||||
|
"editTitle": "Prompt bearbeiten"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"title": {
|
||||||
|
"label": "Titel",
|
||||||
|
"placeholder": "Mein toller Prompt",
|
||||||
|
"required": "Bitte geben Sie einen Titel ein"
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"label": "Prompt",
|
||||||
|
"placeholder": "Prompt eingeben",
|
||||||
|
"required": "Bitte geben Sie einen Prompt ein",
|
||||||
|
"help": "Sie können {key} als Variable in Ihrem Prompt verwenden.",
|
||||||
|
"missingTextPlaceholder": "Die Variable {text} fehlt im Prompt. Bitte fügen Sie sie hinzu."
|
||||||
|
},
|
||||||
|
"isSystem": {
|
||||||
|
"label": "Ist System-Prompt"
|
||||||
|
},
|
||||||
|
"btnSave": {
|
||||||
|
"saving": "Prompt wird hinzugefügt...",
|
||||||
|
"save": "Prompt hinzufügen"
|
||||||
|
},
|
||||||
|
"btnEdit": {
|
||||||
|
"saving": "Prompt wird aktualisiert...",
|
||||||
|
"save": "Prompt aktualisieren"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"addSuccess": "Prompt hinzugefügt",
|
||||||
|
"addSuccessDesc": "Prompt wurde erfolgreich hinzugefügt",
|
||||||
|
"error": "Fehler",
|
||||||
|
"someError": "Etwas ist schiefgelaufen. Bitte versuchen Sie es später erneut",
|
||||||
|
"updatedSuccess": "Prompt aktualisiert",
|
||||||
|
"updatedSuccessDesc": "Prompt wurde erfolgreich aktualisiert",
|
||||||
|
"deletedSuccess": "Prompt gelöscht",
|
||||||
|
"deletedSuccessDesc": "Prompt wurde erfolgreich gelöscht"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"manageShare": {
|
||||||
|
"title": "Freigabe verwalten",
|
||||||
|
"heading": "Seiten-Freigabe-URL konfigurieren",
|
||||||
|
"form": {
|
||||||
|
"url": {
|
||||||
|
"label": "Seiten-Freigabe-URL",
|
||||||
|
"placeholder": "Seiten-Freigabe-URL eingeben",
|
||||||
|
"required": "Bitte geben Sie Ihre Seiten-Freigabe-URL ein!",
|
||||||
|
"help": "Aus Datenschutzgründen können Sie die Seitenfreigabe selbst hosten und die URL hier angeben. <anchor>Mehr erfahren</anchor>."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webshare": {
|
||||||
|
"heading": "Web-Freigabe",
|
||||||
|
"columns": {
|
||||||
|
"title": "Titel",
|
||||||
|
"url": "URL",
|
||||||
|
"actions": "Aktionen"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"delete": "Freigabe löschen"
|
||||||
|
},
|
||||||
|
"confirm": {
|
||||||
|
"delete": "Sind Sie sicher, dass Sie diese Freigabe löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden."
|
||||||
|
},
|
||||||
|
"label": "Seitenfreigabe verwalten",
|
||||||
|
"description": "Seitenfreigabe-Funktion aktivieren oder deaktivieren"
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"pageShareSuccess": "Seiten-Freigabe-URL erfolgreich aktualisiert",
|
||||||
|
"someError": "Etwas ist schiefgelaufen. Bitte versuchen Sie es später erneut",
|
||||||
|
"webShareDeleteSuccess": "Web-Freigabe erfolgreich gelöscht"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ollamaSettings": {
|
||||||
|
"title": "Ollama-Einstellungen",
|
||||||
|
"heading": "Ollama konfigurieren",
|
||||||
|
"settings": {
|
||||||
|
"ollamaUrl": {
|
||||||
|
"label": "Ollama-URL",
|
||||||
|
"placeholder": "Ollama-URL eingeben"
|
||||||
|
},
|
||||||
|
"advanced": {
|
||||||
|
"label": "Erweiterte Ollama-URL-Konfiguration",
|
||||||
|
"urlRewriteEnabled": {
|
||||||
|
"label": "Benutzerdefinierte Ursprungs-URL aktivieren oder deaktivieren"
|
||||||
|
},
|
||||||
|
"rewriteUrl": {
|
||||||
|
"label": "Benutzerdefinierte Ursprungs-URL",
|
||||||
|
"placeholder": "Benutzerdefinierte Ursprungs-URL eingeben"
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "Benutzerdefinierte Header",
|
||||||
|
"add": "Header hinzufügen",
|
||||||
|
"key": {
|
||||||
|
"label": "Header-Schlüssel",
|
||||||
|
"placeholder": "Autorisierung"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Header-Wert",
|
||||||
|
"placeholder": "Bearer-Token"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"help": "Wenn Sie Verbindungsprobleme mit Ollama auf Page Assist haben, können Sie eine benutzerdefinierte Ursprungs-URL konfigurieren. Um mehr über die Konfiguration zu erfahren, <anchor>klicken Sie hier</anchor>."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"manageSearch": {
|
||||||
|
"title": "Web-Suche verwalten",
|
||||||
|
"heading": "Web-Suche konfigurieren"
|
||||||
|
},
|
||||||
|
"about": {
|
||||||
|
"title": "Über",
|
||||||
|
"heading": "Über",
|
||||||
|
"chromeVersion": "Page Assist Version",
|
||||||
|
"ollamaVersion": "Ollama Version",
|
||||||
|
"support": "Sie können das Page Assist-Projekt durch Spenden oder Sponsoring über die folgenden Plattformen unterstützen:",
|
||||||
|
"koFi": "Unterstützen Sie uns auf Ko-fi",
|
||||||
|
"githubSponsor": "Sponsern Sie uns auf GitHub",
|
||||||
|
"githubRepo": "GitHub-Repository"
|
||||||
|
},
|
||||||
|
"manageKnowledge": {
|
||||||
|
"title": "Wissen verwalten",
|
||||||
|
"heading": "Wissensbasis konfigurieren"
|
||||||
|
},
|
||||||
|
"rag": {
|
||||||
|
"title": "RAG-Einstellungen",
|
||||||
|
"ragSettings": {
|
||||||
|
"label": "RAG-Einstellungen",
|
||||||
|
"model": {
|
||||||
|
"label": "Embedding-Modell",
|
||||||
|
"required": "Bitte wählen Sie ein Modell aus",
|
||||||
|
"help": "Es wird dringend empfohlen, Embedding-Modelle wie `nomic-embed-text` zu verwenden.",
|
||||||
|
"placeholder": "Wählen Sie ein Modell aus"
|
||||||
|
},
|
||||||
|
"chunkSize": {
|
||||||
|
"label": "Chunk-Größe",
|
||||||
|
"placeholder": "Chunk-Größe eingeben",
|
||||||
|
"required": "Bitte geben Sie eine Chunk-Größe ein"
|
||||||
|
},
|
||||||
|
"chunkOverlap": {
|
||||||
|
"label": "Chunk-Überlappung",
|
||||||
|
"placeholder": "Chunk-Überlappung eingeben",
|
||||||
|
"required": "Bitte geben Sie eine Chunk-Überlappung ein"
|
||||||
|
},
|
||||||
|
"totalFilePerKB": {
|
||||||
|
"label": "Standard-Datei-Upload-Limit für die Wissensbasis",
|
||||||
|
"placeholder": "Geben Sie das Standard-Datei-Upload-Limit ein (z.B. 10)",
|
||||||
|
"required": "Bitte geben Sie das Standard-Datei-Upload-Limit ein"
|
||||||
|
},
|
||||||
|
"noOfRetrievedDocs": {
|
||||||
|
"label": "Anzahl der abgerufenen Dokumente",
|
||||||
|
"placeholder": "Anzahl der abgerufenen Dokumente eingeben",
|
||||||
|
"required": "Bitte geben Sie die Anzahl der abgerufenen Dokumente ein"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"label": "RAG-Prompt konfigurieren",
|
||||||
|
"option1": "Normal",
|
||||||
|
"option2": "Web",
|
||||||
|
"alert": "Die Konfiguration des System-Prompts hier ist veraltet. Bitte verwenden Sie den Abschnitt 'Prompts verwalten', um Prompts hinzuzufügen oder zu bearbeiten. Dieser Abschnitt wird in einer zukünftigen Version entfernt",
|
||||||
|
"systemPrompt": "System-Prompt",
|
||||||
|
"systemPromptPlaceholder": "System-Prompt eingeben",
|
||||||
|
"webSearchPrompt": "Web-Suche-Prompt",
|
||||||
|
"webSearchPromptHelp": "Entfernen Sie `{search_results}` nicht aus dem Prompt.",
|
||||||
|
"webSearchPromptError": "Bitte geben Sie einen Web-Suche-Prompt ein",
|
||||||
|
"webSearchPromptPlaceholder": "Web-Suche-Prompt eingeben",
|
||||||
|
"webSearchFollowUpPrompt": "Web-Suche-Folgeprompt",
|
||||||
|
"webSearchFollowUpPromptHelp": "Entfernen Sie `{chat_history}` und `{question}` nicht aus dem Prompt.",
|
||||||
|
"webSearchFollowUpPromptError": "Bitte geben Sie Ihren Web-Suche-Folgeprompt ein!",
|
||||||
|
"webSearchFollowUpPromptPlaceholder": "Ihr Web-Suche-Folgeprompt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chromeAiSettings": {
|
||||||
|
"title": "Chrome AI-Einstellungen"
|
||||||
|
}
|
||||||
|
}
|
7
src/assets/locale/de/sidepanel.json
Normal file
7
src/assets/locale/de/sidepanel.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"tooltip": {
|
||||||
|
"embed": "Es kann einige Minuten dauern, die Seite einzubetten. Bitte warten Sie...",
|
||||||
|
"clear": "Chatverlauf löschen",
|
||||||
|
"history": "Chatverlauf"
|
||||||
|
}
|
||||||
|
}
|
@ -95,5 +95,6 @@
|
|||||||
"rephrase": "Rephrase",
|
"rephrase": "Rephrase",
|
||||||
"translate": "Translate",
|
"translate": "Translate",
|
||||||
"custom": "Custom"
|
"custom": "Custom"
|
||||||
}
|
},
|
||||||
|
"citations": "Citations"
|
||||||
}
|
}
|
@ -94,5 +94,6 @@
|
|||||||
"explain": "Explicar",
|
"explain": "Explicar",
|
||||||
"rephrase": "Reformular",
|
"rephrase": "Reformular",
|
||||||
"translate": "Traducir"
|
"translate": "Traducir"
|
||||||
}
|
},
|
||||||
|
"citations": "Citas"
|
||||||
}
|
}
|
@ -88,5 +88,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"advanced": "تنظیمات بیشتر مدل"
|
"advanced": "تنظیمات بیشتر مدل"
|
||||||
}
|
},
|
||||||
|
"citations": "منابع"
|
||||||
}
|
}
|
@ -94,5 +94,6 @@
|
|||||||
"explain": "Expliquer",
|
"explain": "Expliquer",
|
||||||
"rephrase": "Reformuler",
|
"rephrase": "Reformuler",
|
||||||
"translate": "Traduire"
|
"translate": "Traduire"
|
||||||
}
|
},
|
||||||
|
"citations": "Citations"
|
||||||
}
|
}
|
@ -93,5 +93,6 @@
|
|||||||
"explain": "Spiegare",
|
"explain": "Spiegare",
|
||||||
"rephrase": "Riformulare",
|
"rephrase": "Riformulare",
|
||||||
"translate": "Tradurre"
|
"translate": "Tradurre"
|
||||||
}
|
},
|
||||||
|
"citations": "Citazioni"
|
||||||
}
|
}
|
@ -94,5 +94,6 @@
|
|||||||
"explain": "説明",
|
"explain": "説明",
|
||||||
"rephrase": "言い換え",
|
"rephrase": "言い換え",
|
||||||
"translate": "翻訳"
|
"translate": "翻訳"
|
||||||
}
|
},
|
||||||
|
"citations": "引用"
|
||||||
}
|
}
|
@ -93,5 +93,6 @@
|
|||||||
"explain": "വിശദീകരിക്കുക",
|
"explain": "വിശദീകരിക്കുക",
|
||||||
"rephrase": "പുനഃരൂപീകരിക്കുക",
|
"rephrase": "പുനഃരൂപീകരിക്കുക",
|
||||||
"translate": "വിവർത്തനം ചെയ്യുക"
|
"translate": "വിവർത്തനം ചെയ്യുക"
|
||||||
}
|
},
|
||||||
|
"citations": "ഉദ്ധരണികൾ"
|
||||||
}
|
}
|
@ -94,5 +94,6 @@
|
|||||||
"explain": "Explicar",
|
"explain": "Explicar",
|
||||||
"rephrase": "Reformular",
|
"rephrase": "Reformular",
|
||||||
"translate": "Traduzir"
|
"translate": "Traduzir"
|
||||||
}
|
},
|
||||||
|
"citations": "Citações"
|
||||||
}
|
}
|
@ -93,5 +93,6 @@
|
|||||||
"explain": "Объяснить",
|
"explain": "Объяснить",
|
||||||
"rephrase": "Перефразировать",
|
"rephrase": "Перефразировать",
|
||||||
"translate": "Перевести"
|
"translate": "Перевести"
|
||||||
}
|
},
|
||||||
|
"citations": "Цитаты"
|
||||||
}
|
}
|
@ -94,5 +94,6 @@
|
|||||||
"explain": "解释",
|
"explain": "解释",
|
||||||
"rephrase": "重述",
|
"rephrase": "重述",
|
||||||
"translate": "翻译"
|
"translate": "翻译"
|
||||||
}
|
},
|
||||||
|
"citations": "引用"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import Markdown from "../../Common/Markdown"
|
import Markdown from "../../Common/Markdown"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { Tag, Image, Tooltip } from "antd"
|
import { Tag, Image, Tooltip, Collapse } from "antd"
|
||||||
import { WebSearch } from "./WebSearch"
|
import { WebSearch } from "./WebSearch"
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
@ -127,15 +127,31 @@ export const PlaygroundMessage = (props: Props) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{props.isBot && props?.sources && props?.sources.length > 0 && (
|
{props.isBot && props?.sources && props?.sources.length > 0 && (
|
||||||
<div className="mb-3 flex flex-wrap gap-2">
|
<Collapse
|
||||||
{props?.sources?.map((source, index) => (
|
className="mt-6"
|
||||||
<MessageSource
|
ghost
|
||||||
onSourceClick={props.onSourceClick}
|
items={[
|
||||||
key={index}
|
{
|
||||||
source={source}
|
key: "1",
|
||||||
/>
|
label: (
|
||||||
))}
|
<div className="italic text-gray-500 dark:text-gray-400">
|
||||||
</div>
|
{t('citations')}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
children: (
|
||||||
|
<div className="mb-3 flex flex-wrap gap-2">
|
||||||
|
{props?.sources?.map((source, index) => (
|
||||||
|
<MessageSource
|
||||||
|
onSourceClick={props.onSourceClick}
|
||||||
|
key={index}
|
||||||
|
source={source}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{!props.isProcessing && !editMode && (
|
{!props.isProcessing && !editMode && (
|
||||||
<div
|
<div
|
||||||
|
@ -9,6 +9,7 @@ import { getPageShareUrl } from "~/services/ollama"
|
|||||||
import { cleanUrl } from "~/libs/clean-url"
|
import { cleanUrl } from "~/libs/clean-url"
|
||||||
import { getUserId, saveWebshare } from "@/db"
|
import { getUserId, saveWebshare } from "@/db"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
import fetcher from "@/libs/fetcher"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
messages: Message[]
|
messages: Message[]
|
||||||
@ -94,7 +95,7 @@ export const ShareBtn: React.FC<Props> = ({ messages }) => {
|
|||||||
const chat = reformatMessages(messages, values.name)
|
const chat = reformatMessages(messages, values.name)
|
||||||
const title = values.title
|
const title = values.title
|
||||||
const url = await getPageShareUrl()
|
const url = await getPageShareUrl()
|
||||||
const res = await fetch(`${cleanUrl(url)}/api/v1/share/create`, {
|
const res = await fetcher(`${cleanUrl(url)}/api/v1/share/create`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
@ -14,6 +14,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { KnowledgeSelect } from "../Knowledge/KnowledgeSelect"
|
import { KnowledgeSelect } from "../Knowledge/KnowledgeSelect"
|
||||||
import { useSpeechRecognition } from "@/hooks/useSpeechRecognition"
|
import { useSpeechRecognition } from "@/hooks/useSpeechRecognition"
|
||||||
import { PiGlobe } from "react-icons/pi"
|
import { PiGlobe } from "react-icons/pi"
|
||||||
|
import { handleChatInputKeyDown } from "@/utils/key-down"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dropedFile: File | undefined
|
dropedFile: File | undefined
|
||||||
@ -144,13 +145,16 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||||
if (e.key === "Process" || e.key === "229") return
|
if (import.meta.env.BROWSER !== "firefox") {
|
||||||
|
if (e.key === "Process" || e.key === "229") return
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
!typing &&
|
handleChatInputKeyDown({
|
||||||
e.key === "Enter" &&
|
e,
|
||||||
!e.shiftKey &&
|
sendWhenEnter,
|
||||||
!isSending &&
|
typing,
|
||||||
sendWhenEnter
|
isSending
|
||||||
|
})
|
||||||
) {
|
) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
stopListening()
|
stopListening()
|
||||||
@ -244,8 +248,16 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<div className="w-full border-x border-t flex flex-col dark:border-gray-600 rounded-t-xl p-2">
|
<div className="w-full border-x border-t flex flex-col dark:border-gray-600 rounded-t-xl p-2">
|
||||||
<textarea
|
<textarea
|
||||||
onCompositionStart={() => setTyping(true)}
|
onCompositionStart={() => {
|
||||||
onCompositionEnd={() => setTyping(false)}
|
if (import.meta.env.BROWSER !== "firefox") {
|
||||||
|
setTyping(true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onCompositionEnd={() => {
|
||||||
|
if (import.meta.env.BROWSER !== "firefox") {
|
||||||
|
setTyping(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
onKeyDown={(e) => handleKeyDown(e)}
|
onKeyDown={(e) => handleKeyDown(e)}
|
||||||
ref={textareaRef}
|
ref={textareaRef}
|
||||||
className="px-2 py-2 w-full resize-none bg-transparent focus-within:outline-none focus:ring-0 focus-visible:ring-0 ring-0 dark:ring-0 border-0 dark:text-gray-100"
|
className="px-2 py-2 w-full resize-none bg-transparent focus-within:outline-none focus:ring-0 focus-visible:ring-0 ring-0 dark:ring-0 border-0 dark:text-gray-100"
|
||||||
|
@ -4,6 +4,7 @@ import { useQuery } from "@tanstack/react-query"
|
|||||||
import { Skeleton } from "antd"
|
import { Skeleton } from "antd"
|
||||||
import { cleanUrl } from "@/libs/clean-url"
|
import { cleanUrl } from "@/libs/clean-url"
|
||||||
import { Descriptions } from "antd"
|
import { Descriptions } from "antd"
|
||||||
|
import fetcher from "@/libs/fetcher"
|
||||||
|
|
||||||
export const AboutApp = () => {
|
export const AboutApp = () => {
|
||||||
const { t } = useTranslation("settings")
|
const { t } = useTranslation("settings")
|
||||||
@ -14,7 +15,7 @@ export const AboutApp = () => {
|
|||||||
const chromeVersion = browser.runtime.getManifest().version
|
const chromeVersion = browser.runtime.getManifest().version
|
||||||
try {
|
try {
|
||||||
const url = await getOllamaURL()
|
const url = await getOllamaURL()
|
||||||
const req = await fetch(`${cleanUrl(url)}/api/version`)
|
const req = await fetcher(`${cleanUrl(url)}/api/version`)
|
||||||
|
|
||||||
if (!req.ok) {
|
if (!req.ok) {
|
||||||
return {
|
return {
|
||||||
@ -75,11 +76,11 @@ export const AboutApp = () => {
|
|||||||
label: "X (formerly Twitter)",
|
label: "X (formerly Twitter)",
|
||||||
children: (
|
children: (
|
||||||
<a
|
<a
|
||||||
href="https://twitter.com/n4ze3m"
|
href="https://twitter.com/page_assist"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="text-blue-500 dark:text-blue-400">
|
className="text-blue-500 dark:text-blue-400">
|
||||||
@n4ze3m
|
@page_assist
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,13 @@ import {
|
|||||||
import { useStorage } from "@plasmohq/storage/hook"
|
import { useStorage } from "@plasmohq/storage/hook"
|
||||||
|
|
||||||
export const GeneralSettings = () => {
|
export const GeneralSettings = () => {
|
||||||
const { clearChat, speechToTextLanguage, setSpeechToTextLanguage } =
|
const { clearChat } =
|
||||||
useMessageOption()
|
useMessageOption()
|
||||||
|
|
||||||
|
const [ speechToTextLanguage, setSpeechToTextLanguage ] = useStorage(
|
||||||
|
"speechToTextLanguage",
|
||||||
|
"en-US"
|
||||||
|
)
|
||||||
const [copilotResumeLastChat, setCopilotResumeLastChat] = useStorage(
|
const [copilotResumeLastChat, setCopilotResumeLastChat] = useStorage(
|
||||||
"copilotResumeLastChat",
|
"copilotResumeLastChat",
|
||||||
false
|
false
|
||||||
|
@ -7,6 +7,7 @@ import { deleteWebshare, getAllWebshares, getUserId } from "@/db"
|
|||||||
import { getPageShareUrl, setPageShareUrl } from "~/services/ollama"
|
import { getPageShareUrl, setPageShareUrl } from "~/services/ollama"
|
||||||
import { verifyPageShareURL } from "~/utils/verify-page-share"
|
import { verifyPageShareURL } from "~/utils/verify-page-share"
|
||||||
import { useStorage } from "@plasmohq/storage/hook"
|
import { useStorage } from "@plasmohq/storage/hook"
|
||||||
|
import fetcher from "@/libs/fetcher"
|
||||||
|
|
||||||
export const OptionShareBody = () => {
|
export const OptionShareBody = () => {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@ -48,7 +49,7 @@ export const OptionShareBody = () => {
|
|||||||
api_url: string
|
api_url: string
|
||||||
}) => {
|
}) => {
|
||||||
const owner_id = await getUserId()
|
const owner_id = await getUserId()
|
||||||
const res = await fetch(`${api_url}/api/v1/share/delete`, {
|
const res = await fetcher(`${api_url}/api/v1/share/delete`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
@ -12,6 +12,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { ModelSelect } from "@/components/Common/ModelSelect"
|
import { ModelSelect } from "@/components/Common/ModelSelect"
|
||||||
import { useSpeechRecognition } from "@/hooks/useSpeechRecognition"
|
import { useSpeechRecognition } from "@/hooks/useSpeechRecognition"
|
||||||
import { PiGlobeX, PiGlobe } from "react-icons/pi"
|
import { PiGlobeX, PiGlobe } from "react-icons/pi"
|
||||||
|
import { handleChatInputKeyDown } from "@/utils/key-down"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dropedFile: File | undefined
|
dropedFile: File | undefined
|
||||||
@ -66,11 +67,12 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
|
|||||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||||
if (e.key === "Process" || e.key === "229") return
|
if (e.key === "Process" || e.key === "229") return
|
||||||
if (
|
if (
|
||||||
e.key === "Enter" &&
|
handleChatInputKeyDown({
|
||||||
!e.shiftKey &&
|
e,
|
||||||
!isSending &&
|
sendWhenEnter,
|
||||||
sendWhenEnter &&
|
typing,
|
||||||
!typing
|
isSending
|
||||||
|
})
|
||||||
) {
|
) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
form.onSubmit(async (value) => {
|
form.onSubmit(async (value) => {
|
||||||
@ -245,8 +247,16 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
|
|||||||
rows={1}
|
rows={1}
|
||||||
style={{ minHeight: "60px" }}
|
style={{ minHeight: "60px" }}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onCompositionStart={() => setTyping(true)}
|
onCompositionStart={() => {
|
||||||
onCompositionEnd={() => setTyping(false)}
|
if (import.meta.env.BROWSER !== "firefox") {
|
||||||
|
setTyping(true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onCompositionEnd={() => {
|
||||||
|
if (import.meta.env.BROWSER !== "firefox") {
|
||||||
|
setTyping(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
placeholder={t("form.textarea.placeholder")}
|
placeholder={t("form.textarea.placeholder")}
|
||||||
{...form.getInputProps("message")}
|
{...form.getInputProps("message")}
|
||||||
/>
|
/>
|
||||||
|
@ -53,7 +53,10 @@ export const SettingsBody = () => {
|
|||||||
const [hideCurrentChatModelSettings, setHideCurrentChatModelSettings] =
|
const [hideCurrentChatModelSettings, setHideCurrentChatModelSettings] =
|
||||||
useStorage("hideCurrentChatModelSettings", false)
|
useStorage("hideCurrentChatModelSettings", false)
|
||||||
|
|
||||||
const { speechToTextLanguage, setSpeechToTextLanguage } = useMessage()
|
const [ speechToTextLanguage, setSpeechToTextLanguage ] = useStorage(
|
||||||
|
"speechToTextLanguage",
|
||||||
|
"en-US"
|
||||||
|
)
|
||||||
const { mode, toggleDarkMode } = useDarkMode()
|
const { mode, toggleDarkMode } = useDarkMode()
|
||||||
|
|
||||||
const { changeLocale, locale, supportLanguage } = useI18n()
|
const { changeLocale, locale, supportLanguage } = useI18n()
|
||||||
|
@ -74,8 +74,6 @@ export const useMessage = () => {
|
|||||||
setChatMode,
|
setChatMode,
|
||||||
setIsEmbedding,
|
setIsEmbedding,
|
||||||
isEmbedding,
|
isEmbedding,
|
||||||
speechToTextLanguage,
|
|
||||||
setSpeechToTextLanguage,
|
|
||||||
currentURL,
|
currentURL,
|
||||||
setCurrentURL
|
setCurrentURL
|
||||||
} = useStoreMessage()
|
} = useStoreMessage()
|
||||||
@ -1230,8 +1228,6 @@ export const useMessage = () => {
|
|||||||
chatMode,
|
chatMode,
|
||||||
setChatMode,
|
setChatMode,
|
||||||
isEmbedding,
|
isEmbedding,
|
||||||
speechToTextLanguage,
|
|
||||||
setSpeechToTextLanguage,
|
|
||||||
regenerateLastMessage,
|
regenerateLastMessage,
|
||||||
webSearch,
|
webSearch,
|
||||||
setWebSearch,
|
setWebSearch,
|
||||||
|
@ -10,6 +10,7 @@ import { ja } from "./lang/ja";
|
|||||||
import { it } from "./lang/it";
|
import { it } from "./lang/it";
|
||||||
import { es } from "./lang/es";
|
import { es } from "./lang/es";
|
||||||
import { fa } from "./lang/fa";
|
import { fa } from "./lang/fa";
|
||||||
|
import { de } from "./lang/de";
|
||||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
@ -30,7 +31,8 @@ i18n
|
|||||||
ja: ja,
|
ja: ja,
|
||||||
"ja-JP": ja,
|
"ja-JP": ja,
|
||||||
fa: fa,
|
fa: fa,
|
||||||
"fa-IR": fa
|
"fa-IR": fa,
|
||||||
|
de: de
|
||||||
},
|
},
|
||||||
fallbackLng: "en",
|
fallbackLng: "en",
|
||||||
lng: localStorage.getItem("i18nextLng") || "en",
|
lng: localStorage.getItem("i18nextLng") || "en",
|
||||||
|
17
src/i18n/lang/de.ts
Normal file
17
src/i18n/lang/de.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import option from "@/assets/locale/de/option.json";
|
||||||
|
import playground from "@/assets/locale/de/playground.json";
|
||||||
|
import common from "@/assets/locale/de/common.json";
|
||||||
|
import sidepanel from "@/assets/locale/de/sidepanel.json";
|
||||||
|
import settings from "@/assets/locale/de/settings.json";
|
||||||
|
import knowledge from "@/assets/locale/de/knowledge.json";
|
||||||
|
import chrome from "@/assets/locale/de/chrome.json";
|
||||||
|
|
||||||
|
export const de = {
|
||||||
|
option,
|
||||||
|
playground,
|
||||||
|
common,
|
||||||
|
sidepanel,
|
||||||
|
settings,
|
||||||
|
knowledge,
|
||||||
|
chrome
|
||||||
|
}
|
@ -39,5 +39,9 @@ export const supportLanguage = [
|
|||||||
{
|
{
|
||||||
label: "فارسی",
|
label: "فارسی",
|
||||||
value: "fa"
|
value: "fa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Deutsch",
|
||||||
|
value: "de"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
14
src/libs/fetcher.ts
Normal file
14
src/libs/fetcher.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { getCustomOllamaHeaders } from "@/services/app"
|
||||||
|
|
||||||
|
|
||||||
|
const fetcher = async (input: string | URL | globalThis.Request, init?: RequestInit) : Promise<Response> => {
|
||||||
|
const update = {...init} || {}
|
||||||
|
const customHeaders = await getCustomOllamaHeaders()
|
||||||
|
update.headers = {
|
||||||
|
...customHeaders,
|
||||||
|
...update?.headers
|
||||||
|
}
|
||||||
|
return fetch(input, update)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default fetcher
|
@ -10,19 +10,8 @@ import {
|
|||||||
import { BaseMessage, AIMessageChunk } from "@langchain/core/messages"
|
import { BaseMessage, AIMessageChunk } from "@langchain/core/messages"
|
||||||
import { ChatGenerationChunk } from "@langchain/core/outputs"
|
import { ChatGenerationChunk } from "@langchain/core/outputs"
|
||||||
import { IterableReadableStream } from "@langchain/core/utils/stream"
|
import { IterableReadableStream } from "@langchain/core/utils/stream"
|
||||||
|
import { AITextSession, checkChromeAIAvailability, createAITextSession } from "./utils/chrome"
|
||||||
|
|
||||||
export interface AI {
|
|
||||||
canCreateTextSession(): Promise<AIModelAvailability>
|
|
||||||
createTextSession(options?: AITextSessionOptions): Promise<AITextSession>
|
|
||||||
defaultTextSessionOptions(): Promise<AITextSessionOptions>
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AITextSession {
|
|
||||||
prompt(input: string): Promise<string>
|
|
||||||
promptStreaming(input: string): ReadableStream
|
|
||||||
destroy(): void
|
|
||||||
clone(): AITextSession
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AITextSessionOptions {
|
export interface AITextSessionOptions {
|
||||||
topK: number
|
topK: number
|
||||||
@ -44,16 +33,12 @@ export interface ChromeAIInputs extends BaseChatModelParams {
|
|||||||
promptFormatter?: (messages: BaseMessage[]) => string
|
promptFormatter?: (messages: BaseMessage[]) => string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChromeAICallOptions extends BaseLanguageModelCallOptions {}
|
export interface ChromeAICallOptions extends BaseLanguageModelCallOptions { }
|
||||||
|
|
||||||
function formatPrompt(messages: BaseMessage[]): string {
|
function formatPrompt(messages: BaseMessage[]): string {
|
||||||
return messages
|
return messages
|
||||||
.map((message) => {
|
.map((message) => {
|
||||||
if (typeof message.content !== "string") {
|
if (typeof message.content !== "string") {
|
||||||
// console.log(message.content)
|
|
||||||
// throw new Error(
|
|
||||||
// "ChatChromeAI does not support non-string message content."
|
|
||||||
// )
|
|
||||||
if (message.content.length > 0) {
|
if (message.content.length > 0) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
return message.content[0]?.text || ""
|
return message.content[0]?.text || ""
|
||||||
@ -66,31 +51,12 @@ function formatPrompt(messages: BaseMessage[]): string {
|
|||||||
.join("\n")
|
.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* To use this model you need to have the `Built-in AI Early Preview Program`
|
|
||||||
* for Chrome. You can find more information about the program here:
|
|
||||||
* @link https://developer.chrome.com/docs/ai/built-in
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* // Initialize the ChatChromeAI model.
|
|
||||||
* const model = new ChatChromeAI({
|
|
||||||
* temperature: 0.5, // Optional. Default is 0.5.
|
|
||||||
* topK: 40, // Optional. Default is 40.
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* // Call the model with a message and await the response.
|
|
||||||
* const response = await model.invoke([
|
|
||||||
* new HumanMessage({ content: "My name is John." }),
|
|
||||||
* ]);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export class ChatChromeAI extends SimpleChatModel<ChromeAICallOptions> {
|
export class ChatChromeAI extends SimpleChatModel<ChromeAICallOptions> {
|
||||||
session?: AITextSession
|
session?: AITextSession
|
||||||
|
|
||||||
temperature = 0.5
|
temperature = 0.8
|
||||||
|
|
||||||
topK = 40
|
topK = 120
|
||||||
|
|
||||||
promptFormatter: (messages: BaseMessage[]) => string
|
promptFormatter: (messages: BaseMessage[]) => string
|
||||||
|
|
||||||
@ -120,15 +86,14 @@ export class ChatChromeAI extends SimpleChatModel<ChromeAICallOptions> {
|
|||||||
throw new Error("ChatChromeAI can only be used in the browser.")
|
throw new Error("ChatChromeAI can only be used in the browser.")
|
||||||
}
|
}
|
||||||
|
|
||||||
const { ai } = window as any
|
const canCreateTextSession = await checkChromeAIAvailability()
|
||||||
const canCreateTextSession = await ai.canCreateTextSession()
|
|
||||||
if (canCreateTextSession === AIModelAvailability.No) {
|
if (canCreateTextSession === AIModelAvailability.No) {
|
||||||
throw new Error("The AI model is not available.")
|
throw new Error("The AI model is not available.")
|
||||||
} else if (canCreateTextSession === AIModelAvailability.AfterDownload) {
|
} else if (canCreateTextSession === AIModelAvailability.AfterDownload) {
|
||||||
throw new Error("The AI model is not yet downloaded.")
|
throw new Error("The AI model is not yet downloaded.")
|
||||||
}
|
}
|
||||||
|
|
||||||
this.session = await ai.createTextSession({
|
this.session = await createAITextSession({
|
||||||
topK: this.topK,
|
topK: this.topK,
|
||||||
temperature: this.temperature
|
temperature: this.temperature
|
||||||
})
|
})
|
||||||
|
54
src/models/utils/chrome.ts
Normal file
54
src/models/utils/chrome.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
export const checkChromeAIAvailability = async (): Promise<"readily" | "no" | "after-download"> => {
|
||||||
|
try {
|
||||||
|
const ai = (window as any).ai;
|
||||||
|
|
||||||
|
// upcoming version change
|
||||||
|
if (ai?.assistant?.capabilities) {
|
||||||
|
const capabilities = await ai.assistant.capabilities();
|
||||||
|
return capabilities?.available ?? "no";
|
||||||
|
}
|
||||||
|
|
||||||
|
// old version
|
||||||
|
if (ai?.canCreateTextSession) {
|
||||||
|
const available = await ai.canCreateTextSession();
|
||||||
|
return available ?? "no";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "no";
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error checking Chrome AI availability:", e);
|
||||||
|
return "no";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AITextSession {
|
||||||
|
prompt(input: string): Promise<string>
|
||||||
|
promptStreaming(input: string): ReadableStream
|
||||||
|
destroy(): void
|
||||||
|
clone(): AITextSession
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const createAITextSession = async (data: any): Promise<AITextSession> => {
|
||||||
|
const ai = (window as any).ai;
|
||||||
|
|
||||||
|
// upcoming version change
|
||||||
|
if (ai?.assistant?.create) {
|
||||||
|
const session = await ai.assistant.create({
|
||||||
|
...data
|
||||||
|
})
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
|
||||||
|
// old version
|
||||||
|
if (ai.createTextSession) {
|
||||||
|
const session = await ai.createTextSession({
|
||||||
|
...data
|
||||||
|
})
|
||||||
|
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("Chrome AI is not available.")
|
||||||
|
}
|
29
src/public/_locales/de/messages.json
Normal file
29
src/public/_locales/de/messages.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"extName": {
|
||||||
|
"message": "Page Assist - Eine Web-Benutzeroberfläche für lokale KI-Modelle"
|
||||||
|
},
|
||||||
|
"extDescription": {
|
||||||
|
"message": "Nutzen Sie Ihre lokal laufenden KI-Modelle, um Sie beim Surfen im Web zu unterstützen."
|
||||||
|
},
|
||||||
|
"openSidePanelToChat": {
|
||||||
|
"message": "Copilot zum Chatten öffnen"
|
||||||
|
},
|
||||||
|
"openOptionToChat": {
|
||||||
|
"message": "Web-Benutzeroberfläche zum Chatten öffnen"
|
||||||
|
},
|
||||||
|
"contextSummarize": {
|
||||||
|
"message": "Zusammenfassen"
|
||||||
|
},
|
||||||
|
"contextExplain": {
|
||||||
|
"message": "Erklären"
|
||||||
|
},
|
||||||
|
"contextRephrase": {
|
||||||
|
"message": "Umformulieren"
|
||||||
|
},
|
||||||
|
"contextTranslate" :{
|
||||||
|
"message": "Übersetzen"
|
||||||
|
},
|
||||||
|
"contextCustom": {
|
||||||
|
"message": "Benutzerdefiniert"
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ import { cleanUrl } from "../libs/clean-url"
|
|||||||
import { urlRewriteRuntime } from "../libs/runtime"
|
import { urlRewriteRuntime } from "../libs/runtime"
|
||||||
import { getChromeAIModel } from "./chrome"
|
import { getChromeAIModel } from "./chrome"
|
||||||
import { setNoOfRetrievedDocs, setTotalFilePerKB } from "./app"
|
import { setNoOfRetrievedDocs, setTotalFilePerKB } from "./app"
|
||||||
|
import fetcher from "@/libs/fetcher"
|
||||||
|
|
||||||
|
|
||||||
const storage = new Storage()
|
const storage = new Storage()
|
||||||
|
|
||||||
@ -15,9 +17,9 @@ const DEFAULT_RAG_QUESTION_PROMPT =
|
|||||||
|
|
||||||
const DEFAUTL_RAG_SYSTEM_PROMPT = `You are a helpful AI assistant. Use the following pieces of context to answer the question at the end. If you don't know the answer, just say you don't know. DO NOT try to make up an answer. If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. {context} Question: {question} Helpful answer:`
|
const DEFAUTL_RAG_SYSTEM_PROMPT = `You are a helpful AI assistant. Use the following pieces of context to answer the question at the end. If you don't know the answer, just say you don't know. DO NOT try to make up an answer. If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. {context} Question: {question} Helpful answer:`
|
||||||
|
|
||||||
const DEFAULT_WEBSEARCH_PROMP = `You are an AI model who is expert at searching the web and answering user's queries.
|
const DEFAULT_WEBSEARCH_PROMP = `You are an AI model who is expert at searching the web and answering user's queries.
|
||||||
|
|
||||||
Generate a response that is informative and relevant to the user's query based on provided search results. the current date and time are {current_date_time}.
|
Generate a response that is informative and relevant to the user's query based on provided search results. the current date and time are {current_date_time}.
|
||||||
|
|
||||||
\`search-results\` block provides knowledge from the web search results. You can use this information to generate a meaningful response.
|
\`search-results\` block provides knowledge from the web search results. You can use this information to generate a meaningful response.
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ Follow-up question: Taylor Swift's latest album?
|
|||||||
Rephrased question: Name of Taylor Swift's latest album.
|
Rephrased question: Name of Taylor Swift's latest album.
|
||||||
|
|
||||||
|
|
||||||
Previous Conversation:
|
Previous Conversation:
|
||||||
|
|
||||||
{chat_history}
|
{chat_history}
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ export const defaultModel = async () => {
|
|||||||
export const isOllamaRunning = async () => {
|
export const isOllamaRunning = async () => {
|
||||||
try {
|
try {
|
||||||
const baseUrl = await getOllamaURL()
|
const baseUrl = await getOllamaURL()
|
||||||
const response = await fetch(`${cleanUrl(baseUrl)}`)
|
const response = await fetcher(`${cleanUrl(baseUrl)}`)
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(response.statusText)
|
throw new Error(response.statusText)
|
||||||
}
|
}
|
||||||
@ -100,7 +102,7 @@ export const getAllModels = async ({
|
|||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
const baseUrl = await getOllamaURL()
|
const baseUrl = await getOllamaURL()
|
||||||
const response = await fetch(`${cleanUrl(baseUrl)}/api/tags`)
|
const response = await fetcher(`${cleanUrl(baseUrl)}/api/tags`)
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
if (returnEmpty) {
|
if (returnEmpty) {
|
||||||
return []
|
return []
|
||||||
@ -132,7 +134,7 @@ export const getAllModels = async ({
|
|||||||
|
|
||||||
export const deleteModel = async (model: string) => {
|
export const deleteModel = async (model: string) => {
|
||||||
const baseUrl = await getOllamaURL()
|
const baseUrl = await getOllamaURL()
|
||||||
const response = await fetch(`${cleanUrl(baseUrl)}/api/delete`, {
|
const response = await fetcher(`${cleanUrl(baseUrl)}/api/delete`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
@ -154,7 +156,7 @@ export const fetchChatModels = async ({
|
|||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
const baseUrl = await getOllamaURL()
|
const baseUrl = await getOllamaURL()
|
||||||
const response = await fetch(`${cleanUrl(baseUrl)}/api/tags`)
|
const response = await fetcher(`${cleanUrl(baseUrl)}/api/tags`)
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
if (returnEmpty) {
|
if (returnEmpty) {
|
||||||
return []
|
return []
|
||||||
|
@ -49,8 +49,6 @@ type State = {
|
|||||||
setChatMode: (chatMode: "normal" | "rag") => void
|
setChatMode: (chatMode: "normal" | "rag") => void
|
||||||
isEmbedding: boolean
|
isEmbedding: boolean
|
||||||
setIsEmbedding: (isEmbedding: boolean) => void
|
setIsEmbedding: (isEmbedding: boolean) => void
|
||||||
speechToTextLanguage: string
|
|
||||||
setSpeechToTextLanguage: (language: string) => void
|
|
||||||
webSearch: boolean
|
webSearch: boolean
|
||||||
setWebSearch: (webSearch: boolean) => void
|
setWebSearch: (webSearch: boolean) => void
|
||||||
isSearchingInternet: boolean
|
isSearchingInternet: boolean
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { checkChromeAIAvailability } from "@/models/utils/chrome"
|
||||||
|
|
||||||
export const getChromeAISupported = async () => {
|
export const getChromeAISupported = async () => {
|
||||||
try {
|
try {
|
||||||
let browserInfo = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)
|
let browserInfo = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)
|
||||||
@ -11,9 +13,8 @@ export const getChromeAISupported = async () => {
|
|||||||
return "ai_not_supported"
|
return "ai_not_supported"
|
||||||
}
|
}
|
||||||
|
|
||||||
//@ts-ignore
|
const capabilities = await checkChromeAIAvailability()
|
||||||
const createSession = await ai?.canCreateGenericSession()
|
if (capabilities !== "readily") {
|
||||||
if (createSession !== "readily") {
|
|
||||||
return "ai_not_ready"
|
return "ai_not_ready"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/utils/key-down.tsx
Normal file
19
src/utils/key-down.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
export const handleChatInputKeyDown = ({
|
||||||
|
e,
|
||||||
|
sendWhenEnter,
|
||||||
|
typing,
|
||||||
|
isSending
|
||||||
|
}: {
|
||||||
|
e: React.KeyboardEvent
|
||||||
|
typing: boolean
|
||||||
|
sendWhenEnter: boolean
|
||||||
|
isSending: boolean
|
||||||
|
}) => {
|
||||||
|
return import.meta.env.BROWSER === "firefox"
|
||||||
|
? e.key === "Enter" &&
|
||||||
|
!e.shiftKey &&
|
||||||
|
!e.nativeEvent.isComposing &&
|
||||||
|
!isSending &&
|
||||||
|
sendWhenEnter
|
||||||
|
: !typing && e.key === "Enter" && !e.shiftKey && !isSending && sendWhenEnter
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { setBadgeBackgroundColor, setBadgeText, setTitle } from "@/utils/action"
|
import { setBadgeBackgroundColor, setBadgeText, setTitle } from "@/utils/action"
|
||||||
|
import fetcher from "@/libs/fetcher"
|
||||||
|
|
||||||
export const progressHuman = (completed: number, total: number) => {
|
export const progressHuman = (completed: number, total: number) => {
|
||||||
return ((completed / total) * 100).toFixed(0) + "%"
|
return ((completed / total) * 100).toFixed(0) + "%"
|
||||||
@ -11,7 +11,7 @@ export const clearBadge = () => {
|
|||||||
}
|
}
|
||||||
export const streamDownload = async (url: string, model: string) => {
|
export const streamDownload = async (url: string, model: string) => {
|
||||||
url += "/api/pull"
|
url += "/api/pull"
|
||||||
const response = await fetch(url, {
|
const response = await fetcher(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { cleanUrl } from "~/libs/clean-url"
|
import { cleanUrl } from "~/libs/clean-url"
|
||||||
|
import fetcher from "@/libs/fetcher"
|
||||||
|
|
||||||
export const verifyPageShareURL = async (url: string) => {
|
export const verifyPageShareURL = async (url: string) => {
|
||||||
const res = await fetch(`${cleanUrl(url)}/api/v1/ping`)
|
const res = await fetcher(`${cleanUrl(url)}/api/v1/ping`)
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error("Unable to verify page share")
|
throw new Error("Unable to verify page share")
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export default defineConfig({
|
|||||||
outDir: "build",
|
outDir: "build",
|
||||||
|
|
||||||
manifest: {
|
manifest: {
|
||||||
version: "1.2.1",
|
version: "1.2.2",
|
||||||
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