commit
a03cae90bf
27 changed files with 1380 additions and 99 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -5,6 +5,20 @@
|
|||
|
||||
|
||||
|
||||
<h2>Version 2.3.0 - ??/??/2024</h2>
|
||||
<ul>
|
||||
<li>The action button in the compose window has been moved to the formatting toolbar [<a href="https://github.com/micz/ThunderAI/issues/173">#173</a>].</li>
|
||||
<li>On the custom prompts page, when editing a prompt, pressing the cancel button will revert any modified values in the form to their saved state.</li>
|
||||
<li>Implemented placeholders to add additional data to prompts [<a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">More info</a>] [<a href="https://github.com/micz/ThunderAI/issues/146">#146</a>, <a href="https://github.com/micz/ThunderAI/issues/153">#153</a>].</li>
|
||||
<li>Text improved for the "Reply to this" prompt.</li>
|
||||
<li>Added an option to set the maximum number of characters in the prompt [<a href="https://github.com/micz/ThunderAI/issues/165">#165</a>].</li>
|
||||
<li>Added a workaround to show an alert message when needed [<a href="https://github.com/micz/ThunderAI/issues/166">#166</a>].</li>
|
||||
<li><i>[ChatGPT Web]</i> Added an option to set the model to use [<a href="https://github.com/micz/ThunderAI/issues/171">#171</a>].</li>
|
||||
<li><i>[ChatGPT Web]</i> Added an option to use the temporary chat [<a href="https://github.com/micz/ThunderAI/issues/169">#169</a>].</li>
|
||||
<li>A few typos fixed [<a href="https://github.com/micz/ThunderAI/issues/170">#170</a>].</li>
|
||||
<li>Added a loading indicator in the menu when sending a prompt.</li>
|
||||
<li>Added a new default prompt that uses the placeholders and allows replying to an email thread. It requires selecting the text of the first email to identify which is the one to reply to and the others in the thread [<a href="https://github.com/micz/ThunderAI/issues/150">#150</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 2.2.2 - 15/10/2024</h2>
|
||||
<ul>
|
||||
<li>APIs error handling improved.</li>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Are you using this addon in your Thunderbird?
|
|||
<br>
|
||||
|
||||
### Miscellaneous
|
||||
- <a href="https://github.com/KudoAI/chatgpt.js">chatgpt.js</a> for providing methods to interact with the ChatGTP web frontend
|
||||
- <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/ali-raheem/Aify">Aify</a> for inspiration
|
||||
- <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
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Darauf antworten",
|
||||
"message": "Antworten Sie auf diese E-Mail",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Antworten Sie auf diesen Thread",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
|
|
@ -236,7 +240,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "Sie haben die Option zur Verwendung von ChatGPT-4 eingestellt, aber es scheint, dass es nicht korrekt geladen wird. Haben Sie oben das Modell 4 oder 4o gewählt?",
|
||||
"message": "Du hast die Option gewählt, ein bestimmtes Modell zu verwenden, aber es scheint, dass es nicht korrekt geladen wird. Bitte überprüfe den Wert und versuche es erneut. Du kannst jetzt den blauen Knopf drücken, um fortzufahren.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_custom_text": {
|
||||
|
|
@ -260,7 +264,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "Der eingegebene Text ist zu lang. Sie müssen ihn verkürzen, um ChatGPT zu verwenden.",
|
||||
"message": "Der von Ihnen bereitgestellte Text ist zu lang. Sie müssen ihn kürzen.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_release_notes": {
|
||||
|
|
@ -395,12 +399,12 @@
|
|||
"message": "Verbindungstyp",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_Web": {
|
||||
"message": "ChatGTP Weboberfläche",
|
||||
"prefs_Connection_type_ChatGPT_Web": {
|
||||
"message": "ChatGPT Weboberfläche",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_API": {
|
||||
"message": "ChatGTP OpenAI API",
|
||||
"prefs_Connection_type_ChatGPT_API": {
|
||||
"message": "ChatGPT OpenAI API",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ChatGPT_API_Key": {
|
||||
|
|
@ -435,7 +439,7 @@
|
|||
"message": "Sie haben kein Modell für das ChatGPT-API ausgewählt. Bitte wählen Sie eines auf der Optionsseite aus.",
|
||||
"description": ""
|
||||
},
|
||||
"chagtp_api_send_button": {
|
||||
"chagpt_api_send_button": {
|
||||
"message": "Modell wird verwendet",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -579,6 +583,10 @@
|
|||
"message": "Auf 0 setzen, wenn Sie die Fenstergröße nicht angeben möchten.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_API_Key": {
|
||||
"message": "OpenAI Comp API-Schlüssel",
|
||||
"description": ""
|
||||
},
|
||||
"Optional": {
|
||||
"message": "Optional",
|
||||
"description": ""
|
||||
|
|
@ -591,6 +599,88 @@
|
|||
"message": "Bei Anmeldeproblemen im ThunderAI-Fenster öffnen Sie ChatGPT in einem neuen Tab über die Schaltfläche rechts, melden Sie sich an, schließen Sie dann den Tab und fahren Sie fort, ThunderAI zu verwenden.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_text_body": {
|
||||
"message": "E-Mail-Inhalt",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_html_body": {
|
||||
"message": "HTML-E-Mail-Inhalt",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_subject": {
|
||||
"message": "E-Mail-Betreff",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_text": {
|
||||
"message": "Ausgewählter Text",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Zusätzlicher Text",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_junk_score": {
|
||||
"message": "Spam-Score",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_recipients": {
|
||||
"message": "Empfänger",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_cc_list": {
|
||||
"message": "CC-Liste",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_author": {
|
||||
"message": "Autor",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value": {
|
||||
"message": "Platzhalter: standardwert verwenden",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value_info": {
|
||||
"message": "Wenn aktiviert, werden die Platzhalter mit den Standardwerten ausgefüllt, wenn kein Wert angegeben wird. Andernfalls bleiben die Platzhalter erhalten.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length": {
|
||||
"message": "Maximale Eingabelänge",
|
||||
"description": ""
|
||||
},
|
||||
"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.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "ChatGPT Web-Modell",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "Dies ist das Modell, das für die ChatGPT-Webschnittstelle festgelegt wird. Wenn keines angegeben ist oder ein falsches Modell bereitgestellt wird, wird das Standardmodell von ChatGPT auf der Webseite festgelegt.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "ChatGPT Web temporärer Chat",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat_info": {
|
||||
"message": "Wenn aktiviert, wird der temporäre Chat in der ChatGPT-Webschnittstelle verwendet.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_model": {
|
||||
"message": "Aktuelles Modell verwenden",
|
||||
"description": ""
|
||||
},
|
||||
"SendingPrompt": {
|
||||
"message": "Sende Eingabe...",
|
||||
"description": ""
|
||||
},
|
||||
"AllowedValues": {
|
||||
"message": "Erlaubte Werte",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Sie können jetzt zusätzliche Datenplatzhalter verwenden!",
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "\"v1\"-Kompatibilität beibehalten",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Reply to this",
|
||||
"message": "Reply to this email",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Reply to this thread",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
|
|
@ -236,7 +240,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "You have set the option to use ChatGPT-4, but it seems that it is not loading correctly. Have you chosen the model 4 or 4o at the top?",
|
||||
"message": "You have set the option to use a specific model, but it seems that it is not loading correctly. Please check the value and try again. For now, you can press the blue button to continue.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_custom_text": {
|
||||
|
|
@ -260,7 +264,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "The text you provided is too long. You need to reduce it to use ChatGPT.",
|
||||
"message": "The text you provided is too long. You need to reduce it.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_release_notes": {
|
||||
|
|
@ -388,19 +392,19 @@
|
|||
"description": ""
|
||||
},
|
||||
"customprompts_form_label_define_response_lang": {
|
||||
"message": "Define the reponse languange in the prompt",
|
||||
"message": "Define the reponse language in the prompt",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type": {
|
||||
"message": "Connection Type",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_Web": {
|
||||
"message": "ChatGTP Web Interface",
|
||||
"prefs_Connection_type_ChatGPT_Web": {
|
||||
"message": "ChatGPT Web Interface",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_API": {
|
||||
"message": "ChatGTP OpenAI API",
|
||||
"prefs_Connection_type_ChatGPT_API": {
|
||||
"message": "ChatGPT OpenAI API",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ChatGPT_API_Key": {
|
||||
|
|
@ -435,7 +439,7 @@
|
|||
"message": "You've not choosen a model for the ChatGPT API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"chagtp_api_send_button": {
|
||||
"chagpt_api_send_button": {
|
||||
"message": "Using model",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -595,6 +599,88 @@
|
|||
"message": "In case of login issues in the ThunderAI window, open ChatGPT in a new tab using the button on the right, log in, then close the tab and continue using ThunderAI.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_text_body": {
|
||||
"message": "Mail body",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_html_body": {
|
||||
"message": "HTML mail body",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_subject": {
|
||||
"message": "Mail subject",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_text": {
|
||||
"message": "Selected text",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Additional text",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_junk_score": {
|
||||
"message": "Junk score",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_recipients": {
|
||||
"message": "Recipients",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_cc_list": {
|
||||
"message": "CC list",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_author": {
|
||||
"message": "Author",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value": {
|
||||
"message": "Placeholders: use default value",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value_info": {
|
||||
"message": "If checked, the placeholders will be filled with the default values when no value is provided. Otherwise, the placeholders will be kept in place.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length" : {
|
||||
"message": "Max prompt length",
|
||||
"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.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "ChatGPT Web model",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "This is the model that will be enforced for the ChatGPT Web Interface. If none is specified or an incorrect one is provided, the default model will be set by ChatGPT on the webpage.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "ChatGPT Web temporary chat",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat_info": {
|
||||
"message": "If checked, the temporary chat will be used in the ChatGPT Web Interface.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_model": {
|
||||
"message": "Use the current model",
|
||||
"description": ""
|
||||
},
|
||||
"SendingPrompt": {
|
||||
"message": "Sending prompt...",
|
||||
"description": ""
|
||||
},
|
||||
"AllowedValues": {
|
||||
"message": "Allowed values",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "You can now use additional data placeholders!",
|
||||
"prefs_OptionText_openai_comp_use_v1" : {
|
||||
"message": "Keep the \"v1\" compatibility",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Répondre à ceci",
|
||||
"message": "Répondez à cet e-mail",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Répondez à ce fil de discussion",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
|
|
@ -236,7 +240,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "Vous avez choisi l'option d'utiliser ChatGPT-4, mais il semble qu'il ne se charge pas correctement. Avez-vous choisi le modèle 4 ou 4o en haut ?",
|
||||
"message": "Vous avez choisi d'utiliser un modèle spécifique, mais il semble qu'il ne se charge pas correctement. Veuillez vérifier la valeur et réessayer. Pour l'instant, vous pouvez appuyer sur le bouton bleu pour continuer.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_custom_text": {
|
||||
|
|
@ -260,7 +264,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "Le texte que vous avez fourni est trop long. Vous devez le réduire pour utiliser ChatGPT.",
|
||||
"message": "Le texte que vous avez fourni est trop long. Vous devez le raccourcir.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_release_notes": {
|
||||
|
|
@ -395,12 +399,12 @@
|
|||
"message": "Type de connexion",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_Web": {
|
||||
"message": "Interface Web ChatGTP",
|
||||
"prefs_Connection_type_ChatGPT_Web": {
|
||||
"message": "Interface Web ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_API": {
|
||||
"message": "API OpenAI ChatGTP",
|
||||
"prefs_Connection_type_ChatGPT_API": {
|
||||
"message": "API OpenAI ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ChatGPT_API_Key": {
|
||||
|
|
@ -435,7 +439,7 @@
|
|||
"message": "Vous n'avez pas choisi de modèle pour l'API ChatGPT. Veuillez en choisir un sur la page des options.",
|
||||
"description": ""
|
||||
},
|
||||
"chagtp_api_send_button": {
|
||||
"chagpt_api_send_button": {
|
||||
"message": "Utilisation du modèle",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -579,6 +583,10 @@
|
|||
"message": "Réglez sur 0 si vous ne souhaitez pas spécifier la taille de la fenêtre.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_API_Key": {
|
||||
"message": "Clé API OpenAI Comp",
|
||||
"description": ""
|
||||
},
|
||||
"Optional": {
|
||||
"message": "Optionnel",
|
||||
"description": ""
|
||||
|
|
@ -591,6 +599,88 @@
|
|||
"message": "En cas de problèmes de connexion dans la fenêtre ThunderAI, ouvrez ChatGPT dans un nouvel onglet à l'aide du bouton à droite, connectez-vous, puis fermez l'onglet et continuez à utiliser ThunderAI.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_text_body": {
|
||||
"message": "Corps du mail",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_html_body": {
|
||||
"message": "Corps du mail HTML",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_subject": {
|
||||
"message": "Objet du mail",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_text": {
|
||||
"message": "Texte sélectionné",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Texte supplémentaire",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_junk_score": {
|
||||
"message": "Score de spam",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_recipients": {
|
||||
"message": "Destinataires",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_cc_list": {
|
||||
"message": "Liste CC",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_author": {
|
||||
"message": "Auteur",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value": {
|
||||
"message": "Espaces réservés : utiliser la valeur par défaut",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value_info": {
|
||||
"message": "Si coché, les espaces réservés seront remplis avec les valeurs par défaut si aucune valeur n'est fournie. Sinon, les espaces réservés resteront en place.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length": {
|
||||
"message": "Longueur maximale de l'invite",
|
||||
"description": ""
|
||||
},
|
||||
"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.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Modèle Web ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "C'est le modèle qui sera appliqué pour l'interface Web de ChatGPT. Si aucun n'est spécifié ou si un modèle incorrect est fourni, le modèle par défaut sera défini par ChatGPT sur la page Web.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "Chat temporaire Web ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat_info": {
|
||||
"message": "Si coché, le chat temporaire sera utilisé dans l'interface Web de ChatGPT.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_model": {
|
||||
"message": "Utiliser le modèle actuel",
|
||||
"description": ""
|
||||
},
|
||||
"SendingPrompt": {
|
||||
"message": "Envoi de l'invite...",
|
||||
"description": ""
|
||||
},
|
||||
"AllowedValues": {
|
||||
"message": "Valeurs autorisées",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Vous pouvez maintenant utiliser des espaces réservés de données supplémentaires !",
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Conserver la compatibilité \"v1\"",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Rispondi",
|
||||
"message": "Rispondi a questa email",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Rispondi a questo thread",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
|
|
@ -236,7 +240,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "Hai impostato l'opzione per utilizzare ChatGPT-4, ma sembra che non si stia caricando. Hai selezionato il modello 4 o 4o in alto?",
|
||||
"message": "Hai impostato l'opzione per utilizzare un modello specifico, ma sembra che non si stia caricando correttamente. Controlla il valore e riprova. Per ora, puoi premere il pulsante blu per continuare.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_custom_text": {
|
||||
|
|
@ -260,7 +264,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "Il testo che vuoi inviare a ChatGPT è troppo lungo. Devi ridurlo per poter procedere.",
|
||||
"message": "Il testo che vuoi inviare è troppo lungo. Devi ridurlo per poter procedere.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_release_notes": {
|
||||
|
|
@ -395,12 +399,12 @@
|
|||
"message": "Tipo di connessione",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_Web": {
|
||||
"message": "Interfaccia Web ChatGTP",
|
||||
"prefs_Connection_type_ChatGPT_Web": {
|
||||
"message": "Interfaccia Web ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_API": {
|
||||
"message": "API OpenAI per ChatGTP",
|
||||
"prefs_Connection_type_ChatGPT_API": {
|
||||
"message": "API OpenAI per ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ChatGPT_API_Key": {
|
||||
|
|
@ -435,7 +439,7 @@
|
|||
"message": "Non hai scelto un modello per l'API di ChatGPT. Per favore, scegline uno nella pagina delle opzioni.",
|
||||
"description": ""
|
||||
},
|
||||
"chagtp_api_send_button": {
|
||||
"chagpt_api_send_button": {
|
||||
"message": "Modello utilizzato",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -579,6 +583,10 @@
|
|||
"message": "Imposta a 0 se non desideri specificare la dimensione della finestra.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_API_Key": {
|
||||
"message": "Chiave API OpenAI Comp",
|
||||
"description": ""
|
||||
},
|
||||
"Optional": {
|
||||
"message": "Opzionale",
|
||||
"description": ""
|
||||
|
|
@ -591,6 +599,88 @@
|
|||
"message": "In caso di problemi di accesso nella finestra di ThunderAI, apri ChatGPT in un nuovo tab utilizzando il pulsante a destra, accedi, quindi chiudi la scheda e continua a usare ThunderAI.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_text_body": {
|
||||
"message": "Corpo del messaggio",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_html_body": {
|
||||
"message": "Corpo del messaggio in HTML",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_subject": {
|
||||
"message": "Oggetto del messaggio",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_text": {
|
||||
"message": "Testo selezionato",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Testo aggiuntivo",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_junk_score": {
|
||||
"message": "Punteggio di spam",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_recipients": {
|
||||
"message": "Destinatari",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_cc_list": {
|
||||
"message": "Lista CC",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_author": {
|
||||
"message": "Autore",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value": {
|
||||
"message": "Segnaposti: usa valore predefinito",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value_info": {
|
||||
"message": "Se selezionato, i segnaposti saranno riempiti con i valori predefiniti quando non viene fornito alcun valore. Altrimenti, i segnaposti rimarranno visibili nel testo.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length": {
|
||||
"message": "Lunghezza massima del prompt",
|
||||
"description": ""
|
||||
},
|
||||
"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.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Modello Web ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "Questo è il modello che verrà utilizzato nell'interfaccia Web di ChatGPT. Se non viene specificato o ne viene fornito uno errato, ChatGPT imposterà il modello predefinito sulla pagina Web.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "Chat temporanea di ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat_info": {
|
||||
"message": "Se selezionato, la chat temporanea verrà utilizzata nell'interfaccia Web di ChatGPT.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_model": {
|
||||
"message": "Usa il modello corrente",
|
||||
"description": ""
|
||||
},
|
||||
"SendingPrompt": {
|
||||
"message": "Invio del prompt...",
|
||||
"description": ""
|
||||
},
|
||||
"AllowedValues": {
|
||||
"message": "Valori consentiti",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Ora puoi utilizzare segnaposti per i dati aggiuntivi!",
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Mantieni la compatibilità con \"v1\"",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Responda a isso",
|
||||
"message": "Responda a este e-mail",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Responda a este tópico",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
|
|
@ -236,7 +240,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "Você definiu a opção para usar o ChatGPT-4, mas parece que não está carregando corretamente. Você escolheu o modelo 4 ou 4o na parte superior?",
|
||||
"message": "Você configurou a opção para usar um modelo específico, mas parece que ele não está carregando corretamente. Por favor, verifique o valor e tente novamente. Por enquanto, você pode pressionar o botão azul para continuar.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_custom_text": {
|
||||
|
|
@ -260,7 +264,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "O texto que você forneceu é muito longo. Você precisa reduzi-lo para usar o ChatGPT.",
|
||||
"message": "O texto que você forneceu é muito longo. Você precisa reduzi-lo.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_release_notes": {
|
||||
|
|
@ -395,11 +399,11 @@
|
|||
"message": "Tipo de Conexão",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_Web": {
|
||||
"prefs_Connection_type_ChatGPT_Web": {
|
||||
"message": "Interface Web do ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGTP_API": {
|
||||
"prefs_Connection_type_ChatGPT_API": {
|
||||
"message": "API OpenAI do ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -435,7 +439,7 @@
|
|||
"message": "Você não escolheu um modelo para a API do ChatGPT. Por favor, escolha um na página de opções.",
|
||||
"description": ""
|
||||
},
|
||||
"chagtp_api_send_button": {
|
||||
"chagpt_api_send_button": {
|
||||
"message": "Usando modelo",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -595,6 +599,88 @@
|
|||
"message": "Em caso de problemas de login na janela do ThunderAI, abra o ChatGPT em uma nova aba usando o botão à direita, faça o login, depois feche a aba e continue usando o ThunderAI.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_text_body": {
|
||||
"message": "Corpo do e-mail",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_html_body": {
|
||||
"message": "Corpo do e-mail HTML",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_subject": {
|
||||
"message": "Assunto do e-mail",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_text": {
|
||||
"message": "Texto selecionado",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Texto adicional",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_junk_score": {
|
||||
"message": "Pontuação de spam",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_recipients": {
|
||||
"message": "Destinatários",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_cc_list": {
|
||||
"message": "Lista CC",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_author": {
|
||||
"message": "Autor",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value": {
|
||||
"message": "Marcadores de posição: usar valor padrão",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value_info": {
|
||||
"message": "Se marcado, os marcadores de posição serão preenchidos com os valores padrão quando nenhum valor for fornecido. Caso contrário, os marcadores de posição serão mantidos no lugar.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length": {
|
||||
"message": "Comprimento máximo do prompt",
|
||||
"description": ""
|
||||
},
|
||||
"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.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Modelo Web do ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "Este é o modelo que será aplicado para a Interface Web do ChatGPT. Se nenhum for especificado ou um incorreto for fornecido, o modelo padrão será definido pelo ChatGPT na página web.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "Chat temporário Web do ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat_info": {
|
||||
"message": "Se marcado, o chat temporário será utilizado na Interface Web do ChatGPT.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_model": {
|
||||
"message": "Usar o modelo atual",
|
||||
"description": ""
|
||||
},
|
||||
"SendingPrompt": {
|
||||
"message": "Enviando prompt...",
|
||||
"description": ""
|
||||
},
|
||||
"AllowedValues": {
|
||||
"message": "Valores permitidos",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Agora você pode usar marcadores de posição adicionais!",
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Manter a compatibilidade com \"v1\"",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -20,10 +20,13 @@
|
|||
* The original code has been released under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
import { placeholdersUtils } from '../js/mzta-placeholders.js';
|
||||
|
||||
// Get the LLM to be used
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const llm = urlParams.get('llm');
|
||||
const call_id = urlParams.get('call_id');
|
||||
const ph_def_val = urlParams.get('ph_def_val');
|
||||
|
||||
// Data received from the user
|
||||
let promptData = null;
|
||||
|
|
@ -93,6 +96,7 @@ switch (llm) {
|
|||
}
|
||||
}
|
||||
|
||||
//let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
|
||||
|
||||
// Event listeners for worker messages
|
||||
worker.onmessage = function(event) {
|
||||
|
|
@ -126,7 +130,15 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
if(message.do_custom_text=="1") {
|
||||
let userInput = prompt(browser.i18n.getMessage("chatgpt_win_custom_text"));
|
||||
if(userInput !== null) {
|
||||
message.prompt += " " + userInput;
|
||||
if(!placeholdersUtils.hasPlaceholder(message.prompt, 'additional_text')){
|
||||
// no additional_text placeholder, do as usual
|
||||
message.prompt += " " + userInput;
|
||||
}else{
|
||||
// we have the additional_text placeholder, do the magic!
|
||||
let finalSubs = {};
|
||||
finalSubs["additional_text"] = userInput;
|
||||
message.prompt = placeholdersUtils.replacePlaceholders(message.prompt, finalSubs, ph_def_val==='1')
|
||||
}
|
||||
}
|
||||
}
|
||||
promptData = message;
|
||||
|
|
|
|||
|
|
@ -169,8 +169,8 @@ class MessageInput extends HTMLElement {
|
|||
|
||||
setModel(model){
|
||||
this.model = model;
|
||||
this._sendButton.title = browser.i18n.getMessage("chagtp_api_send_button") + ": " + this.model;
|
||||
this._stopButton.title = browser.i18n.getMessage("chagtp_api_send_button") + ": " + this.model;
|
||||
this._sendButton.title = browser.i18n.getMessage("chagpt_api_send_button") + ": " + this.model;
|
||||
this._stopButton.title = browser.i18n.getMessage("chagpt_api_send_button") + ": " + this.model;
|
||||
}
|
||||
|
||||
handleMessageSent() {
|
||||
|
|
@ -186,7 +186,7 @@ class MessageInput extends HTMLElement {
|
|||
this._sendButton.style.display = 'block';
|
||||
this._stopButton.setAttribute('disabled', 'disabled');
|
||||
this._stopButton.style.display = 'none';
|
||||
this._stopButton.title = browser.i18n.getMessage("chagtp_api_send_button") + ": " + this.model;
|
||||
this._stopButton.title = browser.i18n.getMessage("chagpt_api_send_button") + ": " + this.model;
|
||||
this.hideStatusMessage();
|
||||
this.setStatusMessage('');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,46 @@ table .sort.desc {
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.autocomplete-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
z-index: 1000;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.autocomplete-list li {
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.autocomplete-list li:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.autocomplete-list li.active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.need_custom_text_span, .need_selected_span{
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
|
|
@ -196,6 +236,18 @@ table .sort.desc {
|
|||
|
||||
.storage_space{
|
||||
color: rgb(182, 182, 182);
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
background-color: #2E2F36;
|
||||
border: 1px solid #2E2F36;
|
||||
}
|
||||
|
||||
.autocomplete-list li:hover {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
|
||||
.autocomplete-list li.active {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
<h1 class="page_title">__MSG_customPrompts_managePrompts__</h1>
|
||||
<p>__MSG_customPrompts_managePrompts_info_default__<br>
|
||||
__MSG_customPrompts_managePrompts_info_default_2__<br>
|
||||
__MSG_customPrompts_managePrompts_info_default_3__
|
||||
<br><a href="https://micz.it/thunderbird-addon-thunderai/custom-prompts/">__MSG_customPrompts_managePrompts_help__</a></p>
|
||||
__MSG_customPrompts_managePrompts_info_default_3__ <a href="https://micz.it/thunderbird-addon-thunderai/custom-prompts/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a></p>
|
||||
</div>
|
||||
<div id="import_export">
|
||||
<button id="btnExportAll">__MSG_customPrompts_ExportAll__</button><br>
|
||||
|
|
@ -34,23 +34,26 @@
|
|||
<td rowspan="2" class="w25">
|
||||
<label for="txtTextNew">*__MSG_customPrompts_form_label_Text__:</label>
|
||||
<br>
|
||||
<textarea id="txtTextNew" name="text" class="input_new text_output" tabindex="3"></textarea>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="txtTextNew" name="text" class="input_new text_output editor" tabindex="3"></textarea>
|
||||
<ul class="autocomplete-list hidden"></ul>
|
||||
</div>
|
||||
</td>
|
||||
<td class="w19">
|
||||
<label for="selectTypeNew">__MSG_customPrompts_add_to_menu__:</label>
|
||||
<br>
|
||||
<select id="selectTypeNew" name="type" tabindex="4">
|
||||
<select id="selectTypeNew" name="type" tabindex="4" class="type_output">
|
||||
<option value="0">__MSG_customPrompts_add_to_menu_always__</option>
|
||||
<option value="1">__MSG_customPrompts_add_to_menu_reading__</option>
|
||||
<option value="2">__MSG_customPrompts_add_to_menu_composing__</option>
|
||||
</select>
|
||||
</td>
|
||||
<td rowspan="2" class="w19">
|
||||
<input type="checkbox" id="checkboxNeedSelectedNew" name="need_selected" value="1" tabindex="6"> <label for="checkboxNeedSelectedNew">__MSG_customPrompts_form_label_need_selected__</label>
|
||||
<span class="need_selected_span"><input type="checkbox" id="checkboxNeedSelectedNew" name="need_selected" class="need_selected_new" value="1" tabindex="6"> <label for="checkboxNeedSelectedNew">__MSG_customPrompts_form_label_need_selected__</label></span>
|
||||
<br>
|
||||
<input type="checkbox" id="checkboxNeedSignatureNew" name="need_signature" value="1" tabindex="7"> <label for="checkboxNeedSignatureNew">__MSG_customPrompts_form_label_need_signature__</label>
|
||||
<br>
|
||||
<input type="checkbox" id="checkboxNeedCustomTextNew" name="need_custom_text" value="1" tabindex="8"> <label for="checkboxNeedCustomTextNew">__MSG_customPrompts_form_label_need_custom_text__</label>
|
||||
<span class="need_custom_text_span"><input type="checkbox" id="checkboxNeedCustomTextNew" name="need_custom_text" class="need_custom_text_new" value="1" tabindex="8"> <label for="checkboxNeedCustomTextNew">__MSG_customPrompts_form_label_need_custom_text__</label></span>
|
||||
<br>
|
||||
<input type="checkbox" id="checkboxDefineResponseLangNew" name="define_response_lang" value="1" tabindex="8"> <label for="checkboxDefineResponseLangNew">__MSG_customPrompts_form_label_define_response_lang__</label>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@
|
|||
*/
|
||||
|
||||
import { getPrompts, setDefaultPromptsProperties, setCustomPrompts, preparePromptsForExport, preparePromptsForImport } from "../js/mzta-prompts.js";
|
||||
import { isThunderbird128OrGreater, getCustomPromptsUsedSpace } from "../js/mzta-utils.js";
|
||||
import { isThunderbird128OrGreater, getCustomPromptsUsedSpace, sanitizeHtml } from "../js/mzta-utils.js";
|
||||
import { taLogger } from "../js/mzta-logger.js";
|
||||
import { getPlaceholders } from "../js/mzta-placeholders.js";
|
||||
|
||||
var promptsList = null;
|
||||
var somethingChanged = false;
|
||||
|
|
@ -27,6 +28,7 @@ var positionMax_display = 0;
|
|||
var idnumMax = 0;
|
||||
var msgTimeout = null;
|
||||
let taLog = null;
|
||||
let autocompleteSuggestions = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
|
|
@ -111,6 +113,27 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
});
|
||||
}
|
||||
|
||||
const textareas = document.querySelectorAll('.editor');
|
||||
autocompleteSuggestions = (await getPlaceholders(true)).map(p => ({command: '{%'+p.id+'%}', type: p.type}));
|
||||
|
||||
// console.log('>>>>>>>>>>> suggestions: ' + JSON.stringify(suggestions));
|
||||
|
||||
textareas.forEach(textarea => textareaAutocomplete(textarea, autocompleteSuggestions));
|
||||
|
||||
// document.addEventListener('click', (e) => {
|
||||
// // Check if the click was outside the textarea or suggestion list
|
||||
// const isClickInsideTextarea = e.target.closest('.editor');
|
||||
// const isClickInsideAutocompleteList = e.target.closest('.autocomplete-list');
|
||||
|
||||
// if (!isClickInsideTextarea && !isClickInsideAutocompleteList) {
|
||||
// textareas.forEach(textarea => {
|
||||
// const container = textarea.closest('.autocomplete-container');
|
||||
// const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
// hideSuggestions(autocompleteList);
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
i18n.updateDocument();
|
||||
|
||||
//To add a new item
|
||||
|
|
@ -274,7 +297,9 @@ function showItemRowEditor(tr) {
|
|||
tr.querySelector('.id_show').style.display = 'none';
|
||||
tr.querySelector('.name_output').style.display = 'inline';
|
||||
tr.querySelector('.name_show').style.display = 'none';
|
||||
tr.querySelector('.text_output').style.display = 'inline';
|
||||
const text_output = tr.querySelector('.text_output');
|
||||
text_output.style.display = 'inline';
|
||||
textareaAutocomplete(text_output, autocompleteSuggestions)
|
||||
tr.querySelector('.text_show').style.display = 'none';
|
||||
tr.querySelector('.type_output').style.display = 'inline';
|
||||
tr.querySelector('.type_show').style.display = 'none';
|
||||
|
|
@ -324,6 +349,13 @@ function handleCancelClick(e) {
|
|||
// tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
|
||||
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
|
||||
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
|
||||
tr.querySelector('.id_output').value = tr.querySelector('.id_show').innerText.toLocaleUpperCase();
|
||||
tr.querySelector('.name_output').value = tr.querySelector('.name_show').innerText;
|
||||
tr.querySelector('.text_output').value = sanitizeHtml(tr.querySelector('.text_show').innerHTML).replace(/<br\s*\/?>/gi, "\n");
|
||||
tr.querySelector('.type_output').value = tr.querySelector('.type').innerText;
|
||||
// tr.querySelector('.type_output').selectedOptions[0].text = tr.querySelector('.type_show').innerText;
|
||||
tr.querySelector('.action_output').value = tr.querySelector('.action').innerText;
|
||||
// tr.querySelector('.action_output').selectedOptions[0].text = tr.querySelector('.action_show').innerText;
|
||||
hideItemRowEditor(tr);
|
||||
}
|
||||
|
||||
|
|
@ -353,6 +385,11 @@ function handleCheckboxChange(e) {
|
|||
e.preventDefault();
|
||||
e.target.setAttribute('checked_val', e.target.checked ? '1' : '0');
|
||||
//console.log('>>>>>>>> checked_val: ' + e.target.getAttribute('checked_val'));
|
||||
if (e.target.classList.contains('need_selected') || e.target.classList.contains('need_custom_text') || e.target.classList.contains('need_selected_new') || e.target.classList.contains('need_custom_text_new')) {
|
||||
let textarea = e.target.closest('tr').querySelector('.text_output');
|
||||
checkPromptsConfigForPlaceholders(textarea);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enable save button on input change
|
||||
|
|
@ -399,7 +436,7 @@ function loadPromptsList(values){
|
|||
let output = `<tr ` + ((values.is_default == 1) ? 'class="is_default"':'') + `>
|
||||
<td class="w08"><span class="id id_show"></span><input type="text" class="hiddendata id_output" value="` + values.id + `" /></td>
|
||||
<td class="w08"><span class="name name_show"></span><input type="text" class="hiddendata name_output" value="` + values.name + `" /></td>
|
||||
<td class="w40"><span class="text text_show"></span><textarea class="hiddendata text_output">` + values.text + `</textarea></td>
|
||||
<td class="w40"><span class="text text_show"></span><div class="autocomplete-container"><textarea class="hiddendata text_output editor">` + values.text.replace(/<br\s*\/?>/gi, "\n") + `</textarea><ul class="autocomplete-list hidden"></ul></div></td>
|
||||
<td class="w08"><span class="type_show">` + type_output + `</span>
|
||||
<select class="type_output hiddendata">
|
||||
<option value="0"` + ((values.type == "0") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_always__</option>
|
||||
|
|
@ -417,11 +454,11 @@ function loadPromptsList(values){
|
|||
</select>` +
|
||||
`<span class="action hiddendata"></span>
|
||||
<br>
|
||||
<input type="checkbox" class="need_selected" disabled> __MSG_customPrompts_form_label_need_selected__
|
||||
<span class="need_selected_span"><input type="checkbox" class="need_selected" disabled> __MSG_customPrompts_form_label_need_selected__</span>
|
||||
<br>
|
||||
<input type="checkbox" class="need_signature" disabled> __MSG_customPrompts_form_label_need_signature__
|
||||
<br>
|
||||
<input type="checkbox" class="need_custom_text` + ((values.is_default == 1) ? ' input_mod':'') + `"` + ((values.is_default == 0) ? ' disabled':'') + ` > __MSG_customPrompts_form_label_need_custom_text__
|
||||
<span class="need_custom_text_span"><input type="checkbox" class="need_custom_text` + ((values.is_default == 1) ? ' input_mod':'') + `"` + ((values.is_default == 0) ? ' disabled':'') + ` > __MSG_customPrompts_form_label_need_custom_text__</span>
|
||||
<br>
|
||||
<input type="checkbox" class="define_response_lang" disabled> __MSG_customPrompts_form_label_define_response_lang__
|
||||
<br>
|
||||
|
|
@ -642,3 +679,142 @@ if(await isThunderbird128OrGreater()){
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function textareaAutocomplete(textarea, suggestions) {
|
||||
const container = textarea.closest('.autocomplete-container');
|
||||
const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
let activeIndex = -1;
|
||||
|
||||
textarea.addEventListener('input', () => {
|
||||
const cursorPosition = textarea.selectionStart;
|
||||
const text = textarea.value.substring(0, cursorPosition);
|
||||
const match = text.match(/{%[^\s]*$/);
|
||||
|
||||
checkPromptsConfigForPlaceholders(textarea);
|
||||
|
||||
if (match) {
|
||||
const lastWord = match[0];
|
||||
const tr = textarea.parentNode.parentNode.parentNode;
|
||||
let type = tr.querySelector('.type_output').value
|
||||
// console.log(">>>>>>>>> type: " + type);
|
||||
// console.log(">>>>>>>>> suggestions: " + JSON.stringify(suggestions));
|
||||
// console.log(">>>>>>>>> lastWord: " + lastWord);
|
||||
const matches = suggestions.filter(s => s.command.startsWith(lastWord) && (String(s.type) == String(type) || String(s.type) == '0' )).map(s => s.command);
|
||||
// console.log(">>>>>>>>> matches: " + JSON.stringify(matches));
|
||||
showSuggestions(matches, autocompleteList);
|
||||
} else {
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
});
|
||||
|
||||
textarea.addEventListener('keydown', (e) => {
|
||||
if (autocompleteList.classList.contains('hidden')) {
|
||||
return;
|
||||
}
|
||||
const items = autocompleteList.querySelectorAll('li');
|
||||
if (items.length > 0) {
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
activeIndex = (activeIndex + 1) % items.length;
|
||||
updateActiveSuggestion(items, activeIndex);
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
activeIndex = (activeIndex - 1 + items.length) % items.length;
|
||||
updateActiveSuggestion(items, activeIndex);
|
||||
} else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if(activeIndex === -1) activeIndex = 0;
|
||||
if (activeIndex >= 0 && activeIndex < items.length) {
|
||||
insertAutocomplete(items[activeIndex].textContent, textarea);
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
} else if (e.key === 'Escape') {
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function showSuggestions(matches, autocompleteList) {
|
||||
autocompleteList.innerHTML = '';
|
||||
activeIndex = -1;
|
||||
if (matches.length === 0) {
|
||||
hideSuggestions(autocompleteList);
|
||||
return;
|
||||
}
|
||||
matches.forEach(match => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = match;
|
||||
li.addEventListener('click', () => {
|
||||
insertAutocomplete(match, textarea);
|
||||
hideSuggestions(autocompleteList);
|
||||
});
|
||||
autocompleteList.appendChild(li);
|
||||
});
|
||||
autocompleteList.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function hideSuggestions(autocompleteList) {
|
||||
autocompleteList.classList.add('hidden');
|
||||
activeIndex = -1;
|
||||
}
|
||||
|
||||
function updateActiveSuggestion(items, activeIndex) {
|
||||
items.forEach((item, index) => {
|
||||
item.classList.remove('active');
|
||||
if (index === activeIndex) {
|
||||
item.classList.add('active');
|
||||
item.scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertAutocomplete(suggestion, textarea) {
|
||||
const cursorPosition = textarea.selectionStart;
|
||||
const textBefore = textarea.value.substring(0, cursorPosition);
|
||||
const textAfter = textarea.value.substring(cursorPosition);
|
||||
const match = textBefore.match(/{%[^\s]*$/);
|
||||
if (match) {
|
||||
const lastWord = match[0];
|
||||
const completion = suggestion.substring(lastWord.length);
|
||||
const newText = textBefore + completion + textAfter;
|
||||
textarea.value = newText;
|
||||
const newCursorPosition = cursorPosition + completion.length;
|
||||
textarea.setSelectionRange(newCursorPosition, newCursorPosition);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
// Check if the click was outside the textarea or suggestion list
|
||||
const isClickInsideTextarea = e.target.closest('.editor');
|
||||
const isClickInsideAutocompleteList = e.target.closest('.autocomplete-list');
|
||||
|
||||
if (!isClickInsideTextarea && !isClickInsideAutocompleteList) {
|
||||
const container = textarea.closest('.autocomplete-container');
|
||||
const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function checkPromptsConfigForPlaceholders(textarea){
|
||||
// check additional_text and selected_text placeholders presence and the corrispondent checkboxes
|
||||
if(String(textarea.value).indexOf('{%additional_text%}') != -1){
|
||||
let tr_ancestor = textarea.closest('tr');
|
||||
let need_custom_text_element = tr_ancestor.querySelector('.need_custom_text') || tr_ancestor.querySelector('.need_custom_text_new');
|
||||
if(!need_custom_text_element.checked){
|
||||
need_custom_text_element.closest('.need_custom_text_span').style.border = '2px solid red';
|
||||
}else{
|
||||
need_custom_text_element.closest('.need_custom_text_span').style.border = '';
|
||||
}
|
||||
}
|
||||
if(String(textarea.value).indexOf('{%selected_text%}') != -1){
|
||||
let tr_ancestor = textarea.closest('tr');
|
||||
let selected_text_element = tr_ancestor.querySelector('.need_selected') || tr_ancestor.querySelector('.need_selected_new');
|
||||
if(!selected_text_element.checked){
|
||||
selected_text_element.closest('.need_selected_span').style.border = '2px solid red';
|
||||
}else{
|
||||
selected_text_element.closest('.need_selected_span').style.border = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ async function chatgpt_isIdle() {
|
|||
}}, 100);});}
|
||||
|
||||
function chatgpt_getRegenerateButton() {
|
||||
for (const mainSVG of document.querySelectorAll('main svg')) {
|
||||
for (const mainSVG of document.querySelectorAll('main svg.icon-md')) {
|
||||
if (mainSVG.querySelector('path[d^="M3.06957"]')) // regen icon found
|
||||
return mainSVG.parentNode.parentNode;
|
||||
}
|
||||
|
|
@ -105,6 +105,7 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
style.textContent += ".btn_disabled:hover {background-color:#6a829b !important;color:white !important;}";
|
||||
style.textContent += "#mzta-loading{height:50px;display:inline-block;}";
|
||||
style.textContent += "#mzta-model_warn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-height:100%px;min-width:30%;max-width:50%;padding:3px;border-radius:5px;text-align:center;background-color:#FFBABA;border:1px solid;font-size:13px;color:#D8000C;display:none;}#mzta-model_warn a{color:blue;text-decoration: underline;}";
|
||||
style.textContent += "#mzta-btn_model {background-color: #007bff;border: none;color: white;padding: 2px 4px;text-align: center;text-decoration: none;display: none;font-size: 13px;margin-left: 4px;transition-duration: 0.4s;cursor: pointer;border-radius: 2px;}";
|
||||
style.textContent += "#mzta-status-page{position:fixed;bottom:0;left:0;padding-left:5px;font-size:13px;font-style:italic;text-decoration:underline;color:#919191;}";
|
||||
style.textContent += "#mzta-force-completion{cursor:pointer;position:fixed;bottom:0;right:0;padding-right:5px;font-size:13px;font-style:italic;text-decoration:underline;color:#919191;}";
|
||||
style.textContent += "#mzta-status-page:hover, #mzta-force-completion:hover{color:#007bff;}";
|
||||
|
|
@ -128,6 +129,15 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
modelWarnDiv.textContent = browser.i18n.getMessage("chatgpt_win_model_warning");
|
||||
fixedDiv.appendChild(modelWarnDiv);
|
||||
|
||||
// GPT Model Button
|
||||
var btn_model = document.createElement('button');
|
||||
btn_model.id="mzta-btn_model";
|
||||
btn_model.textContent = browser.i18n.getMessage("chatgpt_btn_model");
|
||||
btn_model.onclick = async function() {
|
||||
force_go = true;
|
||||
};
|
||||
modelWarnDiv.appendChild(btn_model);
|
||||
|
||||
//prompt name
|
||||
var prompt_name_div = document.createElement('div');
|
||||
prompt_name_div.id = 'mzta-prompt-name';
|
||||
|
|
@ -234,6 +244,41 @@ function customTextBtnClick(args) {
|
|||
args.customDiv.style.display = 'none';
|
||||
}
|
||||
|
||||
function checkGPTModel(model) { //TODO
|
||||
if(model == '') return;
|
||||
return new Promise((resolve, reject) => {
|
||||
// Set up an interval that shows the warning after 2 seconds
|
||||
const intervalId2 = setTimeout(() => {
|
||||
document.getElementById('mzta-model_warn').style.display = 'inline-block';
|
||||
document.getElementById('mzta-btn_model').style.display = 'inline';
|
||||
}, 2000);
|
||||
// Set up an interval that checks the value every 100 milliseconds
|
||||
const intervalId = setInterval(() => {
|
||||
// Get the '.text-token-text-secondary' element
|
||||
// const element = document.querySelector('div#radix-\\\\:ri2\\\\: > div > span.text-token-text-secondary');
|
||||
const elements = document.querySelectorAll('[id*=radix] span')
|
||||
|
||||
for(element of elements){
|
||||
// Check if the element exists and its content is '4' or '4o'
|
||||
if ((element && element.textContent === model)||(force_go)) {
|
||||
console.log("[ThunderAI] The GPT Model is now " + model);
|
||||
clearInterval(intervalId);
|
||||
clearTimeout(intervalId2);
|
||||
document.getElementById('mzta-model_warn').style.display = 'none';
|
||||
document.getElementById('mzta-btn_model').style.display = 'none';
|
||||
resolve(model);
|
||||
break;
|
||||
} else if (!element) {
|
||||
console.error("[ThunderAI] Model string element not found! [" + model + "]");
|
||||
clearInterval(intervalId);
|
||||
reject("Model string element not found: " + model);
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function operation_done(){
|
||||
let curr_msg = document.getElementById('mzta-curr_msg');
|
||||
curr_msg.textContent = browser.i18n.getMessage("chatgpt_win_job_completed");
|
||||
|
|
@ -256,7 +301,25 @@ function showCustomTextField(){
|
|||
}
|
||||
|
||||
async function doProceed(message, customText = ''){
|
||||
let send_result = await chatgpt_sendMsg(message.prompt+' '+customText,'click');
|
||||
let _gpt_model = mztaGPTModel;
|
||||
if(_gpt_model != ''){
|
||||
await checkGPTModel(_gpt_model);
|
||||
}
|
||||
let final_prompt = message.prompt;
|
||||
// console.log(">>>>>>>>>>>> doProceed customText: " + customText);
|
||||
// console.log(">>>>>>>>>>>> doProceed final_prompt: " + final_prompt);
|
||||
// console.log(">>>>>>>>>>>> doProceed mztaPhDefVal: " + JSON.stringify(mztaPhDefVal));
|
||||
//check if there is che additional_text placeholder
|
||||
if(final_prompt.includes('{%additional_text%}')){
|
||||
// console.log(">>>>>>>>>>>> found ph customText: " + customText);
|
||||
final_prompt = final_prompt.replace('{%additional_text%}', customText || (mztaPhDefVal == '1'?'':'{%additional_text%}'));
|
||||
}else{
|
||||
if(customText != ''){
|
||||
final_prompt += ' '+customText;
|
||||
}
|
||||
}
|
||||
|
||||
let send_result = await chatgpt_sendMsg(final_prompt,'click');
|
||||
//console.log(">>>>>>>>>>> send_result: " + send_result);
|
||||
switch(send_result){
|
||||
case -1: // send button not found
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ switch (message.command) {
|
|||
case "replaceSelectedText":
|
||||
const selectedText = window.getSelection().toString();
|
||||
if (selectedText === '') {
|
||||
return false;
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
const sel = window.getSelection();
|
||||
if (!sel || sel.type !== "Range" || !sel.rangeCount) {
|
||||
return false;
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
const r = sel.getRangeAt(0);
|
||||
r.deleteContents();
|
||||
|
|
@ -55,19 +55,129 @@ switch (message.command) {
|
|||
case "getTextOnly":
|
||||
return Promise.resolve(window.document.body.innerText);
|
||||
|
||||
case 'promptTooLong':
|
||||
alert(browser.i18n.getMessage('msg_prompt_too_long'));
|
||||
return Promise.resolve(true);
|
||||
break;
|
||||
case "getFullHtml":
|
||||
return Promise.resolve(window.document.body.innerHTML);
|
||||
|
||||
case 'sendAlert':
|
||||
alert(message.message);
|
||||
//console.log(">>>>>> message.curr_tab_type: " + JSON.stringify(message.curr_tab_type));
|
||||
if(message.curr_tab_type == 'mail'){ // workaround for Thunderbird bug not showing the alert
|
||||
// Create dialog elements
|
||||
const dialog_sendAlert = window.document.createElement('dialog');
|
||||
dialog_sendAlert.classList.add('mzta_dialog');
|
||||
|
||||
const content_sendAlert = window.document.createElement('div');
|
||||
content_sendAlert.classList.add('mzta_dialog_content');
|
||||
|
||||
// Create close button
|
||||
const closeButton_sendAlert = window.document.createElement('button');
|
||||
closeButton_sendAlert.classList.add('mzta_dialog_close');
|
||||
closeButton_sendAlert.id = 'mzta_dialog_close';
|
||||
closeButton_sendAlert.textContent = 'Close';
|
||||
|
||||
// Create message element
|
||||
const message_sendAlert = window.document.createElement('div');
|
||||
message_sendAlert.classList.add('mzta_dialog_message');
|
||||
message_sendAlert.textContent = message.message;
|
||||
|
||||
// Append elements to the dialog
|
||||
content_sendAlert.appendChild(message_sendAlert);
|
||||
content_sendAlert.appendChild(closeButton_sendAlert);
|
||||
dialog_sendAlert.appendChild(content_sendAlert);
|
||||
window.document.body.appendChild(dialog_sendAlert);
|
||||
|
||||
// Show the dialog
|
||||
dialog_sendAlert.showModal();
|
||||
|
||||
// Close dialog on button click and remove elements from the DOM
|
||||
closeButton_sendAlert.onclick = () => {
|
||||
dialog_sendAlert.close();
|
||||
dialog_sendAlert.addEventListener('close', () => {
|
||||
dialog_sendAlert.remove();
|
||||
style.remove();
|
||||
});
|
||||
};
|
||||
|
||||
// CSS styles for Thunderbird with support for light and dark themes
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.mzta_dialog {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
width: 300px;
|
||||
max-width: 90%;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
background-color: var(--dialog-bg-color, #fff);
|
||||
color: var(--dialog-text-color, #000);
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.mzta_dialog_content {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.mzta_dialog_close {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
background: #007bff;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.mzta_dialog_close:hover {
|
||||
background: #0056b3;
|
||||
}
|
||||
|
||||
.mzta_dialog_message {
|
||||
margin-bottom: 40px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Theme support */
|
||||
:root {
|
||||
--dialog-bg-color: #ffffff;
|
||||
--dialog-text-color: #000000;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--dialog-bg-color: #2e2e2e;
|
||||
--dialog-text-color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Darker overlay for the page background */
|
||||
.mzta_dialog_overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
z-index: 1000;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
}else{
|
||||
alert(message.message);
|
||||
}
|
||||
return Promise.resolve(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
// do nothing
|
||||
return false;
|
||||
return Promise.resolve(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
|
@ -19,9 +19,10 @@
|
|||
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
|
||||
|
||||
import { getPrompts } from './mzta-prompts.js';
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet } from './mzta-utils.js'
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject } from './mzta-utils.js'
|
||||
import { taLogger } from './mzta-logger.js';
|
||||
|
||||
import { placeholdersUtils } from './mzta-placeholders.js';
|
||||
|
||||
export class mzta_Menus {
|
||||
|
||||
allPrompts = [];
|
||||
|
|
@ -73,32 +74,31 @@ export class mzta_Menus {
|
|||
|
||||
let curr_menu_entry = {id: curr_prompt.id, is_default: curr_prompt.is_default, name: curr_prompt.name};
|
||||
|
||||
const getHighlight = async () => {
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
const getMailBody = async (tabs) => {
|
||||
//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" }),
|
||||
text: await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" })
|
||||
text: await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" }),
|
||||
html: await browser.tabs.sendMessage(tabs[0].id, { command: "getFullHtml" }),
|
||||
};
|
||||
};
|
||||
|
||||
curr_menu_entry.act = async () => {
|
||||
const msg_text = await getHighlight();
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
const msg_text = await getMailBody(tabs);
|
||||
|
||||
//check if a selection is needed
|
||||
if(String(curr_prompt.need_selected) == "1" && (msg_text.selection==='')){
|
||||
//A selection is needed, but nothing is selected!
|
||||
//alert(browser.i18n.getMessage('prompt_selection_needed'));
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", message : browser.i18n.getMessage('prompt_selection_needed') });
|
||||
browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", curr_tab_type: tabs[0].type, message : browser.i18n.getMessage('prompt_selection_needed') });
|
||||
return;
|
||||
}
|
||||
|
||||
var body_text = '';
|
||||
if (msg_text.selection!=='') {
|
||||
body_text = msg_text.selection.replace(/\s+/g, ' ').trim();
|
||||
} else {
|
||||
body_text = msg_text.text.replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
let body_text = '';
|
||||
let selection_text = '';
|
||||
selection_text = msg_text.selection.replace(/\s+/g, ' ').trim();
|
||||
body_text = msg_text.text.replace(/\s+/g, ' ').trim();
|
||||
//open chatgpt window
|
||||
//console.log("Click menu item...");
|
||||
let chatgpt_lang = '';
|
||||
|
|
@ -112,9 +112,54 @@ export class mzta_Menus {
|
|||
chatgpt_lang = browser.i18n.getMessage("prompt_lang") + " " + chatgpt_lang + ".";
|
||||
}
|
||||
}
|
||||
|
||||
var fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + body_text + "\" ";
|
||||
|
||||
|
||||
let fullPrompt = '';
|
||||
if(!placeholdersUtils.hasPlaceholder(curr_prompt.text)){
|
||||
// no placeholders, do as usual
|
||||
fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + (selection_text=='' ? body_text : selection_text) + "\" ";
|
||||
}else{
|
||||
// we have at least a placeholder, do the magic!
|
||||
let currPHs = await placeholdersUtils.extractPlaceholders(curr_prompt.text);
|
||||
// console.log(">>>>>>>>>> currPHs: " + JSON.stringify(currPHs));
|
||||
let finalSubs = {};
|
||||
let curr_messages = await browser.mailTabs.getSelectedMessages();
|
||||
let curr_message = curr_messages.messages[0];
|
||||
for(let currPH of currPHs){
|
||||
switch(currPH.id){
|
||||
case 'mail_text_body':
|
||||
finalSubs['mail_text_body'] = body_text;
|
||||
break;
|
||||
case 'mail_html_body':
|
||||
finalSubs['mail_html_body'] = msg_text.html;
|
||||
break;
|
||||
case 'mail_subject':
|
||||
let mail_subject = await getMailSubject(tabs[0]);
|
||||
finalSubs['mail_subject'] = mail_subject;
|
||||
break;
|
||||
case 'selected_text':
|
||||
finalSubs['selected_text'] = selection_text;
|
||||
break;
|
||||
case 'author':
|
||||
finalSubs['author'] = curr_message.author;
|
||||
break;
|
||||
case 'recipients':
|
||||
finalSubs['recipients'] = curr_message.recipients.join(", ");
|
||||
break;
|
||||
case 'cc_list':
|
||||
finalSubs['cc_list'] = curr_message.ccList.join(", ");
|
||||
break;
|
||||
case 'junk_score':
|
||||
finalSubs['junk_score'] = curr_message.junkScore;
|
||||
break;
|
||||
default: // TODO Manage custom placeholders https://github.com/micz/ThunderAI/issues/156
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 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 this.getDefaultSignature():"") + " " + chatgpt_lang;
|
||||
}
|
||||
|
||||
switch(curr_prompt.id){
|
||||
case 'prompt_translate_this':
|
||||
let prefs2 = await browser.storage.sync.get({default_chatgpt_lang: getLanguageDisplayName(browser.i18n.getUILanguage())});
|
||||
|
|
@ -131,7 +176,7 @@ export class mzta_Menus {
|
|||
break;
|
||||
}
|
||||
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
// const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
// add custom text if needed
|
||||
//browser.runtime.sendMessage({command: "chatgpt_open", prompt: fullPrompt, action: curr_prompt.action, tabId: tabs[0].id});
|
||||
this.openChatGPT(fullPrompt, curr_prompt.action, tabs[0].id, curr_prompt.name, curr_prompt.need_custom_text);
|
||||
|
|
|
|||
214
js/mzta-placeholders.js
Normal file
214
js/mzta-placeholders.js
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 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/>.
|
||||
*/
|
||||
|
||||
/* ================= PROMPTS PROPERTIES ========================================
|
||||
|
||||
================ BASE PROPERTIES
|
||||
|
||||
Types (type attribute):
|
||||
0: always show (when composing a part of the text must be selected if need_selected = 1)
|
||||
1: show when reading an email
|
||||
2: show when composing a mail (a part of the text must be selected if need_selected = 1)
|
||||
|
||||
================ USER PROPERTIES
|
||||
Enabled (enabled attribute):
|
||||
0: Disabled
|
||||
1: Enabled
|
||||
|
||||
*/
|
||||
|
||||
const defaultPlaceholders = [
|
||||
{
|
||||
id: 'mail_text_body',
|
||||
name: "__MSG_placeholder_mail_text_body__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'mail_html_body',
|
||||
name: "__MSG_placeholder_mail_html_body__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'mail_subject',
|
||||
name: "__MSG_placeholder_mail_subject__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'selected_text',
|
||||
name: "__MSG_placeholder_selected_text__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'additional_text',
|
||||
name: "__MSG_placeholder_additional_text__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'junk_score',
|
||||
name: "__MSG_placeholder_junk_score__",
|
||||
default_value: "0",
|
||||
type: 1,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'recipients',
|
||||
name: "__MSG_placeholder_recipients__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'cc_list',
|
||||
name: "__MSG_placeholder_cc_list__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'author',
|
||||
name: "__MSG_placeholder_author__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export async function getPlaceholders(onlyEnabled = false){
|
||||
const _defaultPlaceholders = await getDefaultPlaceholders_withProps();
|
||||
// console.log('>>>>>>>>>>>> getPlaceholders _defaultPlaceholders: ' + JSON.stringify(_defaultPlaceholders));
|
||||
const customPlaceholders = await getCustomPlaceholders();
|
||||
// console.log('>>>>>>>>>>>> getPlaceholders customPlaceholders: ' + JSON.stringify(customPlaceholders));
|
||||
let output = _defaultPlaceholders.concat(customPlaceholders);
|
||||
if(onlyEnabled){
|
||||
output = output.filter(obj => obj.enabled != 0);
|
||||
}else{ // order only if we are not filtering, the filtering is for the automplete and we are ordering there after i18n
|
||||
output.sort((a, b) => a.id.localeCompare(b.id));
|
||||
}
|
||||
// console.log('>>>>>>>>>>>> getPlaceholders output: ' + JSON.stringify(output));
|
||||
return output;
|
||||
}
|
||||
|
||||
async function getDefaultPlaceholders_withProps() {
|
||||
let prefs = await browser.storage.local.get({_default_placeholders_properties: null});
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps prefs: ' + JSON.stringify(prefs));
|
||||
//let defaultPlaceholders_prop = [...defaultPlaceholders];
|
||||
let defaultPlaceholders_prop = JSON.parse(JSON.stringify(defaultPlaceholders));
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps defaultPlaceholders: ' + JSON.stringify(defaultPlaceholders));
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
||||
if(prefs._default_placeholders_properties === null){ // no default Placeholders properties saved
|
||||
defaultPlaceholders_prop.forEach((placeholder) => {
|
||||
placeholder.enabled = 1;
|
||||
})
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps [no prop saved] defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
||||
} else { // we have saved default Placeholders properties
|
||||
defaultPlaceholders_prop.forEach((placeholder) => {
|
||||
if(prefs._default_Placeholders_properties?.[placeholder.id]){
|
||||
placeholder.enabled = prefs._default_Placeholders_properties[placeholder.id].enabled;
|
||||
}else{
|
||||
placeholder.enabled = 1;
|
||||
}
|
||||
})
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps [prop saved] defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
||||
}
|
||||
return defaultPlaceholders_prop;
|
||||
}
|
||||
|
||||
async function getCustomPlaceholders() {
|
||||
let prefs = await browser.storage.local.get({_custom_placeholder: null});
|
||||
if(prefs._custom_placeholder === null){
|
||||
return [];
|
||||
} else {
|
||||
return prefs._custom_placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
export async function setDefaultPlaceholdersProperties(placeholders) {
|
||||
let default_placeholders_properties = {};
|
||||
placeholders.forEach((placeholder) => {
|
||||
default_placeholders_properties[placeholder.id] = {enabled: placeholder.enabled};
|
||||
});
|
||||
//console.log('>>>>>>>>>>>>>> default_placeholders_properties: ' + JSON.stringify(default_placeholders_properties));
|
||||
await browser.storage.local.set({_default_placeholders_properties: default_placeholders_properties});
|
||||
}
|
||||
|
||||
export async function setCustomPlaceholders(placeholders) {
|
||||
await browser.storage.local.set({_custom_placeholder: placeholders});
|
||||
}
|
||||
|
||||
|
||||
export const placeholdersUtils = {
|
||||
|
||||
async extractPlaceholders(text) {
|
||||
// Regular expression to match patterns like {%...%}
|
||||
const regex = /{%\s*(.*?)\s*%}/g;
|
||||
let matches = [];
|
||||
let match;
|
||||
|
||||
let activePHs = await getPlaceholders(true);
|
||||
|
||||
// Use exec to find all matches
|
||||
while ((match = regex.exec(text)) !== null) {
|
||||
const foundPH = activePHs.find(ph => ph.id === match[1].trim());
|
||||
if (foundPH) {
|
||||
matches.push(foundPH);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
},
|
||||
|
||||
replacePlaceholders(text, replacements, use_default_value = false, skip_additional_text = false) {
|
||||
// Regular expression to match patterns like {%...%}
|
||||
return text.replace(/{%\s*(.*?)\s*%}/g, function(match, p1) {
|
||||
// p1 contains the key inside {% %}
|
||||
if (skip_additional_text && (p1 === 'additional_text')) {
|
||||
return match;
|
||||
}
|
||||
// Replace if found, otherwise keep the original or substitute with default value
|
||||
return replacements[p1] || (use_default_value ? defaultPlaceholders.find(ph => ph.id === p1).default_value : match);
|
||||
});
|
||||
},
|
||||
|
||||
hasPlaceholder(text, placeholder = "") {
|
||||
let regex;
|
||||
|
||||
// If a specific placeholder is provided, we search for it
|
||||
if (placeholder !== "") {
|
||||
// Dynamically build the regex for the specific placeholder
|
||||
regex = new RegExp(`{%\s*${placeholder}\s*%}`);
|
||||
} else {
|
||||
// Otherwise, we search for any placeholder in the format {% ... %}
|
||||
regex = /{%\s*(.*?)\s*%}/;
|
||||
}
|
||||
|
||||
// Check if the specific or any placeholder is present in the text
|
||||
return regex.test(text);
|
||||
},
|
||||
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ const defaultPrompts = [
|
|||
{
|
||||
id: 'prompt_reply',
|
||||
name: "__MSG_prompt_reply__",
|
||||
text: "Reply to the following email.",
|
||||
text: "Reply to the following email. Reply with only the needed text and with no extra comments or other text.",
|
||||
type: "1",
|
||||
action: "1",
|
||||
need_selected: "0",
|
||||
|
|
@ -74,6 +74,18 @@ const defaultPrompts = [
|
|||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_reply_advanced',
|
||||
name: "__MSG_prompt_reply_advanced__",
|
||||
text: "Reply to the following email {%selected_text%}, considering this is the full thread of emails {%mail_html_body%}. Reply with only the needed text and with no extra comments or other text.",
|
||||
type: "1",
|
||||
action: "1",
|
||||
need_selected: "1",
|
||||
need_signature: "1",
|
||||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_rewrite_polite',
|
||||
name: "__MSG_prompt_rewrite_polite__",
|
||||
|
|
|
|||
|
|
@ -63,6 +63,26 @@ function extractEmail(text) {
|
|||
return match ? match[0] : '';
|
||||
}
|
||||
|
||||
export async function getMailSubject(tab){
|
||||
// console.log(">>>>>>>>>> getMailSubject tab: " + JSON.stringify(tab));
|
||||
if(!["mail", "messageCompose","messageDisplay"].includes(tab.type)){
|
||||
return "";
|
||||
}
|
||||
switch(tab.type){
|
||||
case "mail":
|
||||
let messages_list = await browser.mailTabs.getSelectedMessages(tab.id);
|
||||
return messages_list.messages[0].subject;
|
||||
case "messageDisplay":
|
||||
let message = await messenger.messageDisplay.getDisplayedMessage(tab.id);
|
||||
return message.subject;
|
||||
case "messageCompose":
|
||||
let msg_details = await browser.compose.getComposeDetails(tab.id)
|
||||
return msg_details.subject;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export async function reloadBody(tabId){
|
||||
let composeDetails = await messenger.compose.getComposeDetails(tabId);
|
||||
let originalHtmlBody = composeDetails.body + " ";
|
||||
|
|
@ -87,6 +107,29 @@ export async function replaceBody(tabId, replyHtml) {
|
|||
await messenger.compose.setComposeDetails(tabId, {body: fullBody});
|
||||
}
|
||||
|
||||
export function sanitizeHtml(input) {
|
||||
// Keep only <br> tags and remove all other HTML tags
|
||||
return input.replace(/<(?!br\s*\/?)[^>]+>/gi, '');
|
||||
}
|
||||
|
||||
export function getGPTWebModelString(model) {
|
||||
model = model.toLowerCase().trim();
|
||||
switch (model) {
|
||||
case 'GTP-4o':
|
||||
return '4o';
|
||||
case 'o1-preview':
|
||||
return 'o1-preview';
|
||||
case 'o1-mini':
|
||||
return 'o1-mini';
|
||||
case 'gpt-4':
|
||||
return '4';
|
||||
case 'gpt-4o-mini':
|
||||
return '4o mini';
|
||||
default:
|
||||
return '4o';
|
||||
}
|
||||
}
|
||||
|
||||
export function i18nConditionalGet(str) {
|
||||
// if we are getting a string that starts with '__MSG_' and ends with '__' we return the translated string
|
||||
// using the browser.i18n API
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "ThunderAI",
|
||||
"description": "__MSG_extensionDescription__",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0pre4",
|
||||
"author": "Mic (m@micz.it)",
|
||||
"homepage_url": "https://micz.it/thunderbird-addon-thunderai/",
|
||||
"browser_specific_settings": {
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
"default_popup": "popup/mzta-popup.html"
|
||||
},
|
||||
"compose_action": {
|
||||
"default_area": "formattoolbar",
|
||||
"default_title": "__MSG_menu_title__",
|
||||
"default_icon": "images/icon-32px.png",
|
||||
"default_popup": "popup/mzta-popup.html"
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ 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 { taStore } from './js/mzta-store.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage } from './js/mzta-utils.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString } from './js/mzta-utils.js';
|
||||
|
||||
await migrateCustomPromptsStorage();
|
||||
await migrateDefaultPromptsPropStorage();
|
||||
|
|
@ -245,10 +244,11 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
taLog.changeDebug(prefs.do_debug);
|
||||
prefs = checkScreenDimensions(prefs);
|
||||
//console.log(">>>>>>>>>>>>>>>> prefs: " + JSON.stringify(prefs));
|
||||
taLog.log("[ThunderAI] Prompt length: " + promptText.length);
|
||||
if(promptText.length > 30000 ){
|
||||
taLog.log("Prompt length: " + promptText.length);
|
||||
if(promptText.length > prefs.max_prompt_length){
|
||||
// Prompt too long for ChatGPT
|
||||
browser.tabs.sendMessage(curr_tabId, { command: "promptTooLong" });
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -259,9 +259,20 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
// We are using the ChatGPT web interface
|
||||
|
||||
let rand_call_id = '_chatgptweb_' + generateCallID();
|
||||
let call_opt = '';
|
||||
|
||||
if(prefs.chatgpt_web_tempchat){
|
||||
call_opt += '&temporary-chat=true';
|
||||
}
|
||||
|
||||
if(prefs.chatgpt_web_model != ''){
|
||||
call_opt += '&model=' + encodeURIComponent(prefs.chatgpt_web_model).toLowerCase();
|
||||
}
|
||||
|
||||
taLog.log("[chatgpt_web] call_opt: " + call_opt);
|
||||
|
||||
let win_options = {
|
||||
url: "https://chatgpt.com?call_id=" + rand_call_id,
|
||||
url: "https://chatgpt.com?call_id=" + rand_call_id + call_opt,
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +285,9 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
|
||||
const listener = (message, sender, sendResponse) => {
|
||||
async function handleChatGptWeb(createdTab) {
|
||||
taLog.log("[ThunderAI] ChatGPT web interface script started...");
|
||||
taLog.log("ChatGPT web interface script started...");
|
||||
|
||||
let _gpt_model = getGPTWebModelString(prefs.chatgpt_web_model);
|
||||
|
||||
let pre_script = `let mztaWinId = `+ createdTab.windowId +`;
|
||||
let mztaStatusPageDesc="`+ browser.i18n.getMessage("prefs_status_page") +`";
|
||||
|
|
@ -282,6 +295,8 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
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="`+ _gpt_model +`";
|
||||
`;
|
||||
|
||||
taLog.log("Waiting 1 sec");
|
||||
|
|
@ -343,7 +358,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
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),
|
||||
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",
|
||||
}
|
||||
|
||||
|
|
@ -400,7 +415,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
browser.runtime.onMessage.addListener(listener3);
|
||||
|
||||
let win_options3 = {
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id3),
|
||||
url: browser.runtime.getURL('api_webchat/index.html?llm='+prefs.connection_type+'&call_id='+rand_call_id3+'&ph_def_val='+(prefs.placeholders_use_default_value?'1':'0')),
|
||||
type: "popup",
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +466,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
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),
|
||||
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",
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ export const prefs_default = {
|
|||
chatgpt_win_width: 700,
|
||||
default_chatgpt_lang: '',
|
||||
connection_type: 'chatgpt_web', //Other values: 'chatgpt_api', 'ollama_api', 'openai_comp_api'
|
||||
chatgpt_web_model: '',
|
||||
chatgpt_web_tempchat: false,
|
||||
chatgpt_api_key: '',
|
||||
chatgpt_model: '',
|
||||
ollama_host: '',
|
||||
|
|
@ -33,4 +35,6 @@ export const prefs_default = {
|
|||
openai_comp_chat_name: 'OpenAI Comp',
|
||||
dynamic_menu_force_enter: false,
|
||||
dynamic_menu_order_alphabet: true,
|
||||
placeholders_use_default_value: false,
|
||||
max_prompt_length: 30000, // max string length for prompt
|
||||
}
|
||||
|
|
@ -84,6 +84,17 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>
|
||||
<span>__MSG_prefs_OptionText_placeholders_use_default_value__</span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="placeholders_use_default_value" name="placeholders_use_default_value" class="option-input" />
|
||||
<span>__MSG_prefs_OptionText_placeholders_use_default_value_info__</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label>
|
||||
|
|
@ -93,8 +104,8 @@
|
|||
<td>
|
||||
<label>
|
||||
<select id="connection_type" name="connection_type" class="option-input">
|
||||
<option value="chatgpt_web">__MSG_prefs_Connection_type_ChatGTP_Web__</option>
|
||||
<option value="chatgpt_api">__MSG_prefs_Connection_type_ChatGTP_API__</option>
|
||||
<option value="chatgpt_web">__MSG_prefs_Connection_type_ChatGPT_Web__</option>
|
||||
<option value="chatgpt_api">__MSG_prefs_Connection_type_ChatGPT_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>
|
||||
|
|
@ -102,6 +113,29 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="conntype_chatgpt_web">
|
||||
<td><label>
|
||||
<span>__MSG_prefs_OptionText_chatgpt_web_model__</span>
|
||||
<br><table><tr><td><i style="font-size:smaller;"><nobr>__MSG_AllowedValues__:</nobr></i></td><td><i style="font-size:smaller;"> <nobr>gpt-4o</nobr> <nobr>gpt-4o-mini</nobr> <nobr>gpt-4</nobr> <nobr>o1-mini</nobr> <nobr>o1-preview</nobr></i></td></tr></table>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="text" id="chatgpt_web_model" name="chatgpt_web_model" class="option-input" />
|
||||
<br>__MSG_prefs_OptionText_chatgpt_web_model_info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_chatgpt_web">
|
||||
<td><label>
|
||||
<span>__MSG_prefs_OptionText_chatgpt_web_tempchat__</span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="chatgpt_web_tempchat" name="chatgpt_web_tempchat" class="option-input" />
|
||||
<span>__MSG_prefs_OptionText_chatgpt_web_tempchat_info__</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_chatgpt_web">
|
||||
<td><label>
|
||||
<span>__MSG_OpenChatGPTTab_Info__</span>
|
||||
|
|
@ -223,6 +257,15 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="max_prompt_length_tr">
|
||||
<td><span>__MSG_prefs_OptionText_max_prompt_length__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="max_prompt_length" name="max_prompt_length" class="option-input" />
|
||||
<br>__MSG_prefs_OptionText_max_prompt_length_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:20em"><label>
|
||||
<span>__MSG_Debug__</span>
|
||||
|
|
@ -237,6 +280,7 @@
|
|||
</table>
|
||||
<div id="btn_custom_prompts">
|
||||
<button id="btnManagePrompts">__MSG_prefs_OptionText_btnManagePrompts__</button>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
</div>
|
||||
<div id="miczDescription">
|
||||
<h1>__MSG_prefsInfoTitle__</h1>
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ async function restoreOptions() {
|
|||
}
|
||||
|
||||
function showConnectionOptions() {
|
||||
disable_MaxPromptLength();
|
||||
let chatgpt_web_display = 'table-row';
|
||||
let chatgpt_api_display = 'none';
|
||||
let ollama_api_display = 'none';
|
||||
|
|
@ -176,7 +177,7 @@ function warn_Ollama_HostEmpty() {
|
|||
if((modelOllama.selectedIndex === -1)||(modelOllama.value === '')){
|
||||
modelOllama.style.border = '2px solid red';
|
||||
}else{
|
||||
modelOllama.style.border = 'none';
|
||||
modelOllama.style.border = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -203,6 +204,14 @@ function warn_OpenAIComp_HostEmpty() {
|
|||
}
|
||||
}
|
||||
|
||||
function disable_MaxPromptLength(){
|
||||
let maxPromptLength = document.getElementById('max_prompt_length');
|
||||
let conntype_select = document.getElementById("connection_type");
|
||||
maxPromptLength.disabled = (conntype_select.value === "chatgpt_web");
|
||||
let maxPromptLength_tr = document.getElementById('max_prompt_length_tr');
|
||||
maxPromptLength_tr.style.display = (maxPromptLength.disabled) ? 'none' : 'table-row';
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await restoreOptions();
|
||||
|
||||
|
|
@ -384,6 +393,7 @@ select_openai_comp_model.addEventListener("change", warn_OpenAIComp_HostEmpty);
|
|||
warn_ChatGPT_APIKeyEmpty();
|
||||
warn_Ollama_HostEmpty();
|
||||
warn_OpenAIComp_HostEmpty();
|
||||
disable_MaxPromptLength();
|
||||
|
||||
const passwordField_chatgpt_api_key = document.getElementById('chatgpt_api_key');
|
||||
const toggleIcon_chatgpt_api_key = document.getElementById('toggle_chatgpt_api_key');
|
||||
|
|
|
|||
|
|
@ -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 2.3.0 - ??/??/2024</h2>
|
||||
<ul>
|
||||
<li>The action button in the compose window has been moved to the formatting toolbar [<a href="https://github.com/micz/ThunderAI/issues/173">#173</a>].</li>
|
||||
<li>On the custom prompts page, when editing a prompt, pressing the cancel button will revert any modified values in the form to their saved state.</li>
|
||||
<li>Implemented placeholders to add additional data to prompts [<a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">More info</a>] [<a href="https://github.com/micz/ThunderAI/issues/146">#146</a>, <a href="https://github.com/micz/ThunderAI/issues/153">#153</a>].</li>
|
||||
<li>Text improved for the "Reply to this" prompt.</li>
|
||||
<li>Added an option to set the maximum number of characters in the prompt [<a href="https://github.com/micz/ThunderAI/issues/165">#165</a>].</li>
|
||||
<li>Added a workaround to show an alert message when needed [<a href="https://github.com/micz/ThunderAI/issues/166">#166</a>].</li>
|
||||
<li><i>[ChatGPT Web]</i> Added an option to set the model to use [<a href="https://github.com/micz/ThunderAI/issues/171">#171</a>].</li>
|
||||
<li><i>[ChatGPT Web]</i> Added an option to use the temporary chat [<a href="https://github.com/micz/ThunderAI/issues/169">#169</a>].</li>
|
||||
<li>A few typos fixed [<a href="https://github.com/micz/ThunderAI/issues/170">#170</a>].</li>
|
||||
<li>Added a loading indicator in the menu when sending a prompt.</li>
|
||||
<li>Added a new default prompt that uses the placeholders and allows replying to an email thread. It requires selecting the text of the first email to identify which is the one to reply to and the others in the thread [<a href="https://github.com/micz/ThunderAI/issues/150">#150</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 2.2.2 - 15/10/2024</h2>
|
||||
<ul>
|
||||
<li>APIs error handling improved.</li>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ body {
|
|||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#mzta_sending_prompt{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mzta_autocomplete-item {
|
||||
padding: 4px;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
<body>
|
||||
<div id="mzta_search_banner">
|
||||
<div id="_spacer_div"> </div>
|
||||
<div id="mzta_sending_prompt"><img src="mzta-loading.svg" title="__MSG_SendingPrompt__"></div>
|
||||
<input type="text" id="mzta_search_input" placeholder="__MSG_SearchPrompt__">
|
||||
<div id="mzta_autocomplete-items-loading"><img src="mzta-loading.svg" title="__MSG_Loading__"></div>
|
||||
<div id="mzta_autocomplete-items" style="display: none;"></div>
|
||||
|
|
|
|||
|
|
@ -228,6 +228,8 @@ document.body.insertBefore(banner, document.body.firstChild);
|
|||
|
||||
function sendPrompt(prompt_id, tabId){
|
||||
taLog.log("sendPrompt: " + prompt_id);
|
||||
document.getElementById('mzta_search_input').style.display = 'none';
|
||||
document.getElementById('mzta_sending_prompt').style.display = 'block';
|
||||
browser.runtime.sendMessage({command: "shortcut_do_prompt", tabId: tabId, promptId: prompt_id});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue