commit
2cb868f390
43 changed files with 1633 additions and 394 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -4,6 +4,20 @@
|
|||
|
||||
|
||||
|
||||
<h2>Version 3.5.0 - 30/05/2025</h2>
|
||||
<ul>
|
||||
<li>Added Anthropic API support [<a href="https://github.com/micz/ThunderAI/issues/349">#349</a>].</li>
|
||||
<li>Added the <i>{%selected_html%}</i> placeholder to retrieve the HTML portion of the selected text [<a href="https://github.com/micz/ThunderAI/issues/368">#368</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added a shortcut to select configurations for known AI services. Currently, <i>Grok AI</i> and <i>Mistral AI</i> are available [<a href="https://github.com/micz/ThunderAI/issues/378">#378</a>]. <a href="https://github.com/micz/ThunderAI/issues/new?template=feature_request.md">Open an issue</a> to request additional services.</li>
|
||||
<li><i>[All APIs]</i> In the API WebChat is now possibile to select a part of the answer and use only that [<a href="https://github.com/micz/ThunderAI/issues/356">#356</a>].</li>
|
||||
<li><i>[All APIs]</i> Setting the "Max prompt length" to zero on the options page will disable the length check when sending a prompt to the AI. [<a href="https://github.com/micz/ThunderAI/issues/380">#380</a>].</li>
|
||||
<li><i>[All APIs]</i> Added a button to the options page to reset the 'Max prompt length' value to its default.</li>
|
||||
<li><i>[All APIs]</i> Adding tags automatically or with the context menu will now use also tags not created by ThunderAI [<a href="https://github.com/micz/ThunderAI/issues/390">#390</a>].</li>
|
||||
<li>Fix: in the Spamfilter page the unsaved changes warning is now correctly shown.</li>
|
||||
<li>Fix: The default keyboard shortcut is no longer enforced at every Thunderbird startup [<a href="https://github.com/micz/ThunderAI/issues/384">#384</a>].</li>
|
||||
<li>Fix: Incoming email processing now works correctly when auto-tagging is enabled and the full tagging feature is subsequently disabled.</li>
|
||||
<li>Fix: The reply type is correctly saved in the options. [<a href="https://github.com/micz/ThunderAI/issues/387">#387</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 3.4.1 - 12/05/2025</h2>
|
||||
<ul>
|
||||
<li><i>[All APIs]</i> Fix: correctly assigning tags when receiving mails. Thanks to <a href="https://github.com/jdkio">jdkio</a> [<a href="https://github.com/micz/ThunderAI/issues/374">#374</a>].</li>
|
||||
|
|
|
|||
78
README.md
78
README.md
|
|
@ -1,6 +1,6 @@
|
|||
#  ThunderAI
|
||||
|
||||
ThunderAI is a Thunderbird Addon that uses the capabilities of ChatGPT, Google Gemini or Ollama to enhance email management.
|
||||
ThunderAI is a Thunderbird Addon that uses the capabilities of ChatGPT, Google Gemini, Anthropic or Ollama to enhance email management.
|
||||
|
||||
It enables users to analyse, write, correct, assign tags, create calendar events or tasks and optimize their emails, facilitating more effective and professional communication.
|
||||
|
||||
|
|
@ -17,39 +17,39 @@ Using an API integration, you can activate some automatic features:
|
|||
<br>
|
||||
|
||||
|
||||
> [!TIP]
|
||||
> **Using ChatGPT**
|
||||
>
|
||||
> There is no need for an API key and is possibile to use this extension even with a free account, using the **ChatGPT web interface**!
|
||||
>
|
||||
> If you want to connect with the OpenAI API integration, instead, you can use an **API Key**!
|
||||
|
||||
<br>
|
||||
|
||||
> [!TIP]
|
||||
> **Using Google Gemini**
|
||||
>
|
||||
> Connect directly with Google Gemini API, using also the _System Instructions_ option if needed.
|
||||
|
||||
<br>
|
||||
|
||||
> [!TIP]
|
||||
> **Using Ollama**
|
||||
> [!NOTE]
|
||||
> **Available Integrations**
|
||||
> - **ChatGPT Web**
|
||||
> - There is no need for an API key!
|
||||
> - You can use a free account!
|
||||
>
|
||||
> It's also possible to use a local Ollama server!
|
||||
> <br>
|
||||
>
|
||||
> Just remember to add `OLLAMA_ORIGINS = moz-extension://*` to the Ollama server environment variables.
|
||||
>
|
||||
> [More info about CORS](https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/)
|
||||
|
||||
<br>
|
||||
|
||||
> [!TIP]
|
||||
> **Using an OpenAI Compatible API**
|
||||
> - **OpenAI API**
|
||||
> - Connect directly to ChatGPT using your API key.
|
||||
>
|
||||
> You can also use a local OpenAI Compatible API server, like LM Studio or Mistral AI!
|
||||
> <br>
|
||||
>
|
||||
> There is also an option to remove the "v1" segment from the API url, if needed, and to manually set the model name if the server doesn't have a models list endpoint.
|
||||
> - **Google Gemini**
|
||||
> - You can use also the _System Instructions_ option if needed.
|
||||
>
|
||||
> <br>
|
||||
>
|
||||
> - **Using Ollama**
|
||||
> - Just remember to add `OLLAMA_ORIGINS = moz-extension://*` to the Ollama server environment variables.
|
||||
> - [More info about CORS](https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/)
|
||||
>
|
||||
> <br>
|
||||
>
|
||||
> - **OpenAI Compatible API**
|
||||
> - You can also use a local OpenAI Compatible API server, like LM Studio or Mistral AI!
|
||||
> - There is also an option to remove the "v1" segment from the API url, if needed, and to manually set the model name if the server doesn't have a models list endpoint.
|
||||
>
|
||||
> <br>
|
||||
>
|
||||
> - **Anthropic API**
|
||||
> - Use Claude directly!
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
|
@ -80,14 +80,15 @@ Are you using this addon in your Thunderbird?
|
|||
## Attributions
|
||||
|
||||
### Translations
|
||||
- Chinese (Simplified): [jeklau](https://github.com/jeklau)
|
||||
- Czech (cs): [Fjuro](https://hosted.weblate.org/user/Fjuro/), [Jaroslav Staněk](https://hosted.weblate.org/user/jaroush/)
|
||||
- English (en-US): [Mic](https://github.com/micz/)
|
||||
- French (fr): Generated automatically, [Noam](https://github.com/noam-sc)
|
||||
- German (de): Generated automatically
|
||||
- Italian (it): [Mic](https://github.com/micz/)
|
||||
- Polski (pl): [neexpl](https://github.com/neexpl), [makkacprzak](https://github.com/makkacprzak)
|
||||
- Português Brasileiro (pt-br): Bruno Pereira de Souza
|
||||
- Chinese (Simplified): [jeklau](https://github.com/jeklau) <img src="https://micz.it/weblate/thunderai/zh_Hans.svg">
|
||||
- Czech (cs): [Fjuro](https://hosted.weblate.org/user/Fjuro/), [Jaroslav Staněk](https://hosted.weblate.org/user/jaroush/) <img src="https://micz.it/weblate/thunderai/cs.svg">
|
||||
- French (fr): Generated automatically, [Noam](https://github.com/noam-sc) <img src="https://micz.it/weblate/thunderai/fr.svg">
|
||||
- German (de): Generated automatically <img src="https://micz.it/weblate/thunderai/de.svg">
|
||||
- Italian (it): [Mic](https://github.com/micz/) <img src="https://micz.it/weblate/thunderai/it.svg">
|
||||
- Polski (pl): [neexpl](https://github.com/neexpl), [makkacprzak](https://github.com/makkacprzak) <img src="https://micz.it/weblate/thunderai/pl.svg">
|
||||
- Português Brasileiro (pt-br): Bruno Pereira de Souza <img src="https://micz.it/weblate/thunderai/pt-br.svg">
|
||||
|
||||
Do you want to help translate this addon? [Find out how!](https://micz.it/thunderbird-addon-thunderai/translate/)
|
||||
|
||||
|
||||
<br>
|
||||
|
|
@ -106,4 +107,3 @@ Are you using this addon in your Thunderbird?
|
|||
- <a href="https://github.com/KudoAI/chatgpt.js">chatgpt.js</a> for providing methods to interact with the ChatGPT web frontend
|
||||
- <a href="https://github.com/boxabirds">Julian Harris</a> for his project <a href="https://github.com/boxabirds/chatgpt-frontend-nobuild">chatgpt-frontend-nobuild</a>, that has been used as a starting point for the API Web Interface
|
||||
- <a href="https://hosted.weblate.org/widgets/thunderai/">Hosted Weblate</a> for managing the localization
|
||||
- <a href="https://github.com/ali-raheem/Aify">Aify</a> for inspiration
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
"message": "Přidat do nabídky"
|
||||
},
|
||||
"extensionDescription": {
|
||||
"message": "Použijte ChatGPT, Google Gemini nebo Ollama pro vylepšení vašich e-mailů!"
|
||||
"message": "Použijte ChatGPT, Google Gemini, Anthropic nebo Ollama pro vylepšení vašich e-mailů!"
|
||||
},
|
||||
"menu_title": {
|
||||
"message": "AI"
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
"message": "stav služby"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "Rozměry okna ChatGPT"
|
||||
"message": "Rozměry okna AI chatu"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_height": {
|
||||
"message": "Výška"
|
||||
|
|
@ -717,7 +717,7 @@
|
|||
"message": "Maximální délka výzvy"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "Toto je maximální počet znaků, které lze použít ve výzvě. V opačném případě se zobrazí chybová zpráva. Tato hodnota není upravitelná pro webové rozhraní ChatGPT."
|
||||
"message": "Toto je maximální počet znaků, které lze použít ve výzvě. V opačném případě se zobrazí chybová zpráva. Tato hodnota není upravitelná pro webové rozhraní ChatGPT. Nastavte na nulu pro deaktivaci kontroly."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Webový model ChatGPT"
|
||||
|
|
@ -870,10 +870,10 @@
|
|||
"message": "Pokud je zaškrtnuto, AI automaticky přidá štítky k nově přijatým e-mailům."
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Vynutit existující štítky při automatickém označování"
|
||||
"message": "Vynutit existující štítky při automatickém označování nebo použití kontextového menu"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Analyzuj následující e-mail a urči, zda se jedná o spam či nikoli. Zvaž faktory, jako jsou podezřelá klíčová slova, nadměrné propagační výrazy, zavádějící řádky předmětu, žádosti o osobní informace a neobvyklé adresy odesílatele.\nZadej hodnotu od 0 (není spam) do 100 (spam) a vysvětlení o maximálně 10 slovech. \nVygeneruj odpověď pouze ve formátu JSON. Neuváděj žádný další text nebo vysvětlení; uveď pouze JSON. Zde je formát, který se má použít:\n{\n\"spamValue\": <celé číslo od 0 do 100>,\n\"explanation\": \"Stručné vysvětlení vašeho zdůvodnění\",\n}\nZde jsou informace o e-mailu:\nOdesílatel: \"{%author%}\"\nPředmět: \"{%mail_subject%}\"\nText HTML: \"{%mail_html_body%}\""
|
||||
"message": "Analyzuj následující e-mail a urči, zda se jedná o spam či nikoli. Zvaž faktory, jako jsou podezřelá klíčová slova, nadměrné propagační výrazy, zavádějící řádky předmětu, žádosti o osobní informace a neobvyklé adresy odesílatele.\nZadej hodnotu od 0 (není spam) do 100 (spam) a vysvětlení o maximálně 10 slovech. \nV případě chybějících údajů zprávy nastavte hodnotu na 0 (není spam) a uveďte důvod.\nVygeneruj odpověď pouze ve formátu JSON. Neuváděj žádný další text nebo vysvětlení; uveď pouze JSON. Zde je formát, který se má použít:\n{\n\"spamValue\": <celé číslo od 0 do 100>,\n\"explanation\": \"Stručné vysvětlení vašeho zdůvodnění\"\n}\nZde jsou informace o e-mailu:\nOdesílatel: \"{%author%}\"\nPředmět: \"{%mail_subject%}\"\nText HTML: \"{%mail_html_body%}\""
|
||||
},
|
||||
"context_menu_mzta-add-tags": {
|
||||
"message": "Přidat štítky"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Verwenden Sie ChatGPT, Google Gemini oder Ollama, um Ihre E-Mails zu verbessern!",
|
||||
"message": "Verwenden Sie ChatGPT, Google Gemini, Anthropic oder Ollama, um Ihre E-Mails zu verbessern!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -487,7 +487,7 @@
|
|||
"message": "Maximale Eingabelänge"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "Dies ist die maximale Anzahl von Zeichen, die in einer Eingabe verwendet werden können. Andernfalls wird eine Fehlermeldung angezeigt. Der Wert ist für die ChatGPT-Webschnittstelle nicht bearbeitbar."
|
||||
"message": "Dies ist die maximale Anzahl von Zeichen, die in einer Eingabe verwendet werden können. Andernfalls wird eine Fehlermeldung angezeigt. Der Wert ist für die ChatGPT-Webschnittstelle nicht bearbeitbar. Setzen Sie es auf null, um die Prüfung zu deaktivieren."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "ChatGPT Web-Modell"
|
||||
|
|
@ -853,7 +853,7 @@
|
|||
"message": "Wenn ausgewählt, wird die KI nur vorhandene Tags zu neu empfangenen E-Mails hinzufügen und keine neuen Tags erstellen."
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Vorhandene Tags beim automatischen Taggen erzwingen"
|
||||
"message": "Vorhandene Tags beim automatischen Taggen oder bei der Verwendung des Kontextmenüs erzwingen"
|
||||
},
|
||||
"spamfilter_no_reports": {
|
||||
"message": "Es wurden noch keine Nachrichten auf Spam überprüft. Hier finden Sie eine Liste der letzten 100 Spam-Berichte nur für die aktuelle Sitzung."
|
||||
|
|
@ -862,7 +862,7 @@
|
|||
"message": "Wenn ausgewählt, wird ThunderAI Spam-E-Mails automatisch in den Spam-Ordner verschieben."
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Analysieren Sie die folgende E-Mail und bestimmen Sie, ob es sich um Spam handelt oder nicht. Berücksichtigen Sie Faktoren wie verdächtige Schlüsselwörter, übermäßige Werbesprache, irreführende Betreffzeilen, Anfragen nach persönlichen Informationen und ungewöhnliche Absenderadressen.\nGeben Sie einen Wert von 0 (kein Spam) bis 100 (Spam) und eine Erklärung mit maximal 10 Wörtern an.\nGenerieren Sie die Antwort ausschließlich im JSON-Format. Fügen Sie keinen zusätzlichen Text oder Erklärungen hinzu; liefern Sie nur das JSON. Hier ist das zu verwendende Format:\n{\n\"spamValue\": <Ganzzahl von 0 bis 100>,\n\"explanation\": \"Kurze Erklärung Ihrer Begründung\",\n}\nHier sind die Mail-Informationen:\nAbsender: \"{%author%}\"\nBetreff: \"{%mail_subject%}\"\nHTML-Inhalt: \"{%mail_html_body%}\""
|
||||
"message": "Analysieren Sie die folgende E-Mail und bestimmen Sie, ob es sich um Spam handelt oder nicht. Berücksichtigen Sie Faktoren wie verdächtige Schlüsselwörter, übermäßige Werbesprache, irreführende Betreffzeilen, Anfragen nach persönlichen Informationen und ungewöhnliche Absenderadressen.\nGeben Sie einen Wert von 0 (kein Spam) bis 100 (Spam) und eine Erklärung mit maximal 10 Wörtern an.\nFalls Nachrichtendaten fehlen, setzen Sie den Wert auf 0 (kein Spam) und geben Sie den Grund an.\nGenerieren Sie die Antwort ausschließlich im JSON-Format. Fügen Sie keinen zusätzlichen Text oder Erklärungen hinzu; liefern Sie nur das JSON. Hier ist das zu verwendende Format:\n{\n\"spamValue\": <Ganzzahl von 0 bis 100>,\n\"explanation\": \"Kurze Erklärung Ihrer Begründung\"\n}\nHier sind die Mail-Informationen:\nAbsender: \"{%author%}\"\nBetreff: \"{%mail_subject%}\"\nHTML-Inhalt: \"{%mail_html_body%}\""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_info_remote": {
|
||||
"message": "Hier können Sie auch die Adresse eines entfernten Servers eingeben."
|
||||
|
|
@ -1032,16 +1032,16 @@
|
|||
"GetTask_info_default": {
|
||||
"message": "Auf dieser Seite kannst du den Standard-Prompt anpassen, der verwendet wird, um eine Aufgabe aus dem ausgewählten Text zu erstellen."
|
||||
},
|
||||
"ask_chatgptweb_permission_2": {
|
||||
"ask_integration_permission_2": {
|
||||
"message": "Klicke hier, um fortzufahren."
|
||||
},
|
||||
"ask_chatgptweb_permission_1": {
|
||||
"message": "Um die ChatGPT-Web-Integration zu nutzen, musst du die erforderliche Berechtigung erteilen."
|
||||
},
|
||||
"ask_chatgptweb_permission_2_popup": {
|
||||
"ask_integration_permission_2_popup": {
|
||||
"message": "Klicke hier, um einen neuen Tab zu öffnen und den Anweisungen zu folgen."
|
||||
},
|
||||
"ask_chatgptweb_permission_ok": {
|
||||
"ask_integration_permission_ok": {
|
||||
"message": "Berechtigung erteilt. Du kannst hier klicken, um diesen Tab zu schließen und zum Hauptfenster zurückzukehren."
|
||||
},
|
||||
"AccountSelector_AutoTags": {
|
||||
|
|
@ -1082,5 +1082,102 @@
|
|||
},
|
||||
"prompt_proofread_this_full_text": {
|
||||
"message": "Bitte korrigieren Sie die folgende E-Mail und beheben Sie alle Rechtschreib- oder Grammatikfehler. Antworten Sie nur mit dem korrigierten Text, ohne zusätzliche Kommentare oder sonstigen Text.\n\n„{%mail_typed_text%}“"
|
||||
},
|
||||
"prefs_Connection_type_Anthropic_API": {
|
||||
"message": "Anthropic API"
|
||||
},
|
||||
"anthropic_empty_version": {
|
||||
"message": "Sie haben keinen Versionsstring für die Anthropic-API hinzugefügt. Bitte fügen Sie einen auf der Optionsseite ein."
|
||||
},
|
||||
"Anthropic_Models_Error_fetching": {
|
||||
"message": "Fehler beim Abrufen der Anthropic-Modelle"
|
||||
},
|
||||
"prefs_Anthropic_API_Key": {
|
||||
"message": "Anthropic API-Schlüssel"
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens_Info": {
|
||||
"message": "Die maximale Anzahl von Tokens, die in der Vervollständigung generiert werden soll. Die Anzahl der Tokens Ihres Prompts plus max_tokens darf die Kontextlänge des Modells nicht überschreiten."
|
||||
},
|
||||
"anthropic_api_request_failed": {
|
||||
"message": "Anfrage an die Anthropic-API fehlgeschlagen"
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Verbindungsversuch zu $api_string$ mit der folgenden Konfiguration:",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Anthropic_Models_Fetch": {
|
||||
"message": "Anthropic-Modellliste aktualisieren"
|
||||
},
|
||||
"Custom": {
|
||||
"message": "Benutzerdefiniert"
|
||||
},
|
||||
"Anthropic_Version": {
|
||||
"message": "Anthropic-API-Version"
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens": {
|
||||
"message": "Maximale Anzahl an Tokens für Anthropic"
|
||||
},
|
||||
"anthropic_empty_apikey": {
|
||||
"message": "Sie haben keinen API-Schlüssel für die Anthropic-API hinzugefügt. Bitte fügen Sie einen auf der Optionsseite ein."
|
||||
},
|
||||
"ask_anthropic_api_permission_1": {
|
||||
"message": "Um die Anthropic-API-Integration zu verwenden, müssen Sie die erforderliche Berechtigung erteilen."
|
||||
},
|
||||
"Anthropic_Models": {
|
||||
"message": "Anthropic Modelle"
|
||||
},
|
||||
"anthropic_empty_model": {
|
||||
"message": "Sie haben kein Modell für die Anthropic-API ausgewählt. Bitte wählen Sie eines auf der Optionsseite aus."
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Modell: $model$",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Host: $api_host$",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Version: $api_version$",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices": {
|
||||
"message": "Verfügbare Dienste"
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices_Info": {
|
||||
"message": "Wählen Sie einen der verfügbaren Dienste für die OpenAI-kompatible API aus oder fügen Sie einen manuell ein."
|
||||
},
|
||||
"OpenAIComp_Configs_ConfirmApply": {
|
||||
"message": "Sind Sie sicher, dass Sie die Konfiguration \"$config_name$\" anwenden möchten?",
|
||||
"placeholders": {
|
||||
"config_name": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apiwebchat_selection_info": {
|
||||
"message": "Wenn Sie einen Textabschnitt auswählen, wird nur dieser Teil berücksichtigt."
|
||||
},
|
||||
"placeholder_selected_html": {
|
||||
"message": "Ausgewähltes HTML"
|
||||
},
|
||||
"Anthropic_Version_Info": {
|
||||
"message": "ERFORDERLICH. Ändern Sie diesen Wert nicht, es sei denn, Sie wissen, was Sie tun. Weitere Informationen unter:"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Use ChatGPT, Goolge Gemini or Ollama to enhance your emails!",
|
||||
"message": "Use ChatGPT, Goolge Gemini, Anthropic or Ollama to enhance your emails!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -451,10 +451,6 @@
|
|||
"message": "Using model",
|
||||
"description": ""
|
||||
},
|
||||
"chagpt_api_connecting": {
|
||||
"message": "Attempting to connect to OpenAI ChatGPT using the API key provided",
|
||||
"description": ""
|
||||
},
|
||||
"Debug": {
|
||||
"message": "Debug",
|
||||
"description": ""
|
||||
|
|
@ -499,14 +495,6 @@
|
|||
"message": "You've not choosen a model for the Ollama API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"ollama_api_connecting": {
|
||||
"message": "Attempting to connect to the Ollama Local Server using the host",
|
||||
"description": ""
|
||||
},
|
||||
"andModel": {
|
||||
"message": "and model",
|
||||
"description": ""
|
||||
},
|
||||
"error_connection_interrupted": {
|
||||
"message": "The connection to the server was unexpectedly interrupted",
|
||||
"description": ""
|
||||
|
|
@ -547,10 +535,6 @@
|
|||
"message": "You've not choosen a model for the OpenAI Compatible API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_api_connecting": {
|
||||
"message": "Attempting to connect to the OpenAI Compatible API Local Server using the host",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_api_request_failed": {
|
||||
"message": "OpenAI Comp API request failed",
|
||||
"description": ""
|
||||
|
|
@ -635,6 +619,10 @@
|
|||
"message": "Selected text",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_html": {
|
||||
"message": "Selected HTML",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Additional text",
|
||||
"description": ""
|
||||
|
|
@ -672,7 +660,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info" : {
|
||||
"message": "This is the maximum number of characters that can be used in a prompt. Otherwise, an error message will be displayed. The value is not editable for the ChatGPT Web Interface.",
|
||||
"message": "This is the maximum number of characters that can be used in a prompt. Otherwise, an error message will be displayed. The value is not editable for the ChatGPT Web Interface. Set it to zero to disable the check.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
|
|
@ -955,10 +943,6 @@
|
|||
"message": "Google Gemini API request failed",
|
||||
"description": ""
|
||||
},
|
||||
"google_gemini_api_connecting": {
|
||||
"message": "Attempting to connect to Google Gemini using the API key provided",
|
||||
"description": ""
|
||||
},
|
||||
"google_gemini_empty_apikey": {
|
||||
"message": "You've not added an API Key for the Google Gemini API. Please insert one in the options page.",
|
||||
"description": ""
|
||||
|
|
@ -1132,7 +1116,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Force existing tags when autotagging",
|
||||
"message": "Force existing tags when autotagging or using the context menu",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing_Info": {
|
||||
|
|
@ -1192,7 +1176,7 @@
|
|||
"description" : ""
|
||||
},
|
||||
"prompt_spamfilter_full_text" : {
|
||||
"message" : "Analyze the following email and determine if it is spam or not. Consider factors such as suspicious keywords, excessive promotional language, misleading subject lines, requests for personal information, and unusual sender addresses.\nProvide a value from 0 (not spam) to 100 (spam) and an explaination of no more than 10 words.\nGenerate a response in JSON format only. Do not include any additional text or explanation; provide only the JSON. Here is the format to be used:\n{\n\"spamValue\": <integer from 0 to 100>,\n\"explanation\": \"Brief explanation of your reasoning\",\n}\nHere there are the mail information:\nSender: \"{%author%}\"\nSubject: \"{%mail_subject%}\"\nHtml body: \"{%mail_html_body%}\"",
|
||||
"message" : "Analyze the following email and determine if it is spam or not. Consider factors such as suspicious keywords, excessive promotional language, misleading subject lines, requests for personal information, and unusual sender addresses.\nProvide a value from 0 (not spam) to 100 (spam) and an explanation of no more than 10 words.\nIn case of missing message data, set the value to 0 (not spam), and give the reason.\nGenerate a response in JSON format only. Do not include any additional text or explanation; provide only the JSON. Here is the format to be used:\n{\n\"spamValue\": <integer from 0 to 100>,\n\"explanation\": \"Brief explanation of your reasoning\"\n}\nHere there are the mail information:\nSender: \"{%author%}\"\nSubject: \"{%mail_subject%}\"\nHtml body: \"{%mail_html_body%}\"",
|
||||
"description" : ""
|
||||
},
|
||||
"SpamFilter_prompt_prefs_title": {
|
||||
|
|
@ -1364,18 +1348,22 @@
|
|||
"description": ""
|
||||
},
|
||||
"ask_chatgptweb_permission_1": {
|
||||
"message": "To use the ChatGPT Web Integration, you need to grant the required permission.",
|
||||
"message": "To use the ChatGPT Web integration, you need to grant the required permission.",
|
||||
"description": ""
|
||||
},
|
||||
"ask_chatgptweb_permission_2_popup": {
|
||||
"ask_anthropic_api_permission_1": {
|
||||
"message": "To use the Anthropic API integration, you need to grant the required permission.",
|
||||
"description": ""
|
||||
},
|
||||
"ask_integration_permission_2_popup": {
|
||||
"message": "Click here to open a new tab and follow the instructions.",
|
||||
"description": ""
|
||||
},
|
||||
"ask_chatgptweb_permission_2": {
|
||||
"ask_integration_permission_2": {
|
||||
"message": "Click here to proceed.",
|
||||
"description": ""
|
||||
},
|
||||
"ask_chatgptweb_permission_ok": {
|
||||
"ask_integration_permission_ok": {
|
||||
"message": "Permission granted. You can click here to close this tab and return to the main window.",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -1438,5 +1426,118 @@
|
|||
"prefs_OptionText_Project_No_temporary_chat_warn": {
|
||||
"message": "If a Project is specified in the options or in a prompt, the temporary chat will not be used.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Anthropic_API_Key": {
|
||||
"message": "Anthropic API Key",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_Anthropic_API": {
|
||||
"message": "Anthropic API",
|
||||
"description": ""
|
||||
},
|
||||
"Anthropic_Models": {
|
||||
"message": "Anthropic Models",
|
||||
"description": ""
|
||||
},
|
||||
"Anthropic_Models_Fetch": {
|
||||
"message": "Update Anthropic Models list",
|
||||
"description": ""
|
||||
},
|
||||
"Anthropic_Models_Error_fetching": {
|
||||
"message": "Error trying to fetch Anthropic models",
|
||||
"description": ""
|
||||
},
|
||||
"Anthropic_Version": {
|
||||
"message": "Anthropic API Version",
|
||||
"description": ""
|
||||
},
|
||||
"Anthropic_Version_Info": {
|
||||
"message": "REQUIRED. Do not change this value unless you know what you're doing. More info at:",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens": {
|
||||
"message": "Anthropic Max Tokens",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens_Info": {
|
||||
"message": "The maximum number of tokens to generate in the completion. The token count of your prompt plus max_tokens cannot exceed the model's context length.",
|
||||
"description": ""
|
||||
},
|
||||
"anthropic_empty_apikey": {
|
||||
"message": "You've not added an API Key for the Anthropic API. Please insert one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"anthropic_empty_model": {
|
||||
"message": "You've not choosen a model for the Anthropic API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"anthropic_empty_version": {
|
||||
"message": "You've not added a version string for the Anthropic API. Please insert one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"anthropic_api_request_failed": {
|
||||
"message": "Anthropic API request failed",
|
||||
"description": ""
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Attempting to connect to $api_string$ using the following configuration:",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Model: $model$",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Host: $api_host$",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Version: $api_version$",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices": {
|
||||
"message": "Available Services",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices_Info": {
|
||||
"message": "Choose one of the services available for the OpenAI Compatible API or insert one manually.",
|
||||
"description": ""
|
||||
},
|
||||
"Custom": {
|
||||
"message": "Custom",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_Configs_ConfirmApply": {
|
||||
"message": "Are you sure you want to apply the configuration \"$config_name$\"?",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"config_name": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apiwebchat_selection_info": {
|
||||
"message": "If you select some text, only that portion will be considered.",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
"message": "Respondi per"
|
||||
},
|
||||
"extensionDescription": {
|
||||
"message": "Uzu ChatGPT, Google Gemini aŭ Ollama por poluri viajn retpoŝtajn mesaĝojn!"
|
||||
"message": "Uzu ChatGPT, Google Gemini, Anthropic aŭ Ollama por poluri viajn retpoŝtajn mesaĝojn!"
|
||||
},
|
||||
"prompt_rewrite_formal": {
|
||||
"message": "Reverki formale"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "¡Usa ChatGPT, Goolge Gemini u Ollama para mejorar tus emails!"
|
||||
"message": "¡Usa ChatGPT, Goolge Gemini, Anthropic u Ollama para mejorar tus emails!"
|
||||
},
|
||||
"menu_title": {
|
||||
"message": "IA"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Utilise ChatGPT, Goolge Gemini ou Ollama pour améliorer tes e-mails !",
|
||||
"message": "Utilise ChatGPT, Goolge Gemini, Anthropic ou Ollama pour améliorer tes e-mails !",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -487,7 +487,7 @@
|
|||
"message": "Longueur maximale du prompt"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "C'est le nombre maximum de caractères qui peuvent être utilisés dans une invite. Sinon, un message d'erreur sera affiché. La valeur n'est pas modifiable pour l'interface Web de ChatGPT."
|
||||
"message": "C'est le nombre maximum de caractères qui peuvent être utilisés dans une invite. Sinon, un message d'erreur sera affiché. La valeur n'est pas modifiable pour l'interface Web de ChatGPT. Réglez-le sur zéro pour désactiver la vérification."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Modèle Web ChatGPT"
|
||||
|
|
@ -850,7 +850,7 @@
|
|||
"message": "Ici, vous pouvez également insérer l'adresse d'un serveur distant."
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Forcer les tags existants lors de l'ajout automatique"
|
||||
"message": "Forcer les balises existantes lors de l’auto-étiquetage ou de l’utilisation du menu contextuel"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing_Info": {
|
||||
"message": "Si coché, l'IA ajoutera uniquement les tags existants aux e-mails nouvellement reçus et ne créera pas de nouveaux tags."
|
||||
|
|
@ -865,7 +865,7 @@
|
|||
"message": "Date du rapport"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Analysez l'e-mail suivant et déterminez s'il s'agit d'un spam ou non. Prenez en compte des facteurs tels que des mots-clés suspects, un langage promotionnel excessif, des lignes d'objet trompeuses, des demandes d'informations personnelles et des adresses d'expéditeurs inhabituelles.\nFournissez une valeur de 0 (non spam) à 100 (spam) et une explication de 10 mots maximum.\nGénérez une réponse uniquement au format JSON. N'incluez aucun texte ou explication supplémentaire ; fournissez uniquement le JSON. Voici le format à utiliser :\n{\n\"spamValue\" : <entier de 0 à 100>,\n\"explanation\" : \"Brève explication de votre raisonnement\",\n}\nVoici les informations de l'e-mail :\nExpéditeur : \"{%author%}\"\nObjet : \"{%mail_subject%}\"\nCorps HTML : \"{%mail_html_body%}\""
|
||||
"message": "Analysez l'e-mail suivant et déterminez s'il s'agit d'un spam ou non. Prenez en compte des facteurs tels que des mots-clés suspects, un langage promotionnel excessif, des lignes d'objet trompeuses, des demandes d'informations personnelles et des adresses d'expéditeurs inhabituelles.\nFournissez une valeur de 0 (non spam) à 100 (spam) et une explication de 10 mots maximum.\nEn cas de données de message manquantes, définissez la valeur à 0 (non spam) et indiquez la raison.\nGénérez une réponse uniquement au format JSON. N'incluez aucun texte ou explication supplémentaire ; fournissez uniquement le JSON. Voici le format à utiliser :\n{\n\"spamValue\" : <entier de 0 à 100>,\n\"explanation\" : \"Brève explication de votre raisonnement\"\n}\nVoici les informations de l'e-mail :\nExpéditeur : \"{%author%}\"\nObjet : \"{%mail_subject%}\"\nCorps HTML : \"{%mail_html_body%}\""
|
||||
},
|
||||
"context_menu_mzta-add-tags": {
|
||||
"message": "Ajouter des étiquettes"
|
||||
|
|
@ -987,10 +987,10 @@
|
|||
"prefs_OptionText_chatgpt_web_custom_data_info": {
|
||||
"message": "Cela doit être dans le format suivant :"
|
||||
},
|
||||
"ask_chatgptweb_permission_2_popup": {
|
||||
"ask_integration_permission_2_popup": {
|
||||
"message": "Cliquez ici pour ouvrir un nouvel onglet et suivre les instructions."
|
||||
},
|
||||
"ask_chatgptweb_permission_2": {
|
||||
"ask_integration_permission_2": {
|
||||
"message": "Cliquez ici pour continuer."
|
||||
},
|
||||
"prefs_OptionText_Project_No_temporary_chat_warn": {
|
||||
|
|
@ -1035,7 +1035,7 @@
|
|||
"AccountSelector_Spamfilter": {
|
||||
"message": "Choisissez les comptes pour lesquels le filtre anti-spam est activé"
|
||||
},
|
||||
"ask_chatgptweb_permission_ok": {
|
||||
"ask_integration_permission_ok": {
|
||||
"message": "Autorisation accordée. Vous pouvez cliquer ici pour fermer cet onglet et revenir à la fenêtre principale."
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_Info2": {
|
||||
|
|
@ -1082,5 +1082,102 @@
|
|||
},
|
||||
"prompt_get_task_full_text": {
|
||||
"message": "Extrait tous les détails pertinents nécessaires pour générer une tâche à partir du texte suivant. Les informations extraites doivent inclure :\n- Date et heure d'échéance (incluant le fuseau horaire, si précisé)\n- Résumé de la tâche\n- Date et heure de début (incluant le fuseau horaire, si précisé)\nAssure-toi que les données sont clairement et uniformément formatées afin qu’elles puissent être utilisées directement pour créer une tâche.\nS'il y a des références temporelles relatives, considère que la date et l’heure de l’e-mail sont \"{%mail_datetime%}\". Calcule la date et l’heure de début en te basant sur cette référence. Si la date et l’heure de début calculées sont antérieures à \"{%current_datetime%}\", recalcule-les en utilisant \"{%current_datetime%}\" comme base.\nSi tu ne peux pas obtenir une ou plusieurs des informations requises, réponds par une chaîne vide.\nGénère une réponse uniquement au format JSON. N’inclus aucun texte ou explication supplémentaire – fournis uniquement le JSON. Voici le format à utiliser :\n{\n\"InitialDate\" : \"YYYYMMDDTHHMMSS\",\n\"dueDate\" : \"YYYYMMDDTHHMMSS\",\n\"summary\" : \"Résumé de la tâche ici\"\n}\nS'il n'y a pas d'informations concernant les dates, supprime-les.\nVoici le texte : \"{%selected_text%}\""
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Tentative de connexion à $api_string$ avec la configuration suivante :",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"anthropic_empty_model": {
|
||||
"message": "Vous n'avez pas choisi de modèle pour l'API Anthropic. Veuillez en sélectionner un dans la page des options."
|
||||
},
|
||||
"Anthropic_Version_Info": {
|
||||
"message": "OBLIGATOIRE. Ne modifiez pas cette valeur sauf si vous savez ce que vous faites. Plus d'informations sur :"
|
||||
},
|
||||
"ask_anthropic_api_permission_1": {
|
||||
"message": "Pour utiliser l'intégration de l'API Anthropic, vous devez accorder l'autorisation requise."
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens_Info": {
|
||||
"message": "Le nombre maximum de jetons à générer dans la complétion. Le total des jetons de votre invite plus max_tokens ne peut pas dépasser la longueur du contexte du modèle."
|
||||
},
|
||||
"anthropic_empty_apikey": {
|
||||
"message": "Vous n'avez pas ajouté de clé API pour l'API Anthropic. Veuillez en insérer une dans la page des options."
|
||||
},
|
||||
"anthropic_empty_version": {
|
||||
"message": "Vous n'avez pas ajouté de chaîne de version pour l'API Anthropic. Veuillez en insérer une dans la page des options."
|
||||
},
|
||||
"apiwebchat_selection_info": {
|
||||
"message": "Si vous sélectionnez du texte, seule cette portion sera prise en compte."
|
||||
},
|
||||
"Anthropic_Version": {
|
||||
"message": "Version de l’API Anthropic"
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens": {
|
||||
"message": "Nombre maximum de jetons Anthropic"
|
||||
},
|
||||
"anthropic_api_request_failed": {
|
||||
"message": "Échec de la requête à l'API Anthropic"
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices": {
|
||||
"message": "Services Disponibles"
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices_Info": {
|
||||
"message": "Choisissez l’un des services disponibles pour l’API compatible OpenAI ou saisissez-en un manuellement."
|
||||
},
|
||||
"OpenAIComp_Configs_ConfirmApply": {
|
||||
"message": "Êtes-vous sûr de vouloir appliquer la configuration \"$config_name$\" ?",
|
||||
"placeholders": {
|
||||
"config_name": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"prefs_Anthropic_API_Key": {
|
||||
"message": "Clé API Anthropic"
|
||||
},
|
||||
"prefs_Connection_type_Anthropic_API": {
|
||||
"message": "API Anthropic"
|
||||
},
|
||||
"Anthropic_Models": {
|
||||
"message": "Modèles Anthropic"
|
||||
},
|
||||
"Anthropic_Models_Fetch": {
|
||||
"message": "Mettre à jour la liste des modèles Anthropic"
|
||||
},
|
||||
"Anthropic_Models_Error_fetching": {
|
||||
"message": "Erreur lors de la tentative de récupération des modèles Anthropic"
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Modèle : $model$",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Hôte : $api_host$",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Version : $api_version$",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"placeholder_selected_html": {
|
||||
"message": "HTML sélectionné"
|
||||
},
|
||||
"Custom": {
|
||||
"message": "Personnalisé"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Koristite ChatGPT, Google Gemini ili Ollama kako bi poboljšali vaše e-poruke!",
|
||||
"message": "Koristite ChatGPT, Google Gemini, Anthropic ili Ollama kako bi poboljšali vaše e-poruke!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
"message": "status usluge"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "Dimenzije prozora ChatGPT"
|
||||
"message": "Dimenzije prozora za AI razgovor"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_height": {
|
||||
"message": "Visina"
|
||||
|
|
@ -487,13 +487,13 @@
|
|||
"message": "Maksimalna duljina upita"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "Ovo je najveći broj znakova koji se mogu koristiti u upitu. U protivnom će se prikazati poruka o pogrešci. Vrijednost nije moguće uređivati za ChatGPT web sučelje."
|
||||
"message": "Ovo je najveći broj znakova koji se mogu koristiti u upitu. U protivnom će se prikazati poruka o pogrešci. Vrijednost nije moguće uređivati za ChatGPT web sučelje. Postavite na nulu kako biste onemogućili provjeru."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "ChatGPT web model"
|
||||
"message": "ChatGPT Web Model"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "Ovo je model koji će se provoditi za ChatGPT web sučelje. Ako nijedan nije naveden ili je naveden netočan, zadani model postavit će ChatGPT na web stranici."
|
||||
"message": "Ovo je Model koji će se provoditi za ChatGPT web sučelje. Ako nijedan nije naveden ili je naveden netočan, zadani model postavit će ChatGPT na web stranici."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "ChatGPT Web privremeno čavrljanje"
|
||||
|
|
@ -745,7 +745,7 @@
|
|||
"message": "Možete promijeniti upit kako želite, ali odgovor primljen od AI mora biti u JSON formatu kako je navedeno u zadanom upitu!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
"message": "Za korištenje značajke kalendarskih događaja instalirajte dodatak ThunderAI Sparks."
|
||||
"message": "Za korištenje značajki kalendarskih događaja i zadataka, molimo instalirajte dodatak ThunderAI Sparks."
|
||||
},
|
||||
"prefs_OptionText_download_now": {
|
||||
"message": "Preuzmite ThunderAI Sparks sada!"
|
||||
|
|
@ -772,7 +772,7 @@
|
|||
"message": "Ako je označeno, AI će automatski dodati oznake novoprimljenim e-porukama."
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Nametni postojeće oznake prilikom automatskog označavanja"
|
||||
"message": "Prisilno koristi postojeće oznake pri automatskom označavanju ili korištenju kontekstnog izbornika"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing_Info": {
|
||||
"message": "Ako je označeno, AI će novoprimljenim e-porukama dodati samo postojeće oznake i neće stvarati nove oznake."
|
||||
|
|
@ -814,7 +814,7 @@
|
|||
"message": "Prepoznaj neželjenu poštu"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Analiziraj sljedeću e-poruku i utvrdi je li neželjena ili ne. Razmotri čimbenike kao što su sumnjive ključne riječi, pretjerani promotivni jezik, zavaravajuće linije predmeta, zahtjevi za osobnim podacima i neobične adrese pošiljatelja.\nNavedi vrijednost od 0 (nije spam) do 100 (neželjena pošta) i objašnjenje od najviše 10 riječi.\nGeneriraj odgovor samo u JSON formatu. Nemoj uključivati nikakav dodatni tekst ili objašnjenje; pruži samo JSON. Ovdje je format koji treba koristiti:\n{\n\"spamValue\": <cijeli broj od 0 do 100>,\n\"explanation\": \"Kratko objašnjenje vašeg obrazloženja\",\n}\nOvdje su informacije o e-poruci:\nŠalje: \"{%author%}\"\nNaslov: \"{%mail_subject%}\"\nHtml tijelo: \"{%mail_html_body%}\""
|
||||
"message": "Analiziraj sljedeću e-poruku i utvrdi je li neželjena ili ne. Razmotri čimbenike kao što su sumnjive ključne riječi, pretjerani promotivni jezik, zavaravajuće linije predmeta, zahtjevi za osobnim podacima i neobične adrese pošiljatelja.\nNavedi vrijednost od 0 (nije spam) do 100 (neželjena pošta) i objašnjenje od najviše 10 riječi.\nU slučaju nedostatka podataka poruke, postavite vrijednost na 0 (nije spam) i navedite razlog.\nGeneriraj odgovor samo u JSON formatu. Nemoj uključivati nikakav dodatni tekst ili objašnjenje; pruži samo JSON. Ovdje je format koji treba koristiti:\n{\n\"spamValue\": <cijeli broj od 0 do 100>,\n\"explanation\": \"Kratko objašnjenje vašeg obrazloženja\"\n}\nOvdje su informacije o e-poruci:\nŠalje: \"{%author%}\"\nNaslov: \"{%mail_subject%}\"\nHtml tijelo: \"{%mail_html_body%}\""
|
||||
},
|
||||
"SpamFilter_prompt_prefs_title": {
|
||||
"message": "Mogućnosti filtera neželjene pošte"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Usa ChatGPT, Google Gemini oppure Ollama per migliorare le tue email!",
|
||||
"message": "Usa ChatGPT, Google Gemini, Anthropic oppure Ollama per migliorare le tue email!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -487,7 +487,7 @@
|
|||
"message": "Lunghezza massima del prompt"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "Questa è la lunghezza massima di caratteri che può essere utilizzata in un prompt. Altrimenti, verrà visualizzato un messaggio di errore. Il valore non è modificabile per l'interfaccia Web di ChatGPT."
|
||||
"message": "Questa è la lunghezza massima di caratteri che può essere utilizzata in un prompt. Altrimenti, verrà visualizzato un messaggio di errore. Il valore non è modificabile per l'interfaccia Web di ChatGPT. Impostalo a zero per disabilitare il controllo."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Modello Web ChatGPT"
|
||||
|
|
@ -787,7 +787,7 @@
|
|||
"message": "Aggiungi tag automaticamente"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Forza i tag esistenti durante l'autotagging"
|
||||
"message": "Forza i tag esistenti durante l'autotagging o quando usi il menu di contesto"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_only_inbox": {
|
||||
"message": "Aggiungi tag solo alle email nella posta in arrivo"
|
||||
|
|
@ -856,7 +856,7 @@
|
|||
"message": "Valore soglia per lo spam"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Analizza la seguente email e determina se si tratta di spam o meno. Considera fattori come parole chiave sospette, linguaggio promozionale eccessivo, linee oggetto fuorvianti, richieste di informazioni personali e indirizzi del mittente insoliti.\nFornisci un valore da 0 (non spam) a 100 (spam) e una spiegazione di non più di 10 parole.\nGenera una risposta esclusivamente in formato JSON. Non includere alcun testo o spiegazione aggiuntiva; fornisci solo il JSON. Ecco il formato da utilizzare:\n{\n\"spamValue\": <intero da 0 a 100>,\n\"explanation\": \"Breve spiegazione del tuo ragionamento\",\n}\nQui ci sono le informazioni sull'email:\nMittente: \"{%author%}\"\nOggetto: \"{%mail_subject%}\"\nCorpo HTML: \"{%mail_html_body%}\""
|
||||
"message": "Analizza la seguente email e determina se si tratta di spam o meno. Considera fattori come parole chiave sospette, linguaggio promozionale eccessivo, linee oggetto fuorvianti, richieste di informazioni personali e indirizzi del mittente insoliti.\nFornisci un valore da 0 (non spam) a 100 (spam) e una spiegazione di non più di 10 parole.\nIn caso di dati del messaggio mancanti, imposta il valore a 0 (non spam) e fornisci la motivazione.\nGenera una risposta esclusivamente in formato JSON. Non includere alcun testo o spiegazione aggiuntiva; fornisci solo il JSON. Ecco il formato da utilizzare:\n{\n\"spamValue\": <intero da 0 a 100>,\n\"explanation\": \"Breve spiegazione del tuo ragionamento\"\n}\nQui ci sono le informazioni sull'email:\nMittente: \"{%author%}\"\nOggetto: \"{%mail_subject%}\"\nCorpo HTML: \"{%mail_html_body%}\""
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing_Info": {
|
||||
"message": "Se selezionato, l'IA aggiungerà solo i tag esistenti alle email appena ricevute e non creerà nuovi tag."
|
||||
|
|
@ -996,7 +996,7 @@
|
|||
"ask_chatgptweb_permission_1": {
|
||||
"message": "Per utilizzare l'integrazione con ChatGPT Web, devi concedere l'autorizzazione richiesta."
|
||||
},
|
||||
"ask_chatgptweb_permission_2_popup": {
|
||||
"ask_integration_permission_2_popup": {
|
||||
"message": "Clicca qui per aprire una nuova scheda e seguire le istruzioni."
|
||||
},
|
||||
"GetTask_info_default": {
|
||||
|
|
@ -1035,10 +1035,10 @@
|
|||
"no_valid_data_received": {
|
||||
"message": "Nessun dato valido ricevuto dall'IA."
|
||||
},
|
||||
"ask_chatgptweb_permission_2": {
|
||||
"ask_integration_permission_2": {
|
||||
"message": "Clicca qui per procedere."
|
||||
},
|
||||
"ask_chatgptweb_permission_ok": {
|
||||
"ask_integration_permission_ok": {
|
||||
"message": "Autorizzazione concessa. Puoi cliccare qui per chiudere questa scheda e tornare alla finestra principale."
|
||||
},
|
||||
"prompt_proofread_this": {
|
||||
|
|
@ -1085,5 +1085,102 @@
|
|||
},
|
||||
"prefs_OptionText_Project_No_temporary_chat_warn": {
|
||||
"message": "Se un Progetto è specificato nelle opzioni o nel prompt, la chat temporanea non verrà utilizzata."
|
||||
},
|
||||
"placeholder_selected_html": {
|
||||
"message": "HTML selezionato"
|
||||
},
|
||||
"prefs_Connection_type_Anthropic_API": {
|
||||
"message": "API Anthropic"
|
||||
},
|
||||
"ask_anthropic_api_permission_1": {
|
||||
"message": "Per utilizzare l'integrazione con l'API di Anthropic, è necessario concedere l'autorizzazione richiesta."
|
||||
},
|
||||
"Anthropic_Version_Info": {
|
||||
"message": "OBBLIGATORIO. Non modificare questo valore a meno che tu non sappia esattamente cosa stai facendo. Maggiori informazioni su:"
|
||||
},
|
||||
"Anthropic_Models": {
|
||||
"message": "Modelli di Anthropic"
|
||||
},
|
||||
"Anthropic_Models_Fetch": {
|
||||
"message": "Aggiorna l'elenco dei modelli di Anthropic"
|
||||
},
|
||||
"Anthropic_Models_Error_fetching": {
|
||||
"message": "Errore durante il tentativo di recupero dei modelli di Anthropic"
|
||||
},
|
||||
"Anthropic_Version": {
|
||||
"message": "Versione API di Anthropic"
|
||||
},
|
||||
"prefs_Anthropic_API_Key": {
|
||||
"message": "Chiave API di Anthropic"
|
||||
},
|
||||
"anthropic_empty_model": {
|
||||
"message": "Non hai selezionato un modello per l'API di Anthropic. Scegline uno nella pagina delle opzioni."
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices_Info": {
|
||||
"message": "Scegli uno dei servizi disponibili per l'API compatibile con OpenAI oppure inseriscine uno manualmente."
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens": {
|
||||
"message": "Numero massimo di token di Anthropic"
|
||||
},
|
||||
"prefs_OptionText_anthropic_max_tokens_Info": {
|
||||
"message": "Il numero massimo di token da generare nell'elaborazione. Il conteggio dei token del tuo prompt, sommato a max_tokens, non può superare la lunghezza di contesto del modello."
|
||||
},
|
||||
"anthropic_empty_apikey": {
|
||||
"message": "Non hai aggiunto una chiave per l'API di Anthropic. Inseriscila nella pagina delle opzioni."
|
||||
},
|
||||
"anthropic_empty_version": {
|
||||
"message": "Non hai aggiunto la versione per l'API di Anthropic. Inseriscila nella pagina delle opzioni."
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Tentativo di connessione a $api_string$ utilizzando la seguente configurazione:",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Modello: $model$",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Host: $api_host$",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices": {
|
||||
"message": "Servizi Disponibili"
|
||||
},
|
||||
"Custom": {
|
||||
"message": "Personalizzato"
|
||||
},
|
||||
"OpenAIComp_Configs_ConfirmApply": {
|
||||
"message": "Sei sicuro di voler applicare la configurazione \"$config_name$\"?",
|
||||
"placeholders": {
|
||||
"config_name": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apiwebchat_selection_info": {
|
||||
"message": "Se selezioni del testo, verrà considerata solo quella parte."
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Versione: $api_version$",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"anthropic_api_request_failed": {
|
||||
"message": "Richiesta all'API di Anthropic non riuscita"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Używaj ChatGPT, Goolge Gemini lub Ollama do ulepszania swoich e-maili!",
|
||||
"message": "Używaj ChatGPT, Goolge Gemini, Anthropic lub Ollama do ulepszania swoich e-maili!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
"message": "status usługi"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "Wymiary okna ChatGPT"
|
||||
"message": "Wymiary okna czatu AI"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_height": {
|
||||
"message": "Wysokość"
|
||||
|
|
@ -487,7 +487,7 @@
|
|||
"message": "Maksymalna długość polecenia"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "To jest maksymalna liczba znaków, która może być użyta w poleceniu. W przeciwnym razie zostanie wyświetlony komunikat o błędzie. Wartość nie jest edytowalna dla interfejsu webowego ChatGPT."
|
||||
"message": "To jest maksymalna liczba znaków, która może być użyta w poleceniu. W przeciwnym razie zostanie wyświetlony komunikat o błędzie. Wartość nie jest edytowalna dla interfejsu webowego ChatGPT. Ustaw na zero, aby wyłączyć sprawdzanie."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Model interfejsu webowego ChatGPT"
|
||||
|
|
@ -790,7 +790,7 @@
|
|||
"message": "Wykrywanie e-maili spamowych"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Wymuszaj istniejące tagi podczas automatycznego tagowania"
|
||||
"message": "Wymuś użycie istniejących tagów podczas automatycznego tagowania lub korzystania z menu kontekstowego"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto": {
|
||||
"message": "Automatycznie dodawaj tagi"
|
||||
|
|
@ -859,7 +859,7 @@
|
|||
"message": "Zarządzaj ustawieniami filtra spamu"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Przeanalizuj poniższy e-mail i określ, czy jest to spam, czy nie. Weź pod uwagę takie czynniki jak podejrzane słowa kluczowe, nadmierny język promocyjny, wprowadzające w błąd tematy, prośby o podanie danych osobowych i nietypowe adresy nadawców.\nPodaj wartość od 0 (nie spam) do 100 (spam) oraz wyjaśnienie nie dłuższe niż 10 słów.\nWygeneruj odpowiedź tylko w formacie JSON. Nie dodawaj żadnego dodatkowego tekstu ani wyjaśnień; podaj tylko JSON. Oto format, który należy użyć:\n{\n\"spamValue\": <liczba całkowita od 0 do 100>,\n\"explanation\": \"Krótkie wyjaśnienie twojego rozumowania\",\n}\nOto informacje o e-mailu:\nNadawca: \"{%author%}\"\nTemat: \"{%mail_subject%}\"\nTreść HTML: \"{%mail_html_body%}\""
|
||||
"message": "Przeanalizuj poniższy e-mail i określ, czy jest to spam, czy nie. Weź pod uwagę takie czynniki jak podejrzane słowa kluczowe, nadmierny język promocyjny, wprowadzające w błąd tematy, prośby o podanie danych osobowych i nietypowe adresy nadawców.\nPodaj wartość od 0 (nie spam) do 100 (spam) oraz wyjaśnienie nie dłuższe niż 10 słów.\nW przypadku braku danych wiadomości ustaw wartość na 0 (nie spam) i podaj powód.\nWygeneruj odpowiedź tylko w formacie JSON. Nie dodawaj żadnego dodatkowego tekstu ani wyjaśnień; podaj tylko JSON. Oto format, który należy użyć:\n{\n\"spamValue\": <liczba całkowita od 0 do 100>,\n\"explanation\": \"Krótkie wyjaśnienie twojego rozumowania\"\n}\nOto informacje o e-mailu:\nNadawca: \"{%author%}\"\nTemat: \"{%mail_subject%}\"\nTreść HTML: \"{%mail_html_body%}\""
|
||||
},
|
||||
"prefs_OptionText_spamfilter_threshold_Info": {
|
||||
"message": "Jeśli wartość zwrócona przez AI przekroczy ten próg, e-mail zostanie przeniesiony do folderu spamu."
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Use o ChatGPT, Goolge Gemini ou o Ollama para aprimorar seus e-mails!",
|
||||
"message": "Use o ChatGPT, Goolge Gemini, Anthropic ou o Ollama para aprimorar seus e-mails!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
"message": "status do serviço"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "Dimensões da janela do ChatGPT"
|
||||
"message": "Dimensões da janela de chat de IA"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_height": {
|
||||
"message": "Altura"
|
||||
|
|
@ -487,7 +487,7 @@
|
|||
"message": "Comprimento máximo do prompt"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "Este é o número máximo de caracteres que podem ser usados em um prompt. Caso contrário, uma mensagem de erro será exibida. O valor não é editável para a Interface Web do ChatGPT."
|
||||
"message": "Este é o número máximo de caracteres que podem ser usados em um prompt. Caso contrário, uma mensagem de erro será exibida. O valor não é editável para a Interface Web do ChatGPT. Defina como zero para desativar a verificação."
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Modelo Web do ChatGPT"
|
||||
|
|
@ -793,7 +793,7 @@
|
|||
"message": "Valor de spam"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "Forçar tags existentes ao adicionar automaticamente"
|
||||
"message": "Forçar tags existentes ao usar a marcação automática ou o menu de contexto"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto": {
|
||||
"message": "Adicionar tags automaticamente"
|
||||
|
|
@ -844,7 +844,7 @@
|
|||
"message": "Filtro de spam automático"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "Analise o seguinte e-mail e determine se é spam ou não. Considere fatores como palavras-chave suspeitas, linguagem promocional excessiva, linhas de assunto enganosas, solicitações de informações pessoais e endereços de remetentes incomuns.\nForneça um valor de 0 (não é spam) a 100 (spam) e uma explicação de no máximo 10 palavras.\nGere uma resposta apenas no formato JSON. Não inclua nenhum texto ou explicação adicional; forneça apenas o JSON. Aqui está o formato a ser usado:\n{\n\"spamValue\": <inteiro de 0 a 100>,\n\"explanation\": \"Breve explicação do seu raciocínio\",\n}\nAqui estão as informações do e-mail:\nRemetente: \"{%author%}\"\nAssunto: \"{%mail_subject%}\"\nCorpo HTML: \"{%mail_html_body%}\""
|
||||
"message": "Analise o seguinte e-mail e determine se é spam ou não. Considere fatores como palavras-chave suspeitas, linguagem promocional excessiva, linhas de assunto enganosas, solicitações de informações pessoais e endereços de remetentes incomuns.\nForneça um valor de 0 (não é spam) a 100 (spam) e uma explicação de no máximo 10 palavras.\nEm caso de ausência de dados da mensagem, defina o valor como 0 (não é spam) e informe o motivo.\nGere uma resposta apenas no formato JSON. Não inclua nenhum texto ou explicação adicional; forneça apenas o JSON. Aqui está o formato a ser usado:\n{\n\"spamValue\": <inteiro de 0 a 100>,\n\"explanation\": \"Breve explicação do seu raciocínio\"\n}\nAqui estão as informações do e-mail:\nRemetente: \"{%author%}\"\nAssunto: \"{%mail_subject%}\"\nCorpo HTML: \"{%mail_html_body%}\""
|
||||
},
|
||||
"prefs_OptionText_spamfilter_threshold_Info": {
|
||||
"message": "Se o valor retornado pela IA estiver acima deste limite, o e-mail será movido para a pasta de spam."
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
"message": "保存所有变动"
|
||||
},
|
||||
"extensionDescription": {
|
||||
"message": "使用ChatGPT、Google Gemini 或Ollama 来增强你的邮件!"
|
||||
"message": "使用 ChatGPT、Google Gemini、Anthropic 或 Ollama 来提升你的电子邮件!"
|
||||
},
|
||||
"menu_title": {
|
||||
"message": "AI"
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
"message": "最大提示词长度"
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "这是提示中可以使用的最大字符数。否则,将显示错误消息。该值在 ChatGPT Web 界面中不可编辑。"
|
||||
"message": "这是提示中可以使用的最大字符数。否则,将显示错误消息。该值在 ChatGPT Web 界面中不可编辑。将其设置为零以禁用检查。"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "ChatGPT Web 模型"
|
||||
|
|
@ -414,7 +414,7 @@
|
|||
"message": "若要使用此集成功能,您需要搭建一台兼容OpenAI API的本地服务器(如LM Studio)。服务器启动后,请在应用程序中的指定字段填入其地址。为确保ThunderAI与本地服务器之间通信正常,请务必正确配置CORS设置。"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "ChatGPT 窗口尺寸"
|
||||
"message": "AI 聊天窗口尺寸"
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_width": {
|
||||
"message": "宽度"
|
||||
|
|
@ -807,7 +807,7 @@
|
|||
"message": "在此页面中,您可以修改用于从选定文本获取日历事件的默认提示。"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_force_existing": {
|
||||
"message": "自动标记时强制使用现有标签"
|
||||
"message": "在自动标记或使用上下文菜单时强制使用现有标签"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_only_inbox_Info": {
|
||||
"message": "如果选中,AI 将仅向收件箱文件夹中收到的电子邮件添加标签。"
|
||||
|
|
@ -840,7 +840,7 @@
|
|||
"message": "您可以根据需要更改提示词,但从 AI 收到的响应必须采用默认提示中指定的 JSON 格式!"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "分析以下邮件并判断它是否为垃圾邮件。考虑因素包括可疑关键词、过多的宣传语言、误导性的主题行、索取个人信息的请求以及异常的发件人地址。\n提供一个从 0(非垃圾邮件)到 100(垃圾邮件)的值,并附上不超过 10 个单词的解释。\n仅以 JSON 格式生成响应。不要包含任何额外文本或解释;仅提供 JSON。以下是使用的格式:\n{\n\"spamValue\": <0 到 100 的整数>,\n\"explanation\": \"简要说明您的判断理由\",\n}\n以下是邮件信息:\n发件人:“{%author%}”\n主题:“{%mail_subject%}”\nHTML 正文:“{%mail_html_body%}”"
|
||||
"message": "分析以下邮件并判断它是否为垃圾邮件。考虑因素包括可疑关键词、过多的宣传语言、误导性的主题行、索取个人信息的请求以及异常的发件人地址。\n提供一个从 0(非垃圾邮件)到 100(垃圾邮件)的值,并附上不超过 10 个单词的解释。\n如果消息数据缺失,将数值设为0(非垃圾邮件),并说明原因。\n仅以 JSON 格式生成响应。不要包含任何额外文本或解释;仅提供 JSON。以下是使用的格式:\n{\n\"spamValue\": <0 到 100 的整数>,\n\"explanation\": \"简要说明您的判断理由\"\n}\n以下是邮件信息:\n发件人:“{%author%}”\n主题:“{%mail_subject%}”\nHTML 正文:“{%mail_html_body%}”"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_threshold_Info": {
|
||||
"message": "如果 AI 返回的值高于此阈值,电子邮件将被移至垃圾邮件文件夹。"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
import { placeholdersUtils } from '../js/mzta-placeholders.js';
|
||||
import { getAPIsInitMessageString } from '../js/mzta-utils.js';
|
||||
|
||||
// Get the LLM to be used
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
|
@ -56,6 +57,12 @@ switch (llm) {
|
|||
case "openai_comp_api":
|
||||
worker = new Worker('../js/workers/model-worker-openai_comp.js', { type: 'module' });
|
||||
break;
|
||||
case "anthropic_api":
|
||||
worker = new Worker('../js/workers/model-worker-anthropic.js', { type: 'module' });
|
||||
break;
|
||||
default:
|
||||
console.error('[ThunderAI] API WebChat Unknown LLM type:', llm);
|
||||
break;
|
||||
}
|
||||
|
||||
messagesArea.init(worker);
|
||||
|
|
@ -73,7 +80,7 @@ switch (llm) {
|
|||
messageInput.setModel(prefs_api.chatgpt_model);
|
||||
messagesArea.setLLMName("ChatGPT");
|
||||
worker.postMessage({ type: 'init', chatgpt_api_key: prefs_api.chatgpt_api_key, chatgpt_model: prefs_api.chatgpt_model, chatgpt_developer_messages: prefs_api.chatgpt_developer_messages, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
messagesArea.appendUserMessage(browser.i18n.getMessage("chagpt_api_connecting") + " " +browser.i18n.getMessage("AndModel") + " \"" + prefs_api.chatgpt_model + "\"...", "info");
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("ChatGPT API", prefs_api.chatgpt_model), "info");
|
||||
browser.runtime.sendMessage({command: "openai_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
|
|
@ -85,7 +92,7 @@ switch (llm) {
|
|||
messageInput.setModel(prefs_api.google_gemini_model);
|
||||
messagesArea.setLLMName("Google Gemini");
|
||||
worker.postMessage({ type: 'init', google_gemini_api_key: prefs_api.google_gemini_api_key, google_gemini_model: prefs_api.google_gemini_model, google_gemini_system_instruction: prefs_api.google_gemini_system_instruction, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
messagesArea.appendUserMessage(browser.i18n.getMessage("google_gemini_api_connecting") + " " +browser.i18n.getMessage("AndModel") + " \"" + prefs_api.google_gemini_model + "\"...", "info");
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("Google Gemini API", prefs_api.google_gemini_model), "info");
|
||||
browser.runtime.sendMessage({command: "google_gemini_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
|
|
@ -98,7 +105,7 @@ switch (llm) {
|
|||
messagesArea.setLLMName("Ollama Local");
|
||||
worker.postMessage({ type: 'init', ollama_host: prefs_api.ollama_host, ollama_model: prefs_api.ollama_model, ollama_num_ctx: prefs_api.ollama_num_ctx, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
browser.runtime.sendMessage({command: "ollama_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
messagesArea.appendUserMessage(browser.i18n.getMessage("ollama_api_connecting") + " \"" + prefs_api.ollama_host + "\" " +browser.i18n.getMessage("AndModel") + " \"" + prefs_api.ollama_model + "\"...", "info");
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("Ollama API", prefs_api.ollama_model, prefs_api.ollama_host), "info");
|
||||
break;
|
||||
}
|
||||
case "openai_comp_api": {
|
||||
|
|
@ -109,10 +116,22 @@ switch (llm) {
|
|||
messageInput.setModel(prefs_api.openai_comp_model);
|
||||
messagesArea.setLLMName(prefs_api.openai_comp_chat_name);
|
||||
worker.postMessage({ type: 'init', openai_comp_host: prefs_api.openai_comp_host, openai_comp_model: prefs_api.openai_comp_model, openai_comp_api_key: prefs_api.openai_comp_api_key, openai_comp_use_v1: prefs_api.openai_comp_use_v1, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
messagesArea.appendUserMessage(browser.i18n.getMessage("OpenAIComp_api_connecting") + " \"" + prefs_api.openai_comp_host + "\" " +browser.i18n.getMessage("AndModel") + " \"" + prefs_api.openai_comp_model + "\"...", "info");
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("OpenAI Compatible API", prefs_api.openai_comp_model, prefs_api.openai_comp_host), "info");
|
||||
browser.runtime.sendMessage({command: "openai_comp_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
case "anthropic_api": {
|
||||
let prefs_api = await browser.storage.sync.get({anthropic_api_key: '', anthropic_model: '', anthropic_version: '2023-06-01', anthropic_max_tokens: 4096, do_debug: false});
|
||||
let i18nStrings = {};
|
||||
i18nStrings["anthropic_api_request_failed"] = browser.i18n.getMessage('anthropic_api_request_failed');
|
||||
i18nStrings["error_connection_interrupted"] = browser.i18n.getMessage('error_connection_interrupted');
|
||||
messageInput.setModel(prefs_api.anthropic_model);
|
||||
messagesArea.setLLMName("Anthropic");
|
||||
worker.postMessage({ type: 'init', anthropic_api_key: prefs_api.anthropic_api_key, anthropic_model: prefs_api.anthropic_model, anthropic_version: prefs_api.anthropic_version, anthropic_max_tokens: prefs_api.anthropic_max_tokens, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("Anthropic API", prefs_api.anthropic_model, '', prefs_api.anthropic_version), "info");
|
||||
browser.runtime.sendMessage({command: "anthropic_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ messagesAreaStyle.textContent = `
|
|||
color: navy;
|
||||
margin-bottom: var(--margin);
|
||||
}
|
||||
.sel_info{
|
||||
font-size: 0.7rem;
|
||||
color: gray;
|
||||
margin-top: 5px;
|
||||
}
|
||||
/* diff viewer */
|
||||
.added {
|
||||
background-color: #d4fcdc;
|
||||
|
|
@ -165,7 +170,7 @@ class MessagesArea extends HTMLElement {
|
|||
let source = browser.i18n.getMessage("apiwebchat_you");
|
||||
switch (type) {
|
||||
case "user":
|
||||
source = browser.i18n.getMessage("apiwebchat_you");;
|
||||
source = browser.i18n.getMessage("apiwebchat_you");
|
||||
break;
|
||||
case "info":
|
||||
source = browser.i18n.getMessage("apiwebchat_info");
|
||||
|
|
@ -176,7 +181,16 @@ class MessagesArea extends HTMLElement {
|
|||
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.classList.add('message', type);
|
||||
// Replace \n with <br> for correct HTML display
|
||||
messageElement.textContent = messageText;
|
||||
// Replace \n with <br> elements for correct HTML display
|
||||
messageElement.innerHTML = '';
|
||||
messageText.split('\n').forEach((line, idx, arr) => {
|
||||
messageElement.appendChild(document.createTextNode(line));
|
||||
if (idx < arr.length - 1) {
|
||||
messageElement.appendChild(document.createElement('br'));
|
||||
}
|
||||
});
|
||||
this.messages.appendChild(messageElement);
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
|
@ -227,6 +241,9 @@ class MessagesArea extends HTMLElement {
|
|||
if(promptData == null) { return; }
|
||||
const actionButtons = document.createElement('div');
|
||||
actionButtons.classList.add('action-buttons');
|
||||
const selectionInfo = document.createElement('p');
|
||||
selectionInfo.textContent = browser.i18n.getMessage("apiwebchat_selection_info");
|
||||
selectionInfo.classList.add('sel_info');
|
||||
const actionButton = document.createElement('button');
|
||||
actionButton.textContent = browser.i18n.getMessage("apiwebchat_use_this_answer");
|
||||
const fullTextHTMLAtAssignment = this.fullTextHTML.trim().replace(/^"|"$/g, '').replace(/^<p>"/, '<p>').replace(/"<\/p>$/, '</p>'); // strip quotation marks
|
||||
|
|
@ -235,15 +252,21 @@ class MessagesArea extends HTMLElement {
|
|||
if(promptData.mailMessageId == -1) { // we are using the reply from the compose window!
|
||||
promptData.action = "2"; // replace text
|
||||
}
|
||||
let finalText = fullTextHTMLAtAssignment;
|
||||
const selectedHTML = this.getCurrentSelectionHTML();
|
||||
if(selectedHTML != "") {
|
||||
finalText = selectedHTML;
|
||||
}
|
||||
|
||||
switch(promptData.action) {
|
||||
case "1": // do reply
|
||||
// console.log("[ThunderAI] (do reply) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replyMessage", text: fullTextHTMLAtAssignment, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId});
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replyMessage", text: finalText, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId});
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
case "2": // replace text
|
||||
// console.log("[ThunderAI] (replace text) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replaceSelectedText", text: fullTextHTMLAtAssignment, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId});
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replaceSelectedText", text: finalText, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId});
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
|
|
@ -251,7 +274,6 @@ class MessagesArea extends HTMLElement {
|
|||
const closeButton = document.createElement('button');
|
||||
closeButton.textContent = browser.i18n.getMessage("chatgpt_win_close");
|
||||
closeButton.addEventListener('click', async () => {
|
||||
// console.log("[ThunderAI] (close) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id}); // close window
|
||||
});
|
||||
if(promptData.action != 0) { actionButtons.appendChild(actionButton); }
|
||||
|
|
@ -273,6 +295,7 @@ class MessagesArea extends HTMLElement {
|
|||
}
|
||||
|
||||
actionButtons.appendChild(closeButton);
|
||||
actionButtons.appendChild(selectionInfo);
|
||||
this.messages.appendChild(actionButtons);
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
|
@ -349,6 +372,18 @@ class MessagesArea extends HTMLElement {
|
|||
}
|
||||
}
|
||||
|
||||
getCurrentSelectionHTML() {
|
||||
const selection = window.getSelection();
|
||||
// console.log(">>>>>>>>>>>>>>>> getCurrentSelectionHTML: " + JSON.stringify(selection.toString()));
|
||||
if (selection.rangeCount > 0) {
|
||||
const range = selection.getRangeAt(0);
|
||||
const container = document.createElement('div');
|
||||
container.appendChild(range.cloneContents());
|
||||
return container.innerHTML;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define('messages-area', MessagesArea);
|
||||
107
js/api/anthropic.js
Normal file
107
js/api/anthropic.js
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 - 2025 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Some original methods derived from https://github.com/ali-raheem/Aify/blob/4ece286095ea7a6cf89d696902e6b81b5d1c3a4b/plugin/html/API.js
|
||||
|
||||
|
||||
export class Anthropic {
|
||||
|
||||
apiKey = '';
|
||||
version = '';
|
||||
model = '';
|
||||
max_tokens = 4096;
|
||||
stream = false;
|
||||
|
||||
constructor(apiKey, version, model, max_tokens = 4096, stream = false) {
|
||||
this.apiKey = apiKey;
|
||||
this.version = version;
|
||||
this.model = model;
|
||||
this.max_tokens = max_tokens > 0 ? max_tokens : 4096;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
|
||||
fetchModels = async () => {
|
||||
try{
|
||||
const response = await fetch("https://api.anthropic.com/v1/models", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": this.apiKey,
|
||||
"anthropic-version": this.version,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorDetail = await response.text();
|
||||
let err_msg = "[ThunderAI] Anthropic API request failed: " + response.status + " " + response.statusText + ", Detail: " + errorDetail;
|
||||
console.error(err_msg);
|
||||
let output = {};
|
||||
output.ok = false;
|
||||
output.error = errorDetail;
|
||||
return output;
|
||||
}
|
||||
|
||||
let output = {};
|
||||
output.ok = true;
|
||||
let output_response = await response.json();
|
||||
output.response = output_response.data;
|
||||
|
||||
return output;
|
||||
}catch (error) {
|
||||
console.error("[ThunderAI] Anthropic API request failed: " + error);
|
||||
let output = {};
|
||||
output.is_exception = true;
|
||||
output.ok = false;
|
||||
output.error = "Anthropic API request failed: " + error;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
fetchResponse = async (messages) => {
|
||||
|
||||
// console.log(">>>>>>>>>>> Anthropic API request: " + JSON.stringify(messages));
|
||||
|
||||
try {
|
||||
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": this.apiKey,
|
||||
"anthropic-version": this.version,
|
||||
"anthropic-dangerous-direct-browser-access": "true",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: this.model,
|
||||
max_tokens: this.max_tokens,
|
||||
messages: messages,
|
||||
stream: this.stream,
|
||||
}),
|
||||
});
|
||||
return response;
|
||||
}catch (error) {
|
||||
console.error("[ThunderAI] Anthropic API request failed: " + error);
|
||||
let output = {};
|
||||
output.is_exception = true;
|
||||
output.ok = false;
|
||||
output.error = "Anthropic API request failed: " + error;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
49
js/api/openai_comp_configs.js
Normal file
49
js/api/openai_comp_configs.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 - 2025 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Config properties for OpenAI API Comp
|
||||
id: <unique ID>
|
||||
name: <AI services Name>
|
||||
chat_name: <AI Name used in the API webchat>
|
||||
host: <API endpoint>
|
||||
use_v1: <true/false> (keep "v1" path segment)
|
||||
*/
|
||||
|
||||
export const openAICompConfigs = [
|
||||
{
|
||||
id: 'custom',
|
||||
name: browser.i18n.getMessage('Custom'),
|
||||
chat_name: 'OpenAI Comp API',
|
||||
host: '',
|
||||
use_v1: true,
|
||||
},
|
||||
{
|
||||
id: 'grok',
|
||||
name: 'Grok AI API',
|
||||
chat_name: 'Grok AI',
|
||||
host: 'https://api.x.ai',
|
||||
use_v1: true,
|
||||
},
|
||||
{
|
||||
id: 'mistral',
|
||||
name: 'Mistral AI API',
|
||||
chat_name: 'Mistral AI',
|
||||
host: 'https://api.mistral.ai',
|
||||
use_v1: true,
|
||||
},
|
||||
];
|
||||
|
|
@ -16,8 +16,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// These methods are also defined in the file /js/mzta-compose-script.js
|
||||
|
||||
|
||||
// These methods are also defined in the file /js/mzta-compose-script.js
|
||||
export async function addTags_getExclusionList() {
|
||||
let prefs_excluded_tags = await browser.storage.local.get({add_tags_exclusions: []});
|
||||
return prefs_excluded_tags.add_tags_exclusions;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,17 @@ switch (message.command) {
|
|||
return Promise.resolve(window.getSelection().toString());
|
||||
}
|
||||
|
||||
case "getSelectedHtml": {
|
||||
const selection = window.getSelection();
|
||||
if (!selection || selection.rangeCount === 0) {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
const range = selection.getRangeAt(0);
|
||||
const div = document.createElement('div');
|
||||
div.appendChild(range.cloneContents());
|
||||
return Promise.resolve(div.innerHTML);
|
||||
}
|
||||
|
||||
case "replaceSelectedText": {
|
||||
const selectedText = window.getSelection().toString();
|
||||
let force_insert = false;
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ export class mzta_Menus {
|
|||
//const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
return {tabId: tabs[0].id,
|
||||
selection: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" }),
|
||||
selection_html: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedHtml" }),
|
||||
text: await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" }),
|
||||
html: await browser.tabs.sendMessage(tabs[0].id, { command: "getFullHtml" }),
|
||||
only_typed_text: await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyTypedText", do_autoselect: do_autoselect }),
|
||||
|
|
@ -105,6 +106,7 @@ export class mzta_Menus {
|
|||
|
||||
let body_text = '';
|
||||
let selection_text = '';
|
||||
let selection_html = msg_text.selection_html;
|
||||
let only_typed_text = '';
|
||||
let only_quoted_text = '';
|
||||
only_typed_text = msg_text.only_typed_text.replace(/\s+/g, ' ').trim();
|
||||
|
|
@ -116,6 +118,7 @@ export class mzta_Menus {
|
|||
}
|
||||
only_quoted_text = msg_text.only_quoted_text.replace(/\s+/g, ' ').trim();
|
||||
curr_prompt.selection_text = selection_text;
|
||||
curr_prompt.selection_html = selection_html;
|
||||
body_text = msg_text.text.replace(/\s+/g, ' ').trim();
|
||||
curr_prompt.body_text = body_text;
|
||||
//open chatgpt window
|
||||
|
|
@ -141,7 +144,7 @@ export class mzta_Menus {
|
|||
break;
|
||||
}
|
||||
|
||||
fullPrompt = await taPromptUtils.preparePrompt(curr_prompt, curr_message, chatgpt_lang, selection_text, body_text, await getMailSubject(tabs[0]), msg_text, only_typed_text, only_quoted_text, tags_full_list);
|
||||
fullPrompt = await taPromptUtils.preparePrompt(curr_prompt, curr_message, chatgpt_lang, selection_text, selection_html, body_text, await getMailSubject(tabs[0]), msg_text, only_typed_text, only_quoted_text, tags_full_list);
|
||||
|
||||
switch(curr_prompt.id){
|
||||
case 'prompt_translate_this':
|
||||
|
|
|
|||
|
|
@ -91,6 +91,13 @@ const defaultPlaceholders = [
|
|||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'selected_html',
|
||||
name: "__MSG_placeholder_selected_html__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'additional_text',
|
||||
name: "__MSG_placeholder_additional_text__",
|
||||
|
|
@ -301,7 +308,7 @@ export const placeholdersUtils = {
|
|||
return regex.test(text);
|
||||
},
|
||||
|
||||
async getPlaceholdersValues(prompt_text, curr_message, mail_subject, body_text, msg_text, only_typed_text, only_quoted_text, selection_text, tags_full_list) {
|
||||
async getPlaceholdersValues(prompt_text, curr_message, mail_subject, body_text, msg_text, only_typed_text, only_quoted_text, selection_text, selection_html, tags_full_list) {
|
||||
let currPHs = await placeholdersUtils.extractPlaceholders(prompt_text);
|
||||
// console.log(">>>>>>>>>> currPHs: " + JSON.stringify(currPHs));
|
||||
let finalSubs = {};
|
||||
|
|
@ -331,6 +338,9 @@ export const placeholdersUtils = {
|
|||
case 'selected_text':
|
||||
finalSubs['selected_text'] = placeholdersUtils.failSafePlaceholders(selection_text);
|
||||
break;
|
||||
case 'selected_html':
|
||||
finalSubs['selected_html'] = placeholdersUtils.failSafePlaceholders(selection_html);
|
||||
break;
|
||||
case 'author':
|
||||
finalSubs['author'] = placeholdersUtils.failSafePlaceholders(curr_message.author);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@
|
|||
case "openai_comp_api":
|
||||
this.worker = new Worker(new URL('./workers/model-worker-openai_comp.js', import.meta.url), { type: 'module' });
|
||||
break;
|
||||
case "anthropic_api":
|
||||
this.worker = new Worker(new URL('./workers/model-worker-anthropic.js', import.meta.url), { type: 'module' });
|
||||
break;
|
||||
default:
|
||||
this.logger.log("Invalid LLM type: " + this.llm);
|
||||
throw new Error("Invalid LLM type: " + this.llm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +79,11 @@
|
|||
this.worker.postMessage({ type: 'init', openai_comp_host: prefs_api.openai_comp_host, openai_comp_model: prefs_api.openai_comp_model, openai_comp_api_key: prefs_api.openai_comp_api_key, openai_comp_use_v1: prefs_api.openai_comp_use_v1, do_debug: this.do_debug, i18nStrings: ''});
|
||||
break;
|
||||
}
|
||||
case "anthropic_api": {
|
||||
let prefs_api = await browser.storage.sync.get({anthropic_api_key: '', anthropic_model: '', anthropic_version: '2023-06-01', anthropic_max_tokens: 4096});
|
||||
this.worker.postMessage({ type: 'init', anthropic_api_key: prefs_api.anthropic_api_key, anthropic_model: prefs_api.anthropic_model, anthropic_version: prefs_api.anthropic_version, anthropic_max_tokens: prefs_api.anthropic_max_tokens, do_debug: this.do_debug, i18nStrings: ''});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export const taPromptUtils = {
|
|||
}
|
||||
},
|
||||
|
||||
async preparePrompt(curr_prompt, curr_message, chatgpt_lang, selection_text, body_text, subject_text, msg_text, only_typed_text, only_quoted_text, tags_full_list){
|
||||
async preparePrompt(curr_prompt, curr_message, chatgpt_lang, selection_text, selection_html, body_text, subject_text, msg_text, only_typed_text, only_quoted_text, tags_full_list){
|
||||
let fullPrompt = '';
|
||||
|
||||
if(!placeholdersUtils.hasPlaceholder(curr_prompt.text)){
|
||||
|
|
@ -37,7 +37,7 @@ export const taPromptUtils = {
|
|||
fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await taPromptUtils.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + (selection_text=='' ? body_text : selection_text) + "\" ";
|
||||
}else{
|
||||
// we have at least a placeholder, do the magic!
|
||||
let finalSubs = await placeholdersUtils.getPlaceholdersValues(curr_prompt.text, curr_message, subject_text, body_text, msg_text, only_typed_text, only_quoted_text, selection_text, tags_full_list);
|
||||
let finalSubs = await placeholdersUtils.getPlaceholdersValues(curr_prompt.text, curr_message, subject_text, body_text, msg_text, only_typed_text, only_quoted_text, selection_text, selection_html, tags_full_list);
|
||||
// console.log(">>>>>>>>>> finalSubs: " + JSON.stringify(finalSubs));
|
||||
let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
|
||||
fullPrompt = (placeholdersUtils.replacePlaceholders(curr_prompt.text, finalSubs, prefs_ph.placeholders_use_default_value, true) + (String(curr_prompt.need_signature) == "1" ? " " + await taPromptUtils.getDefaultSignature():"") + " " + chatgpt_lang).trim();
|
||||
|
|
|
|||
|
|
@ -350,21 +350,66 @@ export async function createTag(tag) {
|
|||
}
|
||||
}
|
||||
|
||||
export function checkIfTagExists(tag, tags_list) {
|
||||
return tags_list.hasOwnProperty("$ta-" + sanitizeString(tag));
|
||||
// export function checkIfTagExists(tag, tags_list) {
|
||||
// console.log(">>>>>>>>>>> checkIfTagExists tags_list: " + JSON.stringify(tags_list));
|
||||
// console.log(">>>>>>>>>>> checkIfTagExists tag: " + tag);
|
||||
// return tags_list.hasOwnProperty("$ta-" + sanitizeString(tag));
|
||||
// }
|
||||
|
||||
export function checkIfTagLabelExists(tag_label, tags_list) {
|
||||
// console.log(">>>>>>>>>>> checkIfTagExists tags_list: " + JSON.stringify(tags_list));
|
||||
// console.log(">>>>>>>>>>> checkIfTagExists tag_label: " + tag_label);
|
||||
const lowerTagLabel = tag_label.toLowerCase();
|
||||
return Object.values(tags_list).some(label => label.tag.toLowerCase() === lowerTagLabel);
|
||||
}
|
||||
|
||||
// export async function assignTagsToMessage(messageId, tags) {
|
||||
// console.log(">>>>>>>>>>> assignTagsToMessage messageId: tags: " + JSON.stringify(tags));
|
||||
// tags = tags.map(tag => `$ta-${sanitizeString(tag)}`);
|
||||
// let msg_prop = await browser.messages.get(messageId);
|
||||
// tags = tags.concat(msg_prop.tags || []);
|
||||
// try {
|
||||
// return browser.messages.update(messageId, {tags: tags});
|
||||
// } catch (error) {
|
||||
// console.error('[ThunderAI] Error assigning tag [messageId: ', messageId, ' - tag: ', tag, ']:', error);
|
||||
// }
|
||||
// }
|
||||
|
||||
export async function assignTagsToMessage(messageId, tags) {
|
||||
tags = tags.map(tag => `$ta-${sanitizeString(tag)}`);
|
||||
// console.log(">>>>>>>>>>> assignTagsToMessage tags: " + JSON.stringify(tags));
|
||||
let all_tags_list = await getTagsList();
|
||||
all_tags_list = all_tags_list[1];
|
||||
tags = getTagsKeyFromLabel(tags, all_tags_list);
|
||||
// console.log(">>>>>>>>>>> assignTagsToMessage tags after conversion: " + JSON.stringify(tags));
|
||||
let msg_prop = await browser.messages.get(messageId);
|
||||
// console.log(">>>>>>>>>>> assignTagsToMessage msg_prop.tags: " + JSON.stringify(msg_prop.tags));
|
||||
tags = tags.concat(msg_prop.tags || []);
|
||||
tags = [...new Set(tags)];
|
||||
// console.log(">>>>>>>>>>> assignTagsToMessage tags after concat: " + JSON.stringify(tags));
|
||||
try {
|
||||
return browser.messages.update(messageId, {tags: tags});
|
||||
await browser.messages.update(messageId, {tags: tags});
|
||||
return tags; // Return the updated tags for confirmation
|
||||
} catch (error) {
|
||||
console.error('[ThunderAI] Error assigning tag [messageId: ', messageId, ' - tag: ', tag, ']:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function getTagsKeyFromLabel(tag_names, all_tags_list) {
|
||||
const result = [];
|
||||
|
||||
tag_names.forEach(name => {
|
||||
const lowerName = name.toLowerCase();
|
||||
const match = Object.entries(all_tags_list).find(
|
||||
([, value]) => value.tag.toLowerCase() === lowerName
|
||||
);
|
||||
if (match) {
|
||||
result.push(match[0]);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function sanitizeString(input) {
|
||||
input = input.toLowerCase();
|
||||
// Define the regex to match valid characters
|
||||
|
|
@ -401,6 +446,21 @@ export async function transformTagsLabels(labels, tags_list) {
|
|||
return output;
|
||||
}
|
||||
|
||||
export function getAPIsInitMessageString(api_string, model_string = '', host_string = '', version_string = '') {
|
||||
let output = browser.i18n.getMessage("_api_connecting", api_string);
|
||||
if (model_string !== '') {
|
||||
output += "\n" + browser.i18n.getMessage("_api_connecting_model", model_string);
|
||||
}
|
||||
if (host_string !== '') {
|
||||
output += "\n" + browser.i18n.getMessage("_api_connecting_host", host_string);
|
||||
}
|
||||
if (version_string !== '') {
|
||||
output += "\n" + browser.i18n.getMessage("_api_connecting_version", version_string);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
export function getActiveSpecialPromptsIDs(args = {}) {
|
||||
const { addtags = false, get_calendar_event = false, get_task = false, is_chatgpt_web = false } = args;
|
||||
let output = [];
|
||||
|
|
@ -475,6 +535,7 @@ export function validateCustomData_ChatGPTWeb(event) {
|
|||
document.getElementById(event.target.id + '_info').style.color = is_valid ? '' : 'red';
|
||||
}
|
||||
|
||||
|
||||
// The following methods are a modified version derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/content_scripts/compose.js
|
||||
|
||||
const insertHtml = function (replyHtml, fullBody_string) {
|
||||
|
|
|
|||
148
js/workers/model-worker-anthropic.js
Normal file
148
js/workers/model-worker-anthropic.js
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 - 2025 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* This file contains a modified version of the code from the project at https://github.com/boxabirds/chatgpt-frontend-nobuild
|
||||
* The original code has been released under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
import { Anthropic } from '../api/anthropic.js';
|
||||
import { taLogger } from '../mzta-logger.js';
|
||||
|
||||
let anthropic_api_key = null;
|
||||
let anthropic_model = '';
|
||||
let anthropic = null;
|
||||
let stopStreaming = false;
|
||||
let i18nStrings = null;
|
||||
let do_debug = false;
|
||||
let taLog = null;
|
||||
|
||||
let conversationHistory = [];
|
||||
let assistantResponseAccumulator = '';
|
||||
|
||||
self.onmessage = async function(event) {
|
||||
if (event.data.type === 'init') {
|
||||
anthropic_api_key = event.data.anthropic_api_key;
|
||||
anthropic_model = event.data.anthropic_model;
|
||||
anthropic = new Anthropic(anthropic_api_key, event.data.anthropic_version, anthropic_model, event.data.anthropic_max_tokens, true);
|
||||
do_debug = event.data.do_debug;
|
||||
i18nStrings = event.data.i18nStrings;
|
||||
taLog = new taLogger('model-worker-anthropic', do_debug);
|
||||
} else if (event.data.type === 'chatMessage') {
|
||||
conversationHistory.push({ role: 'user', content: event.data.message });
|
||||
|
||||
const response = await anthropic.fetchResponse(conversationHistory);
|
||||
postMessage({ type: 'messageSent' });
|
||||
|
||||
if (!response.ok) {
|
||||
let error_message = '';
|
||||
let errorDetail = '';
|
||||
if(response.is_exception === true){
|
||||
error_message = response.error;
|
||||
}else{
|
||||
try{
|
||||
const errorJSON = await response.json();
|
||||
errorDetail = JSON.stringify(errorJSON);
|
||||
error_message = errorJSON.error.message;
|
||||
}catch(e){
|
||||
error_message = response.statusText;
|
||||
}
|
||||
taLog.log("error_message: " + JSON.stringify(error_message));
|
||||
}
|
||||
postMessage({ type: 'error', payload: i18nStrings["anthropic_api_request_failed"] + ": " + response.status + " " + response.statusText + ", Detail: " + error_message + " " + errorDetail });
|
||||
throw new Error("[ThunderAI] Anthropic API request failed: " + response.status + " " + response.statusText + ", Detail: " + error_message + " " + errorDetail);
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
let buffer = '';
|
||||
|
||||
while (true) {
|
||||
if (stopStreaming) {
|
||||
stopStreaming = false;
|
||||
reader.cancel();
|
||||
conversationHistory.push({ role: 'assistant', content: assistantResponseAccumulator });
|
||||
assistantResponseAccumulator = '';
|
||||
postMessage({ type: 'tokensDone' });
|
||||
break;
|
||||
}
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
conversationHistory.push({ role: 'assistant', content: assistantResponseAccumulator });
|
||||
assistantResponseAccumulator = '';
|
||||
postMessage({ type: 'tokensDone' });
|
||||
break;
|
||||
}
|
||||
// lots of low-level Anthropic response parsing stuff
|
||||
const chunk = decoder.decode(value);
|
||||
buffer += chunk;
|
||||
taLog.log("buffer " + buffer);
|
||||
const lines = buffer.split("\n");
|
||||
buffer = lines.pop();
|
||||
|
||||
for (const line of lines) {
|
||||
const cleanLine = line.trim();
|
||||
|
||||
// Ignore ping events
|
||||
if (cleanLine === '' || cleanLine.startsWith('event: ping')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove "data: " and parse the JSON
|
||||
if (cleanLine.startsWith('data: ')) {
|
||||
const jsonPart = cleanLine.replace(/^data: /, '');
|
||||
let parsedData = null;
|
||||
|
||||
try {
|
||||
parsedData = JSON.parse(jsonPart);
|
||||
} catch (e) {
|
||||
taLog.error("JSON parse error: " + e);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Events handling
|
||||
switch (parsedData.type) {
|
||||
case 'content_block_delta':
|
||||
if (parsedData.delta && parsedData.delta.text) {
|
||||
const token = parsedData.delta.text;
|
||||
assistantResponseAccumulator += token;
|
||||
postMessage({ type: 'newToken', payload: { token } });
|
||||
}
|
||||
break;
|
||||
|
||||
case 'content_block_start':
|
||||
// optional
|
||||
break;
|
||||
|
||||
case 'message_start':
|
||||
// optional
|
||||
break;
|
||||
|
||||
case 'message_stop':
|
||||
conversationHistory.push({ role: 'assistant', content: assistantResponseAccumulator });
|
||||
assistantResponseAccumulator = '';
|
||||
postMessage({ type: 'tokensDone' });
|
||||
return; // end the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (event.data.type === 'stop') {
|
||||
stopStreaming = true;
|
||||
}
|
||||
};
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "ThunderAI",
|
||||
"description": "__MSG_extensionDescription__",
|
||||
"version": "3.4.1",
|
||||
"version": "3.5.0",
|
||||
"author": "Mic (m@micz.it)",
|
||||
"homepage_url": "https://micz.it/thunderbird-addon-thunderai/",
|
||||
"browser_specific_settings": {
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
"messagesUpdate",
|
||||
"messagesMove",
|
||||
"https://*.chatgpt.com/*",
|
||||
"https://*.anthropic.com/*",
|
||||
"<all_urls>"
|
||||
],
|
||||
"background": {
|
||||
|
|
@ -54,6 +55,9 @@
|
|||
},
|
||||
"commands": {
|
||||
"_thunderai__do_action": {
|
||||
"suggested_key": {
|
||||
"default": "Ctrl+Alt+A"
|
||||
},
|
||||
"description": "Opens the ThunderAI prompts menu"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,12 +20,13 @@ import { mzta_script } from './js/mzta-chatgpt.js';
|
|||
import { prefs_default } from './options/mzta-options-default.js';
|
||||
import { mzta_Menus } from './js/mzta-menus.js';
|
||||
import { taLogger } from './js/mzta-logger.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, stripHtmlKeepLines } from './js/mzta-utils.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagLabelExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, stripHtmlKeepLines } from './js/mzta-utils.js';
|
||||
import { taPromptUtils } from './js/mzta-utils-prompt.js';
|
||||
import { mzta_specialCommand } from './js/mzta-special-commands.js';
|
||||
import { getSpamFilterPrompt } from './js/mzta-prompts.js';
|
||||
import { taSpamReport } from './js/mzta-spamreport.js';
|
||||
import { taWorkingStatus } from './js/mzta-working-status.js';
|
||||
import { addTags_getExclusionList } from './js/mzta-addatags-exclusion-list.js';
|
||||
|
||||
browser.runtime.onInstalled.addListener(({ reason, previousVersion }) => {
|
||||
// console.log(">>>>>>>>>>> onInstalled: " + JSON.stringify(reason) + ", previousVersion: " + previousVersion);
|
||||
|
|
@ -94,18 +95,6 @@ browser.contentScripts.register({
|
|||
runAt: "document_idle"
|
||||
});
|
||||
|
||||
let ThunderAI_Shortcut = "Ctrl+Alt+A";
|
||||
|
||||
// Shortcut
|
||||
messenger.commands.update({
|
||||
name: "_thunderai__do_action",
|
||||
shortcut: ThunderAI_Shortcut
|
||||
}).then(() => {
|
||||
taLog.log('Shortcut [' + ThunderAI_Shortcut + '] registered successfully!');
|
||||
}).catch((error) => {
|
||||
taLog.error('Error registering shortcut [' + ThunderAI_Shortcut + ']: ' + error);
|
||||
});
|
||||
|
||||
// Listen for shortcut command
|
||||
messenger.commands.onCommand.addListener((command, tab) => {
|
||||
if (command === "_thunderai__do_action") {
|
||||
|
|
@ -172,16 +161,26 @@ async function _assign_tags(_data, create_new_tags = true) {
|
|||
// console.log(">>>>>>>>>>>>>>> all_tags_list: " + JSON.stringify(all_tags_list));
|
||||
taLog.log("assign_tags data: " + JSON.stringify(_data));
|
||||
let new_tags = [];
|
||||
for (const tag of _data.tags) {
|
||||
// console.log(">>>>>>>>>>>>>>> tag: " + tag);
|
||||
if (create_new_tags && !checkIfTagExists(tag, all_tags_list)) {
|
||||
let add_tags_exclusions_list = await addTags_getExclusionList();
|
||||
taLog.log("add_tags_exclusions_list: " + JSON.stringify(add_tags_exclusions_list));
|
||||
const tags_final = _data.tags.filter(tag =>
|
||||
!add_tags_exclusions_list.some(exclusion =>
|
||||
tag.toLowerCase().includes(exclusion.toLowerCase())
|
||||
)
|
||||
);
|
||||
if(!create_new_tags){
|
||||
taLog.log("Not creating new tags, only assigning existing ones...");
|
||||
}
|
||||
for (const tag of tags_final) {
|
||||
// console.log(">>>>>>>>>>>>>>> tag: " + JSON.stringify(tag));
|
||||
if (create_new_tags && !checkIfTagLabelExists(tag, all_tags_list)) {
|
||||
taLog.log("Creating tag: " + tag);
|
||||
await createTag(tag);
|
||||
}
|
||||
new_tags.push(tag);
|
||||
}
|
||||
await assignTagsToMessage(_data.messageId, new_tags);
|
||||
taLog.log("Assigned tags: " + JSON.stringify(new_tags));
|
||||
let added_tags = await assignTagsToMessage(_data.messageId, new_tags);
|
||||
taLog.log("Assigned tags: " + JSON.stringify(added_tags));
|
||||
}
|
||||
|
||||
messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
|
|
@ -326,8 +325,12 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
//console.log(">>>>>>>>>>>>>>>> prefs: " + JSON.stringify(prefs));
|
||||
// console.log(">>>>>>>>>>>>>>>> prompt_info: " + JSON.stringify(prompt_info));
|
||||
taLog.log("Prompt length: " + promptText.length);
|
||||
if(promptText.length > prefs.max_prompt_length){
|
||||
// Prompt too long for ChatGPT
|
||||
let _max_prompt_length = prefs.max_prompt_length;
|
||||
if(prefs.connection_type == 'chatgpt_web'){
|
||||
_max_prompt_length = prefs_default.max_prompt_length;
|
||||
}
|
||||
if((_max_prompt_length > 0) && (promptText.length > _max_prompt_length)){
|
||||
// Prompt too long
|
||||
let tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
browser.tabs.sendMessage(curr_tabId, { command: "sendAlert", curr_tab_type: tabs[0].type, message: browser.i18n.getMessage('msg_prompt_too_long') });
|
||||
return;
|
||||
|
|
@ -337,207 +340,212 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
|
||||
switch(prefs.connection_type){
|
||||
case 'chatgpt_web':
|
||||
// We are using the ChatGPT web interface
|
||||
{
|
||||
// We are using the ChatGPT web interface
|
||||
|
||||
let rand_call_id = '_chatgptweb_' + generateCallID();
|
||||
let call_opt = '';
|
||||
let rand_call_id = '_chatgptweb_' + generateCallID();
|
||||
let call_opt = '';
|
||||
|
||||
let _wait_time = 1000;
|
||||
let _base_url = "https://chatgpt.com";
|
||||
let _webproject_set = false;
|
||||
let _custom_gpt_set = false;
|
||||
let _use_prompt_info_custom_gpt = false;
|
||||
let _custom_model = sanitizeChatGPTModelData(prompt_info.chatgpt_web_model != '' ? prompt_info.chatgpt_web_model : prefs.chatgpt_web_model);
|
||||
let _web_project = sanitizeChatGPTWebCustomData(prompt_info.chatgpt_web_project != '' ? prompt_info.chatgpt_web_project : prefs.chatgpt_web_project)
|
||||
let _custom_gpt = sanitizeChatGPTWebCustomData(prompt_info.chatgpt_web_custom_gpt != '' ? prompt_info.chatgpt_web_custom_gpt : prefs.chatgpt_web_custom_gpt)
|
||||
let _wait_time = 1000;
|
||||
let _base_url = "https://chatgpt.com";
|
||||
let _webproject_set = false;
|
||||
let _custom_gpt_set = false;
|
||||
let _use_prompt_info_custom_gpt = false;
|
||||
let _custom_model = sanitizeChatGPTModelData(prompt_info.chatgpt_web_model != '' ? prompt_info.chatgpt_web_model : prefs.chatgpt_web_model);
|
||||
let _web_project = sanitizeChatGPTWebCustomData(prompt_info.chatgpt_web_project != '' ? prompt_info.chatgpt_web_project : prefs.chatgpt_web_project)
|
||||
let _custom_gpt = sanitizeChatGPTWebCustomData(prompt_info.chatgpt_web_custom_gpt != '' ? prompt_info.chatgpt_web_custom_gpt : prefs.chatgpt_web_custom_gpt)
|
||||
|
||||
if(prefs.chatgpt_web_tempchat){
|
||||
call_opt += '&temporary-chat=true';
|
||||
}
|
||||
if(prefs.chatgpt_web_tempchat){
|
||||
call_opt += '&temporary-chat=true';
|
||||
}
|
||||
|
||||
if((prompt_info.chatgpt_web_model != '') || (prefs.chatgpt_web_model != '')){
|
||||
call_opt += '&model=' + _custom_model;
|
||||
}
|
||||
if((prompt_info.chatgpt_web_model != '') || (prefs.chatgpt_web_model != '')){
|
||||
call_opt += '&model=' + _custom_model;
|
||||
}
|
||||
|
||||
taLog.log("[chatgpt_web] call_opt: " + call_opt);
|
||||
taLog.log("[chatgpt_web] call_opt: " + call_opt);
|
||||
|
||||
// If there is a custom gpt on the prompt, but also a web_project on the prefs, we need to use the custom gpt
|
||||
_use_prompt_info_custom_gpt = (prompt_info.chatgpt_web_custom_gpt != '' && prompt_info.chatgpt_web_project == '');
|
||||
// If there is a custom gpt on the prompt, but also a web_project on the prefs, we need to use the custom gpt
|
||||
_use_prompt_info_custom_gpt = (prompt_info.chatgpt_web_custom_gpt != '' && prompt_info.chatgpt_web_project == '');
|
||||
|
||||
if(!_use_prompt_info_custom_gpt && ((prompt_info.chatgpt_web_project != '') || (prefs.chatgpt_web_project != ''))){
|
||||
_base_url += _web_project;
|
||||
_webproject_set = true;
|
||||
_wait_time = 2000;
|
||||
}
|
||||
if(!_webproject_set && ((prompt_info.chatgpt_web_custom_gpt != '') || (prefs.chatgpt_web_custom_gpt != ''))){
|
||||
_base_url += _custom_gpt;
|
||||
_custom_gpt_set = true;
|
||||
}
|
||||
if(!_use_prompt_info_custom_gpt && ((prompt_info.chatgpt_web_project != '') || (prefs.chatgpt_web_project != ''))){
|
||||
_base_url += _web_project;
|
||||
_webproject_set = true;
|
||||
_wait_time = 2000;
|
||||
}
|
||||
if(!_webproject_set && ((prompt_info.chatgpt_web_custom_gpt != '') || (prefs.chatgpt_web_custom_gpt != ''))){
|
||||
_base_url += _custom_gpt;
|
||||
_custom_gpt_set = true;
|
||||
}
|
||||
|
||||
let win_options = {
|
||||
url: _base_url + "?call_id=" + rand_call_id + call_opt,
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
taLog.log("[chatgpt_web] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
let win_options = {
|
||||
url: _base_url + "?call_id=" + rand_call_id + call_opt,
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
taLog.log("[chatgpt_web] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options.width = prefs.chatgpt_win_width,
|
||||
win_options.height = prefs.chatgpt_win_height
|
||||
}
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options.width = prefs.chatgpt_win_width,
|
||||
win_options.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
const listener = (message, sender, sendResponse) => {
|
||||
async function handleChatGptWeb(createdTab) {
|
||||
taLog.log("ChatGPT web interface script started...");
|
||||
const listener = (message, sender, sendResponse) => {
|
||||
async function handleChatGptWeb(createdTab) {
|
||||
taLog.log("ChatGPT web interface script started...");
|
||||
|
||||
let _gpt_model = getGPTWebModelString(_custom_model);
|
||||
let _gpt_model = getGPTWebModelString(_custom_model);
|
||||
|
||||
taLog.log("_custom_model: " + _custom_model);
|
||||
taLog.log("_gpt_model: " + _gpt_model);
|
||||
taLog.log("_custom_model: " + _custom_model);
|
||||
taLog.log("_gpt_model: " + _gpt_model);
|
||||
|
||||
let originalText = prompt_info.selection_text;
|
||||
if((originalText == null) || (originalText == "")) {
|
||||
originalText = prompt_info.body_text;
|
||||
let originalText = prompt_info.selection_text;
|
||||
if((originalText == null) || (originalText == "")) {
|
||||
originalText = prompt_info.body_text;
|
||||
}
|
||||
//console.log(">>>>>>>>>> prompt_info: " + JSON.stringify(prompt_info));
|
||||
let pre_script = `let mztaWinId = `+ createdTab.windowId +`;
|
||||
let mztaStatusPageDesc="`+ browser.i18n.getMessage("prefs_status_page") +`";
|
||||
let mztaForceCompletionDesc="`+ browser.i18n.getMessage("chatgpt_force_completion") +`";
|
||||
let mztaForceCompletionTitle="`+ browser.i18n.getMessage("chatgpt_force_completion_title") +`";
|
||||
let mztaDoCustomText=`+ do_custom_text +`;
|
||||
let mztaPromptName="[`+ i18nConditionalGet(prompt_name) +`]";
|
||||
let mztaPhDefVal="`+(prefs.placeholders_use_default_value?'1':'0')+`";
|
||||
let mztaGPTModel="`+ (_custom_gpt_set ? '' : _gpt_model) +`";
|
||||
let mztaDoDebug="`+(prefs.do_debug?'1':'0')+`";
|
||||
let mztaUseDiffViewer="`+(prompt_info.use_diff_viewer=='1'?'1':'0')+`";
|
||||
let mztaOriginalText="`+ JSON.stringify(originalText).slice(1, -1) +`";
|
||||
`;
|
||||
|
||||
taLog.log("Waiting " + _wait_time + " millisec");
|
||||
await new Promise(resolve => setTimeout(resolve, _wait_time));
|
||||
taLog.log("Waiting " + _wait_time + " millisec done");
|
||||
|
||||
await browser.tabs.executeScript(createdTab.id, { code: pre_script + mzta_script, matchAboutBlank: false });
|
||||
// let mailMessage = await browser.messageDisplay.getDisplayedMessage(curr_tabId);
|
||||
let mailMessageId = -1;
|
||||
if(mailMessage) mailMessageId = mailMessage.id;
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "chatgpt_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId});
|
||||
taLog.log('[ChatGPT Web] Connection succeded!');
|
||||
taLog.log("[ThunderAI] ChatGPT Web script injected successfully");
|
||||
browser.runtime.onMessage.removeListener(listener);
|
||||
}
|
||||
//console.log(">>>>>>>>>> prompt_info: " + JSON.stringify(prompt_info));
|
||||
let pre_script = `let mztaWinId = `+ createdTab.windowId +`;
|
||||
let mztaStatusPageDesc="`+ browser.i18n.getMessage("prefs_status_page") +`";
|
||||
let mztaForceCompletionDesc="`+ browser.i18n.getMessage("chatgpt_force_completion") +`";
|
||||
let mztaForceCompletionTitle="`+ browser.i18n.getMessage("chatgpt_force_completion_title") +`";
|
||||
let mztaDoCustomText=`+ do_custom_text +`;
|
||||
let mztaPromptName="[`+ i18nConditionalGet(prompt_name) +`]";
|
||||
let mztaPhDefVal="`+(prefs.placeholders_use_default_value?'1':'0')+`";
|
||||
let mztaGPTModel="`+ (_custom_gpt_set ? '' : _gpt_model) +`";
|
||||
let mztaDoDebug="`+(prefs.do_debug?'1':'0')+`";
|
||||
let mztaUseDiffViewer="`+(prompt_info.use_diff_viewer=='1'?'1':'0')+`";
|
||||
let mztaOriginalText="`+ JSON.stringify(originalText).slice(1, -1) +`";
|
||||
`;
|
||||
|
||||
if (message.command === "chatgpt_web_ready_" + rand_call_id) {
|
||||
return handleChatGptWeb(sender.tab)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
taLog.log("Waiting " + _wait_time + " millisec");
|
||||
await new Promise(resolve => setTimeout(resolve, _wait_time));
|
||||
taLog.log("Waiting " + _wait_time + " millisec done");
|
||||
|
||||
await browser.tabs.executeScript(createdTab.id, { code: pre_script + mzta_script, matchAboutBlank: false });
|
||||
// let mailMessage = await browser.messageDisplay.getDisplayedMessage(curr_tabId);
|
||||
let mailMessageId = -1;
|
||||
if(mailMessage) mailMessageId = mailMessage.id;
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "chatgpt_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId});
|
||||
taLog.log('[ChatGPT Web] Connection succeded!');
|
||||
taLog.log("[ThunderAI] ChatGPT Web script injected successfully");
|
||||
browser.runtime.onMessage.removeListener(listener);
|
||||
}
|
||||
|
||||
if (message.command === "chatgpt_web_ready_" + rand_call_id) {
|
||||
return handleChatGptWeb(sender.tab)
|
||||
}
|
||||
return false;
|
||||
browser.runtime.onMessage.addListener(listener);
|
||||
await browser.windows.create(win_options);
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener(listener);
|
||||
await browser.windows.create(win_options);
|
||||
break; // chatgpt_web - END
|
||||
|
||||
case 'chatgpt_api':
|
||||
case 'chatgpt_api':
|
||||
{
|
||||
// We are using the ChatGPT API
|
||||
|
||||
let rand_call_id2 = '_openai_' + generateCallID();
|
||||
let rand_call_id2 = '_openai_' + generateCallID();
|
||||
|
||||
const listener2 = (message, sender, sendResponse) => {
|
||||
const listener2 = (message, sender, sendResponse) => {
|
||||
|
||||
function handleChatGptApi(createdTab) {
|
||||
let mailMessageId2 = -1;
|
||||
if(mailMessage) mailMessageId2 = mailMessage.id;
|
||||
function handleChatGptApi(createdTab) {
|
||||
let mailMessageId2 = -1;
|
||||
if(mailMessage) mailMessageId2 = mailMessage.id;
|
||||
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.chatgpt_api_key == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('chatgpt_empty_apikey')});
|
||||
return;
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.chatgpt_api_key == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('chatgpt_empty_apikey')});
|
||||
return;
|
||||
}
|
||||
if (prefs.chatgpt_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('chatgpt_empty_model')});
|
||||
return;
|
||||
}
|
||||
//console.log(">>>>>>>>>> sender: " + JSON.stringify(sender));
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId2, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[OpenAI ChatGPT] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener2);
|
||||
}
|
||||
if (prefs.chatgpt_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('chatgpt_empty_model')});
|
||||
return;
|
||||
|
||||
if (message.command === "openai_api_ready_"+rand_call_id2) {
|
||||
return handleChatGptApi(sender.tab);
|
||||
}
|
||||
//console.log(">>>>>>>>>> sender: " + JSON.stringify(sender));
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId2, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[OpenAI ChatGPT] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener2);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.command === "openai_api_ready_"+rand_call_id2) {
|
||||
return handleChatGptApi(sender.tab);
|
||||
browser.runtime.onMessage.addListener(listener2);
|
||||
|
||||
let win_options2 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id2+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
return false;
|
||||
|
||||
taLog.log("[chatgpt_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options2.width = prefs.chatgpt_win_width,
|
||||
win_options2.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options2);
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener(listener2);
|
||||
|
||||
let win_options2 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id2+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
taLog.log("[chatgpt_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options2.width = prefs.chatgpt_win_width,
|
||||
win_options2.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options2);
|
||||
|
||||
break; // chatgpt_api - END
|
||||
|
||||
case 'google_gemini_api':
|
||||
// We are using the Google Gemini API
|
||||
{
|
||||
// We are using the Google Gemini API
|
||||
|
||||
let rand_call_id5 = '_google_gemini_' + generateCallID();
|
||||
let rand_call_id5 = '_google_gemini_' + generateCallID();
|
||||
|
||||
const listener5 = (message, sender, sendResponse) => {
|
||||
const listener5 = (message, sender, sendResponse) => {
|
||||
|
||||
function handleChatGptApi(createdTab) {
|
||||
let mailMessageId5 = -1;
|
||||
if(mailMessage) mailMessageId5 = mailMessage.id;
|
||||
function handleChatGptApi(createdTab) {
|
||||
let mailMessageId5 = -1;
|
||||
if(mailMessage) mailMessageId5 = mailMessage.id;
|
||||
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.google_gemini_api_key == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('google_gemini_empty_apikey')});
|
||||
return;
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.google_gemini_api_key == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('google_gemini_empty_apikey')});
|
||||
return;
|
||||
}
|
||||
if (prefs.google_gemini_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('google_gemini_empty_model')});
|
||||
return;
|
||||
}
|
||||
//console.log(">>>>>>>>>> sender: " + JSON.stringify(sender));
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId5, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[Google Gemini] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener5);
|
||||
}
|
||||
if (prefs.google_gemini_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('google_gemini_empty_model')});
|
||||
return;
|
||||
|
||||
if (message.command === "google_gemini_api_ready_"+rand_call_id5) {
|
||||
return handleChatGptApi(sender.tab);
|
||||
}
|
||||
//console.log(">>>>>>>>>> sender: " + JSON.stringify(sender));
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId5, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[Google Gemini] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener5);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.command === "google_gemini_api_ready_"+rand_call_id5) {
|
||||
return handleChatGptApi(sender.tab);
|
||||
browser.runtime.onMessage.addListener(listener5);
|
||||
|
||||
let win_options5 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id5+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
return false;
|
||||
|
||||
taLog.log("[google_gemini_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options5.width = prefs.chatgpt_win_width,
|
||||
win_options5.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options5);
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener(listener5);
|
||||
|
||||
let win_options5 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id5+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
taLog.log("[google_gemini_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options5.width = prefs.chatgpt_win_width,
|
||||
win_options5.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options5);
|
||||
|
||||
break; // google_gemini_api - END
|
||||
|
||||
case 'ollama_api':
|
||||
{
|
||||
// We are using the Ollama API
|
||||
|
||||
taLog.log("Ollama API window opening...");
|
||||
|
|
@ -592,61 +600,119 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
|
||||
await browser.windows.create(win_options3);
|
||||
|
||||
break; // ollama_api - END
|
||||
}
|
||||
break; // ollama_api - END
|
||||
|
||||
case 'openai_comp_api':
|
||||
// We are using the OpenAI Comp API
|
||||
|
||||
let rand_call_id4 = '_openai_comp_api_' + generateCallID();
|
||||
case 'openai_comp_api':
|
||||
{
|
||||
// We are using the OpenAI Comp API
|
||||
|
||||
let rand_call_id4 = '_openai_comp_api_' + generateCallID();
|
||||
|
||||
|
||||
const listener4 = (message, sender, sendResponse) => {
|
||||
|
||||
const listener4 = (message, sender, sendResponse) => {
|
||||
|
||||
function handleOpenAICompApi(createdTab) {
|
||||
let mailMessageId4 = -1;
|
||||
if(mailMessage) mailMessageId4 = mailMessage.id;
|
||||
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.openai_comp_host == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('OpenAIComp_empty_host')});
|
||||
return;
|
||||
}
|
||||
if (prefs.openai_comp_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('OpenAIComp_empty_model')});
|
||||
return;
|
||||
}
|
||||
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId4, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[OpenAI Comp API] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener4);
|
||||
function handleOpenAICompApi(createdTab) {
|
||||
let mailMessageId4 = -1;
|
||||
if(mailMessage) mailMessageId4 = mailMessage.id;
|
||||
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.openai_comp_host == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('OpenAIComp_empty_host')});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.command === "openai_comp_api_ready_"+rand_call_id4) {
|
||||
return handleOpenAICompApi(sender.tab);
|
||||
if (prefs.openai_comp_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('OpenAIComp_empty_model')});
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener(listener4);
|
||||
|
||||
let win_options4 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id4+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId4, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[OpenAI Comp API] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener4);
|
||||
}
|
||||
|
||||
taLog.log("[openai_comp_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options4.width = prefs.chatgpt_win_width,
|
||||
win_options4.height = prefs.chatgpt_win_height
|
||||
if (message.command === "openai_comp_api_ready_"+rand_call_id4) {
|
||||
return handleOpenAICompApi(sender.tab);
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options4);
|
||||
|
||||
break; // openai_comp_api - END
|
||||
default:
|
||||
taLog.error("Unknown API connection type: " + prefs.connection_type);
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener(listener4);
|
||||
|
||||
let win_options4 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id4+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
taLog.log("[openai_comp_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options4.width = prefs.chatgpt_win_width,
|
||||
win_options4.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options4);
|
||||
}
|
||||
break; // openai_comp_api - END
|
||||
|
||||
case 'anthropic_api':
|
||||
{
|
||||
// We are using the Anthropic API
|
||||
|
||||
let rand_call_id5 = '_anthropic_' + generateCallID();
|
||||
|
||||
const listener5 = (message, sender, sendResponse) => {
|
||||
|
||||
function handleAnthropicApi(createdTab) {
|
||||
let mailMessageId5 = -1;
|
||||
if(mailMessage) mailMessageId5 = mailMessage.id;
|
||||
|
||||
// check if the config is present, or give a message error
|
||||
if (prefs.anthropic_api_key == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('anthropic_empty_apikey')});
|
||||
return;
|
||||
}
|
||||
if (prefs.anthropic_model == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('anthropic_empty_model')});
|
||||
return;
|
||||
}
|
||||
if (prefs.anthropic_version == '') {
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_error", error: browser.i18n.getMessage('anthropic_empty_version')});
|
||||
return;
|
||||
}
|
||||
//console.log(">>>>>>>>>> sender: " + JSON.stringify(sender));
|
||||
browser.tabs.sendMessage(createdTab.id, { command: "api_send", prompt: promptText, action: action, tabId: curr_tabId, mailMessageId: mailMessageId5, do_custom_text: do_custom_text, prompt_info: prompt_info});
|
||||
taLog.log('[OpenAI ChatGPT] Connection succeded!');
|
||||
browser.runtime.onMessage.removeListener(listener5);
|
||||
}
|
||||
|
||||
if (message.command === "anthropic_api_ready_"+rand_call_id5) {
|
||||
return handleAnthropicApi(sender.tab);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener(listener5);
|
||||
|
||||
let win_options5 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id5+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
taLog.log("[chatgpt_api] prefs.chatgpt_win_width: " + prefs.chatgpt_win_width + ", prefs.chatgpt_win_height: " + prefs.chatgpt_win_height);
|
||||
|
||||
if((prefs.chatgpt_win_width != '') && (prefs.chatgpt_win_height != '') && (prefs.chatgpt_win_width != 0) && (prefs.chatgpt_win_height != 0)){
|
||||
win_options5.width = prefs.chatgpt_win_width,
|
||||
win_options5.height = prefs.chatgpt_win_height
|
||||
}
|
||||
|
||||
await browser.windows.create(win_options5);
|
||||
}
|
||||
break; // anthropic_api - END
|
||||
|
||||
default:
|
||||
taLog.error("Unknown API connection type: " + prefs.connection_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -863,7 +929,9 @@ const newEmailListener = (folder, messagesList) => {
|
|||
|
||||
taSpamReport.logger = taLog;
|
||||
|
||||
await processEmails(messages, prefs_init.add_tags_auto, prefs_init.spamfilter);
|
||||
let add_tags_auto_enabled = prefs_init.add_tags && prefs_init.add_tags_auto;
|
||||
|
||||
await processEmails(messages, add_tags_auto_enabled, prefs_init.spamfilter);
|
||||
|
||||
if(prefs_init.spamfilter){
|
||||
taSpamReport.truncReportData();
|
||||
|
|
@ -900,6 +968,7 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
|
|||
let specialFullPrompt_add_tags = '';
|
||||
let curr_prompt_add_tags = menus.allPrompts.find(p => p.id === 'prompt_add_tags');
|
||||
let tags_full_list = await getTagsList();
|
||||
// console.log(">>>>>>>>>>>>> curr_prompt_add_tags: " + curr_prompt_add_tags);
|
||||
let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_add_tags);
|
||||
specialFullPrompt_add_tags = await taPromptUtils.preparePrompt(curr_prompt_add_tags, message, chatgpt_lang, '', body_text, curr_fullMessage.headers.subject, msg_text, '', tags_full_list);
|
||||
specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang);
|
||||
|
|
@ -926,6 +995,7 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
|
|||
}
|
||||
}
|
||||
let curr_prompt_spamfilter = await getSpamFilterPrompt();
|
||||
// console.log(">>>>>>>>>>>>> curr_prompt_spamfilter: " + curr_prompt_spamfilter);
|
||||
let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_spamfilter);
|
||||
let specialFullPrompt_spamfilter = await taPromptUtils.preparePrompt(curr_prompt_spamfilter, message, chatgpt_lang, '', body_text, curr_fullMessage.headers.subject, msg_text, '', '');
|
||||
taLog.log("Special prompt: " + specialFullPrompt_spamfilter);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const prefs_default = {
|
|||
chatgpt_win_width: 700,
|
||||
default_chatgpt_lang: '',
|
||||
default_sign_name: '',
|
||||
reply_type: 'reply_all',
|
||||
composing_plain_text: false,
|
||||
connection_type: 'chatgpt_web', //Other values: 'chatgpt_api', 'ollama_api', 'openai_comp_api', 'google_gemini_api'
|
||||
chatgpt_web_model: '',
|
||||
|
|
@ -42,6 +43,10 @@ export const prefs_default = {
|
|||
google_gemini_api_key: '',
|
||||
google_gemini_model: '',
|
||||
google_gemini_system_instruction: '',
|
||||
anthropic_api_key: '',
|
||||
anthropic_model: '',
|
||||
anthropic_version: '2023-06-01',
|
||||
anthropic_max_tokens: 4096,
|
||||
dynamic_menu_force_enter: false,
|
||||
dynamic_menu_order_alphabet: true,
|
||||
placeholders_use_default_value: false,
|
||||
|
|
|
|||
|
|
@ -120,6 +120,10 @@ tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{
|
|||
background-color: rgb(233, 238, 169);
|
||||
}
|
||||
|
||||
tr.conntype_anthropic_api, tr.conntype_anthropic_api2{
|
||||
background-color: rgb(255, 168, 204);
|
||||
}
|
||||
|
||||
#chatgpt_model_fetch_loading{
|
||||
display: none;
|
||||
font-style: italic;
|
||||
|
|
@ -178,6 +182,11 @@ input.option-input[type="text"]{
|
|||
font-style: italic;
|
||||
}
|
||||
|
||||
#anthropic_model_fetch_loading{
|
||||
display: none;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#owl_warning{
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -265,6 +274,10 @@ input.option-input[type="text"]{
|
|||
background-color: rgb(72, 77, 3);
|
||||
}
|
||||
|
||||
tr.conntype_anthropic_api, tr.conntype_anthropic_api2{
|
||||
background-color: rgb(83, 0, 35);
|
||||
}
|
||||
|
||||
.api_key-container .toggle-icon img {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@
|
|||
<option value="chatgpt_web">__MSG_prefs_Connection_type_ChatGPT_Web__</option>
|
||||
<option value="chatgpt_api">__MSG_prefs_Connection_type_ChatGPT_API__</option>
|
||||
<option value="google_gemini_api">__MSG_prefs_Connection_type_Google_Gemini_API__</option>
|
||||
<option value="anthropic_api">__MSG_prefs_Connection_type_Anthropic_API__</option>
|
||||
<option value="ollama_api">__MSG_prefs_Connection_type_Ollama_API__</option>
|
||||
<option value="openai_comp_api">__MSG_prefs_Connection_type_OpenAI_Comp_API__</option>
|
||||
</select>
|
||||
|
|
@ -313,6 +314,18 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_openai_comp_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_OpenAIComp_AvailableServices__</span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<select id="openai_comp_services_shortcut">
|
||||
</select>
|
||||
<br>__MSG_prefs_OpenAIComp_AvailableServices_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_openai_comp_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_API_Host__</span>
|
||||
|
|
@ -321,7 +334,7 @@
|
|||
<td>
|
||||
<label>
|
||||
<input type="text" id="openai_comp_host" name="openai_comp_host" class="option-input" />
|
||||
<br><i class="small_info">__MSG_prefs_OptionText_openai_comp_info_remote__</i>
|
||||
<br>__MSG_prefs_OptionText_openai_comp_info_remote__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -384,11 +397,61 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_anthropic_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_Anthropic_API_Key__</span>
|
||||
</label></td>
|
||||
<td>
|
||||
<div class="api_key-container">
|
||||
<label>
|
||||
<input type="password" id="anthropic_api_key" name="anthropic_api_key" class="option-input"/>
|
||||
</label>
|
||||
<span class="toggle-icon" id="toggle_anthropic_api_key"><img src="../images/pwd-show.png" id="pwd-icon_anthropic_api_key"></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_anthropic_api">
|
||||
<td>
|
||||
<label>
|
||||
<span class="opt_title">__MSG_Anthropic_Models__</span>
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
<button id="btnUpdateAnthropicModels">__MSG_Anthropic_Models_Fetch__</button> <span id="anthropic_model_fetch_loading">__MSG_Loading__</span><br>
|
||||
<label>
|
||||
<select id="anthropic_model" name="anthropic_model" class="option-input">
|
||||
</select>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_anthropic_api">
|
||||
<td>
|
||||
<label>
|
||||
<span class="opt_title">__MSG_Anthropic_Version__</span>
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="text" id="anthropic_version" name="anthropic_version" class="option-input" />
|
||||
<br>__MSG_Anthropic_Version_Info__ <a href="https://docs.anthropic.com/en/api/versioning">https://docs.anthropic.com/en/api/versioning</a>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_anthropic_api">
|
||||
<td><span class="opt_title">__MSG_prefs_OptionText_anthropic_max_tokens__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="anthropic_max_tokens" name="anthropic_max_tokens" class="option-input" />
|
||||
<br>__MSG_prefs_OptionText_anthropic_max_tokens_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="max_prompt_length_tr">
|
||||
<td><span class="opt_title">__MSG_prefs_OptionText_max_prompt_length__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="max_prompt_length" name="max_prompt_length" class="option-input" />
|
||||
<button type="button" id="reset_max_prompt_length" class="btn_small" style="margin-left:0.5em;">__MSG_reset_default__</button>
|
||||
<br>__MSG_prefs_OptionText_max_prompt_length_Info__
|
||||
</label>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ import { OpenAI } from '../js/api/openai.js';
|
|||
import { Ollama } from '../js/api/ollama.js';
|
||||
import { OpenAIComp } from '../js/api/openai_comp.js'
|
||||
import { GoogleGemini } from '../js/api/google_gemini.js';
|
||||
import { Anthropic } from '../js/api/anthropic.js';
|
||||
import { ChatGPTWeb_models, checkSparksPresence, isThunderbird128OrGreater, openTab, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML } from '../js/mzta-utils.js';
|
||||
import { openAICompConfigs } from '../js/api/openai_comp_configs.js';
|
||||
|
||||
let taLog = new taLogger("mzta-options",true);
|
||||
let _isThunderbird128OrGreater = true;
|
||||
|
|
@ -36,19 +38,27 @@ function saveOptions(e) {
|
|||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
options[element.id] = element.checked;
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.checked);
|
||||
break;
|
||||
case 'number':
|
||||
options[element.id] = element.valueAsNumber;
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.valueAsNumber);
|
||||
break;
|
||||
case 'text':
|
||||
case 'password':
|
||||
case 'text':
|
||||
options[element.id] = element.value.trim();
|
||||
taLog.logger.log('Saving option: ' + element.id + ' = ' + element.value);
|
||||
break;
|
||||
case 'password':
|
||||
options[element.id] = element.value.trim();
|
||||
taLog.logger.log('Saving option: ' + element.id + ' = *********');
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.value);
|
||||
} else if (element.tagName === 'TEXTAREA') {
|
||||
options[element.id] = element.value.trim();
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.value.trim());
|
||||
} else {
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
|
@ -60,7 +70,7 @@ function saveOptions(e) {
|
|||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" || element.id=="google_gemini_api_key" ? "****************" : result[element.id]));
|
||||
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" || element.id=="google_gemini_api_key" || element.id=="anthropic_api_key" ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
element.checked = result[element.id] || false;
|
||||
|
|
@ -109,6 +119,7 @@ function showConnectionOptions() {
|
|||
let ollama_api_display = 'none';
|
||||
let openai_comp_api_display = 'none';
|
||||
let google_gemini_api_display = 'none';
|
||||
let anthropic_api_display = 'none';
|
||||
let conntype_select = document.getElementById("connection_type");
|
||||
let parent = conntype_select.parentElement.parentElement.parentElement;
|
||||
parent.classList.toggle("conntype_chatgpt_web", (conntype_select.value === "chatgpt_web"));
|
||||
|
|
@ -116,6 +127,7 @@ function showConnectionOptions() {
|
|||
parent.classList.toggle("conntype_ollama_api", (conntype_select.value === "ollama_api"));
|
||||
parent.classList.toggle("conntype_openai_comp_api", (conntype_select.value === "openai_comp_api"));
|
||||
parent.classList.toggle("conntype_google_gemini_api", (conntype_select.value === "google_gemini_api"));
|
||||
parent.classList.toggle("conntype_anthropic_api", (conntype_select.value === "anthropic_api"));
|
||||
if (conntype_select.value === "chatgpt_web") {
|
||||
chatgpt_web_display = 'table-row';
|
||||
}else{
|
||||
|
|
@ -141,6 +153,11 @@ function showConnectionOptions() {
|
|||
}else{
|
||||
google_gemini_api_display = 'none';
|
||||
}
|
||||
if (conntype_select.value === "anthropic_api") {
|
||||
anthropic_api_display = 'table-row';
|
||||
}else{
|
||||
anthropic_api_display = 'none';
|
||||
}
|
||||
document.querySelectorAll(".conntype_chatgpt_web").forEach(element => {
|
||||
element.style.display = chatgpt_web_display;
|
||||
});
|
||||
|
|
@ -156,6 +173,9 @@ function showConnectionOptions() {
|
|||
document.querySelectorAll(".conntype_google_gemini_api").forEach(element => {
|
||||
element.style.display = google_gemini_api_display;
|
||||
});
|
||||
document.querySelectorAll(".conntype_anthropic_api").forEach(element => {
|
||||
element.style.display = anthropic_api_display;
|
||||
});
|
||||
if (permission_all_urls) {
|
||||
document.getElementById('openai_comp_api_cors_warning').style.display = 'none';
|
||||
document.getElementById('ollama_api_cors_warning').style.display = 'none';
|
||||
|
|
@ -250,6 +270,50 @@ function warn_OpenAIComp_HostEmpty() {
|
|||
}
|
||||
}
|
||||
|
||||
function warn_Anthropic_APIKeyEmpty() {
|
||||
let apiKeyInput = document.getElementById('anthropic_api_key');
|
||||
let btnFetchAnthropicModels = document.getElementById('btnUpdateAnthropicModels');
|
||||
let modelAnthropic = document.getElementById('anthropic_model');
|
||||
if(apiKeyInput.value === ''){
|
||||
apiKeyInput.style.border = '2px solid red';
|
||||
btnFetchAnthropicModels.disabled = true;
|
||||
modelAnthropic.disabled = true;
|
||||
modelAnthropic.selectedIndex = -1;
|
||||
modelAnthropic.style.border = '';
|
||||
}else{
|
||||
apiKeyInput.style.border = '';
|
||||
btnFetchAnthropicModels.disabled = false;
|
||||
modelAnthropic.disabled = false;
|
||||
if((modelAnthropic.selectedIndex === -1)||(modelAnthropic.value === '')){
|
||||
modelAnthropic.style.border = '2px solid red';
|
||||
}else{
|
||||
modelAnthropic.style.border = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function warn_Anthropic_VersionEmpty() {
|
||||
let versionInput = document.getElementById('anthropic_version');
|
||||
let btnFetchAnthropicModels = document.getElementById('btnUpdateAnthropicModels');
|
||||
let modelAnthropic = document.getElementById('anthropic_model');
|
||||
if(versionInput.value === ''){
|
||||
versionInput.style.border = '2px solid red';
|
||||
btnFetchAnthropicModels.disabled = true;
|
||||
modelAnthropic.disabled = true;
|
||||
modelAnthropic.selectedIndex = -1;
|
||||
modelAnthropic.style.border = '';
|
||||
}else{
|
||||
versionInput.style.border = '';
|
||||
btnFetchAnthropicModels.disabled = false;
|
||||
modelAnthropic.disabled = false;
|
||||
if((modelAnthropic.selectedIndex === -1)||(modelAnthropic.value === '')){
|
||||
modelAnthropic.style.border = '2px solid red';
|
||||
}else{
|
||||
modelAnthropic.style.border = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disable_MaxPromptLength(){
|
||||
let maxPromptLength = document.getElementById('max_prompt_length');
|
||||
let conntype_select = document.getElementById("connection_type");
|
||||
|
|
@ -318,7 +382,27 @@ async function disable_GetCalendarEvent(){
|
|||
no_sparks_text.style.display = (is_spark_present == -1) ? 'inline' : 'none';
|
||||
wrong_sparks_text.style.display = (is_spark_present == 0) ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
|
||||
function loadOpenAICompConfigs(){
|
||||
let select_openai_comp_model = document.getElementById('openai_comp_services_shortcut');
|
||||
openAICompConfigs.forEach(config => {
|
||||
const option = document.createElement('option');
|
||||
option.value = config.id;
|
||||
option.text = config.name;
|
||||
select_openai_comp_model.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
function resetOpenAICompConfigs(){
|
||||
let select_openai_comp_model = document.getElementById('openai_comp_services_shortcut');
|
||||
select_openai_comp_model.value = 'custom';
|
||||
}
|
||||
|
||||
function resetMaxPromptLength(){
|
||||
let maxPromptLength = document.getElementById('max_prompt_length');
|
||||
maxPromptLength.value = prefs_default.max_prompt_length;
|
||||
browser.storage.sync.set({max_prompt_length: prefs_default.max_prompt_length});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await restoreOptions();
|
||||
|
|
@ -450,6 +534,8 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
conntype_select.addEventListener("change", warn_Ollama_HostEmpty);
|
||||
conntype_select.addEventListener("change", warn_OpenAIComp_HostEmpty);
|
||||
conntype_select.addEventListener("change", warn_GoogleGemini_APIKeyEmpty);
|
||||
conntype_select.addEventListener("change", warn_Anthropic_APIKeyEmpty);
|
||||
conntype_select.addEventListener("change", warn_Anthropic_VersionEmpty);
|
||||
conntype_select.addEventListener("change", disable_AddTags);
|
||||
conntype_select.addEventListener("change", disable_SpamFilter);
|
||||
conntype_select.addEventListener("change", disable_GetCalendarEvent);
|
||||
|
|
@ -459,8 +545,14 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
document.getElementById("google_gemini_api_key").addEventListener("change", warn_GoogleGemini_APIKeyEmpty);
|
||||
document.getElementById("chatgpt_web_project").addEventListener("input", validateCustomData_ChatGPTWeb);
|
||||
document.getElementById("chatgpt_web_custom_gpt").addEventListener("input", validateCustomData_ChatGPTWeb);
|
||||
document.getElementById("anthropic_api_key").addEventListener("change", warn_Anthropic_APIKeyEmpty);
|
||||
document.getElementById("anthropic_version").addEventListener("change", warn_Anthropic_VersionEmpty);
|
||||
document.getElementById("openai_comp_host").addEventListener("input", resetOpenAICompConfigs);
|
||||
document.getElementById("openai_comp_chat_name").addEventListener("input", resetOpenAICompConfigs);
|
||||
document.getElementById("openai_comp_use_v1").addEventListener("input", resetOpenAICompConfigs);
|
||||
|
||||
|
||||
let prefs = await browser.storage.sync.get({chatgpt_web_model: '', chatgpt_model: '', ollama_model: '', openai_comp_model: '', google_gemini_model: '', chatgpt_win_height: 0, chatgpt_win_width: 0 });
|
||||
let prefs = await browser.storage.sync.get({chatgpt_web_model: '', chatgpt_model: '', ollama_model: '', openai_comp_model: '', google_gemini_model: '', anthropic_model: '', anthropic_version: '', chatgpt_win_height: 0, chatgpt_win_width: 0 });
|
||||
|
||||
// OpenAI API ChatGPT model fetching
|
||||
let select_chatgpt_model = document.getElementById('chatgpt_model');
|
||||
|
|
@ -502,7 +594,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
warn_ChatGPT_APIKeyEmpty();
|
||||
});
|
||||
|
||||
// Google Gemini API ChatGPT model fetching
|
||||
// Google Gemini API model fetching
|
||||
let select_google_gemini_model = document.getElementById('google_gemini_model');
|
||||
const google_gemini_option = document.createElement('option');
|
||||
google_gemini_option.value = prefs.google_gemini_model;
|
||||
|
|
@ -640,11 +732,57 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
warn_OpenAIComp_HostEmpty();
|
||||
});
|
||||
|
||||
// Anthropic API model fetching
|
||||
let select_anthropic_model = document.getElementById('anthropic_model');
|
||||
const anthropic_option = document.createElement('option');
|
||||
anthropic_option.value = prefs.anthropic_model;
|
||||
anthropic_option.text = prefs.anthropic_model;
|
||||
select_anthropic_model.appendChild(anthropic_option);
|
||||
select_anthropic_model.addEventListener("change", warn_Anthropic_APIKeyEmpty);
|
||||
select_anthropic_model.addEventListener("change", warn_Anthropic_VersionEmpty);
|
||||
|
||||
document.getElementById('btnUpdateAnthropicModels').addEventListener('click', async () => {
|
||||
document.getElementById('anthropic_model_fetch_loading').style.display = 'inline';
|
||||
let anthropic = new Anthropic(document.getElementById("anthropic_api_key").value, document.getElementById("anthropic_version").value, '');
|
||||
anthropic.fetchModels().then((data) => {
|
||||
if(!data.ok){
|
||||
let errorDetail;
|
||||
try {
|
||||
errorDetail = JSON.parse(data.error);
|
||||
errorDetail = errorDetail.error.message;
|
||||
} catch (e) {
|
||||
errorDetail = data.error;
|
||||
}
|
||||
document.getElementById('anthropic_model_fetch_loading').style.display = 'none';
|
||||
console.error("[ThunderAI] " + browser.i18n.getMessage("Anthropic_Models_Error_fetching"));
|
||||
alert(browser.i18n.getMessage("Anthropic_Models_Error_fetching")+": " + errorDetail);
|
||||
return;
|
||||
}
|
||||
taLog.log("Anthropic models: " + JSON.stringify(data));
|
||||
data.response.forEach(model => {
|
||||
const existingOption = Array.from(select_anthropic_model.options).find(option => option.value === model.id);
|
||||
if (existingOption) {
|
||||
existingOption.text = model.display_name + " (" + model.id + ")";
|
||||
} else {
|
||||
const option = document.createElement('option');
|
||||
option.value = model.id;
|
||||
option.text = model.display_name + " (" + model.id + ")";
|
||||
select_anthropic_model.appendChild(option);
|
||||
}
|
||||
});
|
||||
document.getElementById('anthropic_model_fetch_loading').style.display = 'none';
|
||||
});
|
||||
|
||||
warn_Anthropic_APIKeyEmpty();
|
||||
});
|
||||
|
||||
showConnectionOptions();
|
||||
warn_ChatGPT_APIKeyEmpty();
|
||||
warn_Ollama_HostEmpty();
|
||||
warn_OpenAIComp_HostEmpty();
|
||||
warn_GoogleGemini_APIKeyEmpty();
|
||||
warn_Anthropic_APIKeyEmpty();
|
||||
warn_Anthropic_VersionEmpty();
|
||||
disable_MaxPromptLength();
|
||||
disable_AddTags();
|
||||
disable_SpamFilter();
|
||||
|
|
@ -683,6 +821,17 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
icon_img_openai_comp_api_key.src = type === 'password' ? "../images/pwd-show.png" : "../images/pwd-hide.png";
|
||||
});
|
||||
|
||||
const passwordField_anthropic_api_key = document.getElementById('anthropic_api_key');
|
||||
const toggleIcon_anthropic_api_key = document.getElementById('toggle_anthropic_api_key');
|
||||
const icon_img_anthropic_api_key = document.getElementById('pwd-icon_anthropic_api_key');
|
||||
|
||||
toggleIcon_anthropic_api_key.addEventListener('click', () => {
|
||||
const type = passwordField_anthropic_api_key.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||
passwordField_anthropic_api_key.setAttribute('type', type);
|
||||
|
||||
icon_img_anthropic_api_key.src = type === 'password' ? "../images/pwd-show.png" : "../images/pwd-hide.png";
|
||||
});
|
||||
|
||||
const btnChatGPTWeb_Tab = document.getElementById('btnChatGPTWeb_Tab');
|
||||
btnChatGPTWeb_Tab.addEventListener('click', async () => {
|
||||
let prefs_mod = await browser.storage.sync.get({chatgpt_web_model: prefs_default.chatgpt_web_model, chatgpt_web_project: prefs_default.chatgpt_web_project, chatgpt_web_custom_gpt: prefs_default.chatgpt_web_custom_gpt});
|
||||
|
|
@ -711,4 +860,32 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
}
|
||||
});
|
||||
|
||||
loadOpenAICompConfigs();
|
||||
let select_openai_comp_services_shortcut = document.getElementById('openai_comp_services_shortcut');
|
||||
select_openai_comp_services_shortcut.addEventListener("change", () => {
|
||||
let selectedOption = select_openai_comp_services_shortcut.options[select_openai_comp_services_shortcut.selectedIndex];
|
||||
const config = openAICompConfigs.find(cfg => cfg.id === selectedOption.value);
|
||||
if (config) {
|
||||
if (!confirm(browser.i18n.getMessage('OpenAIComp_Configs_ConfirmApply', config.name))) {
|
||||
return;
|
||||
}
|
||||
document.getElementById('openai_comp_host').value = config.host || '';
|
||||
// Clear all options from the select except the first (placeholder) one
|
||||
const openaiCompModelSelect = document.getElementById('openai_comp_model');
|
||||
openaiCompModelSelect.value = '';
|
||||
while (openaiCompModelSelect.options.length > 0) {
|
||||
openaiCompModelSelect.remove(0);
|
||||
}
|
||||
document.getElementById('openai_comp_use_v1').checked = !!config.use_v1;
|
||||
document.getElementById('openai_comp_chat_name').value = config.chat_name || '';
|
||||
// Trigger change events if needed
|
||||
document.getElementById('openai_comp_host').dispatchEvent(new Event('change', { bubbles: true }));
|
||||
document.getElementById('openai_comp_model').dispatchEvent(new Event('change', { bubbles: true }));
|
||||
document.getElementById('openai_comp_use_v1').dispatchEvent(new Event('change', { bubbles: true }));
|
||||
document.getElementById('openai_comp_chat_name').dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('reset_max_prompt_length').addEventListener('click', resetMaxPromptLength);
|
||||
|
||||
}, { once: true });
|
||||
|
|
|
|||
|
|
@ -7,6 +7,20 @@
|
|||
<body>
|
||||
<div id="miczBackPrefs"><a href="mzta-options.html">__MSG_backToOptionsText__</a></div>
|
||||
<div id="miczRelNotes"><h1>ThunderAI Release Notes</h1>
|
||||
<h2>Version 3.5.0 - 30/05/2025</h2>
|
||||
<ul>
|
||||
<li>Added Anthropic API support [<a href="https://github.com/micz/ThunderAI/issues/349">#349</a>].</li>
|
||||
<li>Added the <i>{%selected_html%}</i> placeholder to retrieve the HTML portion of the selected text [<a href="https://github.com/micz/ThunderAI/issues/368">#368</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added a shortcut to select configurations for known AI services. Currently, <i>Grok AI</i> and <i>Mistral AI</i> are available [<a href="https://github.com/micz/ThunderAI/issues/378">#378</a>]. <a href="https://github.com/micz/ThunderAI/issues/new?template=feature_request.md">Open an issue</a> to request additional services.</li>
|
||||
<li><i>[All APIs]</i> In the API WebChat is now possibile to select a part of the answer and use only that [<a href="https://github.com/micz/ThunderAI/issues/356">#356</a>].</li>
|
||||
<li><i>[All APIs]</i> Setting the "Max prompt length" to zero on the options page will disable the length check when sending a prompt to the AI. [<a href="https://github.com/micz/ThunderAI/issues/380">#380</a>].</li>
|
||||
<li><i>[All APIs]</i> Added a button to the options page to reset the 'Max prompt length' value to its default.</li>
|
||||
<li><i>[All APIs]</i> Adding tags automatically or with the context menu will now use also tags not created by ThunderAI [<a href="https://github.com/micz/ThunderAI/issues/390">#390</a>].</li>
|
||||
<li>Fix: In the Spamfilter page the unsaved changes warning is now correctly shown.</li>
|
||||
<li>Fix: The default keyboard shortcut is no longer enforced at every Thunderbird startup [<a href="https://github.com/micz/ThunderAI/issues/384">#384</a>].</li>
|
||||
<li>Fix: Incoming email processing now works correctly when auto-tagging is enabled and the full tagging feature is subsequently disabled.</li>
|
||||
<li>Fix: The reply type is correctly saved in the options. [<a href="https://github.com/micz/ThunderAI/issues/387">#387</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 3.4.1 - 12/05/2025</h2>
|
||||
<ul>
|
||||
<li><i>[All APIs]</i> Fix: correctly assigning tags when receiving mails. Thanks to <a href="https://github.com/jdkio">jdkio</a> [<a href="https://github.com/micz/ThunderAI/issues/374">#374</a>].</li>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#addtags_info_additional_statements, #add_tags_auto_force_existing_tr, #add_tags_auto_only_inbox_tr{
|
||||
#addtags_info_additional_statements, #add_tags_auto_only_inbox_tr{
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,15 +59,6 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr add_tags_auto" id="add_tags_auto_force_existing_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_auto_force_existing__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="add_tags_auto_force_existing" name="add_tags_auto_force_existing" class="option-input" />
|
||||
__MSG_prefs_OptionText_add_tags_auto_force_existing_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr add_tags_auto" id="add_tags_auto_only_inbox_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_auto_only_inbox__</span></td>
|
||||
<td>
|
||||
|
|
@ -86,6 +77,15 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_auto_force_existing__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="add_tags_auto_force_existing" name="add_tags_auto_force_existing" class="option-input" />
|
||||
__MSG_prefs_OptionText_add_tags_auto_force_existing_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="addtags_prompt_container">
|
||||
<span class="section_title">__MSG_AddTags_prompt_text_title__</span><span id="addtags_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
|
|
|
|||
|
|
@ -54,17 +54,14 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
});
|
||||
|
||||
let add_tags_auto_el = document.getElementById('add_tags_auto');
|
||||
let add_tags_auto_force_existing_tr = document.getElementById('add_tags_auto_force_existing_tr');
|
||||
let add_tags_auto_only_inbox_tr = document.getElementById('add_tags_auto_only_inbox_tr');
|
||||
let account_selector_container = document.getElementById('account_selector_container');
|
||||
let add_tags_auto_infoline = document.getElementById('add_tags_auto_infoline');
|
||||
add_tags_auto_el.addEventListener('click', (event) => {
|
||||
add_tags_auto_force_existing_tr.style.display = event.target.checked ? 'table-row' : 'none';
|
||||
add_tags_auto_only_inbox_tr.style.display = event.target.checked ? 'table-row' : 'none';
|
||||
account_selector_container.style.display = event.target.checked ? 'block' : 'none';
|
||||
add_tags_auto_infoline.style.display = event.target.checked ? 'inline' : 'none';
|
||||
});
|
||||
add_tags_auto_force_existing_tr.style.display = add_tags_auto_el.checked ? 'table-row' : 'none';
|
||||
add_tags_auto_only_inbox_tr.style.display = add_tags_auto_el.checked ? 'table-row' : 'none';
|
||||
account_selector_container.style.display = add_tags_auto_el.checked ? 'block' : 'none';
|
||||
add_tags_auto_infoline.style.display = add_tags_auto_el.checked ? 'inline' : 'none';
|
||||
|
|
|
|||
|
|
@ -966,7 +966,7 @@ function checkPromptsConfigForPlaceholders(textarea){
|
|||
|
||||
let tr_ancestor2 = textarea.closest('tr');
|
||||
let selected_text_element = tr_ancestor2.querySelector('.need_selected') || tr_ancestor2.querySelector('.need_selected_new');
|
||||
if(String(textarea.value).indexOf('{%selected_text%}') != -1){
|
||||
if((String(textarea.value).indexOf('{%selected_text%}') != -1)||(String(textarea.value).indexOf('{%selected_html%}') != -1)){
|
||||
if(!selected_text_element.checked){
|
||||
selected_text_element.closest('.need_selected_span').style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ h2 {
|
|||
box-shadow: inset 5px 2px 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#chatgpt_web_permission {
|
||||
#chatgpt_web_permission, #anthropic_api_permission {
|
||||
display: none;
|
||||
background-color: red;
|
||||
color: white;
|
||||
|
|
@ -196,12 +196,12 @@ h2 {
|
|||
transition: background-color 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
#chatgpt_web_permission:hover {
|
||||
#chatgpt_web_permission:hover, #anthropic_api_permission:hover {
|
||||
background-color: darkred;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
#chatgpt_web_permission_ok {
|
||||
#integration_permission_ok {
|
||||
display: none;
|
||||
background-color: green;
|
||||
color: white;
|
||||
|
|
@ -213,7 +213,7 @@ h2 {
|
|||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
#chatgpt_web_permission_ok:hover {
|
||||
#integration_permission_ok:hover {
|
||||
background-color: darkgreen;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
|
@ -15,9 +15,12 @@
|
|||
<body>
|
||||
<div class="content">
|
||||
<div id="chatgpt_web_permission">__MSG_ask_chatgptweb_permission_1__
|
||||
<br>__MSG_ask_chatgptweb_permission_2__
|
||||
<br>__MSG_ask_integration_permission_2__
|
||||
</div>
|
||||
<div id="chatgpt_web_permission_ok">__MSG_ask_chatgptweb_permission_ok__</div>
|
||||
<div id="anthropic_api_permission">__MSG_ask_anthropic_api_permission_1__
|
||||
<br>__MSG_ask_integration_permission_2__
|
||||
</div>
|
||||
<div id="integration_permission_ok">__MSG_ask_integration_permission_ok__</div>
|
||||
<div class="section header">
|
||||
<h1><img src="../../images/icon.png" class="title-icon"/>ThunderAI</h1>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -32,13 +32,32 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
let granted = await messenger.permissions.request({ origins: ["https://*.chatgpt.com/*"] });
|
||||
if(granted){
|
||||
document.getElementById("chatgpt_web_permission").style.display = "none";
|
||||
document.getElementById("chatgpt_web_permission_ok").style.display = "block";
|
||||
taLog.log("ChatGPT web permission granted");
|
||||
document.getElementById("integration_permission_ok").style.display = "block";
|
||||
taLog.log("ChatGPT Web permission granted");
|
||||
}else{
|
||||
taLog.log("ChatGPT web permission denied");
|
||||
taLog.log("ChatGPT Web permission denied");
|
||||
}
|
||||
});
|
||||
document.getElementById("chatgpt_web_permission_ok").addEventListener("click", async () => {
|
||||
document.getElementById("integration_permission_ok").addEventListener("click", async () => {
|
||||
await messenger.tabs.remove((await messenger.tabs.getCurrent()).id);
|
||||
});
|
||||
}
|
||||
}
|
||||
if(prefs.connection_type === 'anthropic_api'){
|
||||
let permission_chatgpt = await messenger.permissions.contains({ origins: ["https://*.anthropic.com/*"] });
|
||||
if(permission_chatgpt === false){
|
||||
document.getElementById("anthropic_api_permission").style.display = "block";
|
||||
document.getElementById("anthropic_api_permission").addEventListener("click", async () => {
|
||||
let granted = await messenger.permissions.request({ origins: ["https://*.anthropic.com/*"] });
|
||||
if(granted){
|
||||
document.getElementById("anthropic_api_permission").style.display = "none";
|
||||
document.getElementById("integration_permission_ok").style.display = "block";
|
||||
taLog.log("Anthropic API permission granted");
|
||||
}else{
|
||||
taLog.log("Anthropic API web permission denied");
|
||||
}
|
||||
});
|
||||
document.getElementById("integration_permission_ok").addEventListener("click", async () => {
|
||||
await messenger.tabs.remove((await messenger.tabs.getCurrent()).id);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
</tr>
|
||||
</table>
|
||||
<div id="spamfilter_container">
|
||||
<span class="section_title">__MSG_GetCalendarEvent_prompt_text_title__</span><span id="spamfilter_event_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<span class="section_title">__MSG_GetCalendarEvent_prompt_text_title__</span><span id="spamfilter_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br><b>__MSG_prefs_OptionText_GetCalendarEvent_infoline2__</b></span>
|
||||
<br>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ body {
|
|||
background-color: #cfe9ff;
|
||||
}
|
||||
|
||||
#ask_chatgpt_web_perm{
|
||||
#ask_chatgpt_web_perm, #ask_anthropic_api_perm{
|
||||
display: none;
|
||||
max-width: 20em;
|
||||
background-color: red;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@
|
|||
|
||||
<body>
|
||||
<div id="ask_chatgpt_web_perm">__MSG_ask_chatgptweb_permission_1__
|
||||
<br>__MSG_ask_chatgptweb_permission_2_popup__
|
||||
<br>__MSG_ask_integration_permission_2_popup__
|
||||
</div>
|
||||
<div id="ask_anthropic_api_perm">__MSG_ask_anthropic_api_permission_1__
|
||||
<br>__MSG_ask_integration_permission_2_popup__
|
||||
</div>
|
||||
<div id="mzta_search_banner">
|
||||
<div id="_spacer_div"> </div>
|
||||
|
|
|
|||
|
|
@ -66,6 +66,16 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
});
|
||||
}
|
||||
}
|
||||
if(prefs.connection_type === 'anthropic_api'){
|
||||
let permission_anthropic = await browser.permissions.contains({ origins: ["https://*.anthropic.com/*"] });
|
||||
if(permission_anthropic === false){
|
||||
document.getElementById("mzta_search_banner").style.display = "none";
|
||||
document.getElementById("ask_anthropic_api_perm").style.display = "block";
|
||||
document.getElementById('ask_anthropic_api_perm').addEventListener('click', async () => {
|
||||
await browser.tabs.create({ url: "../pages/onboarding/onboarding.html" });
|
||||
});
|
||||
}
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
async function searchPrompt(allPrompts, tabId, tabType){
|
||||
|
|
|
|||
Loading…
Reference in a new issue