Ported all the mods from v3.3.* into v3.4.0
This commit is contained in:
commit
59ae3643a5
14 changed files with 237 additions and 59 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -15,10 +15,25 @@
|
|||
<li>Added the <i>{%empty%}</i> placeholder to prevent the email body from being automatically appended at the end of the prompt [<a href="https://github.com/micz/ThunderAI/issues/345">#345</a>].</li>
|
||||
<li>Added a check for the presence of the correct version of ThunderAI Sparks [<a href="https://github.com/micz/ThunderAI/issues/315">#315</a>].</li>
|
||||
<li><i>[All APIs]</i> Improved the form asking for additional text [<a href="https://github.com/micz/ThunderAI/issues/97">#97</a>].</li>
|
||||
<li><i>[All APIs]</i> Fix: Ensure HTML body is generated from plain text if no parts are available when processing incoming messages for tags or spam.</li>
|
||||
<li>Custom Prompts form improved.</li>
|
||||
<li>Various improvements.</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
<h2>Version 3.3.5 - 22/04/2025</h2>
|
||||
<ul>
|
||||
<li>Using a prompt from the compose window with a "Do reply" action is changed in "Substitute Text", asking also to insert text if none is selected [<a href="https://github.com/micz/ThunderAI/issues/353">#353</a>].</li>
|
||||
<li>Added an option when composing in plain text to remove the extra empty lines [<a href="https://github.com/micz/ThunderAI/issues/350">#350</a>].</li>
|
||||
<li><i>[Ollama API]</i> It's now possibile to define the default context length (the <i>num_ctx</i> parameter) in the options page [<a href="https://github.com/micz/ThunderAI/issues/351">#351</a>].</li>
|
||||
<li><i>[ChatGPT Web]</i> Updated the list of available models in the option page.</li>
|
||||
<li><i>[ChatGPT Web]</i> Opening the ChatGPT webpage from the options now enforce the selected model, if any.</li>
|
||||
<li><i>[All APIs]</i> Fix: Really correctly getting the message body even in multilevel subpart messages when processing incoming messages for tags or spam [<a href="https://github.com/micz/ThunderAI/issues/335">#335</a>].</li>
|
||||
<li>Minor improvements.</li>
|
||||
</ul>
|
||||
<h2>Version 3.3.4 - 14/04/2025</h2>
|
||||
<ul>
|
||||
<li><i>[ChatGPT Web]</i> Fixed a blocking error with the " character in the mail text [<a href="https://github.com/micz/ThunderAI/issues/344">#344</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 3.3.3 - 12/04/2025</h2>
|
||||
<ul>
|
||||
<li><i>[All APIs]</i> Fix: Correctly getting the message body even in multilevel subpart messages when processing incoming messages for tags or spam [<a href="https://github.com/micz/ThunderAI/issues/335">#335</a>].</li>
|
||||
|
|
|
|||
|
|
@ -90,13 +90,13 @@ switch (llm) {
|
|||
break;
|
||||
}
|
||||
case "ollama_api": {
|
||||
let prefs_api = await browser.storage.sync.get({ollama_host: '', ollama_model: '', do_debug: false});
|
||||
let prefs_api = await browser.storage.sync.get({ollama_host: '', ollama_model: '', ollama_num_ctx: 0, do_debug: false});
|
||||
let i18nStrings = {};
|
||||
i18nStrings["ollama_api_request_failed"] = browser.i18n.getMessage('ollama_api_request_failed');
|
||||
i18nStrings["error_connection_interrupted"] = browser.i18n.getMessage('error_connection_interrupted');
|
||||
messageInput.setModel(prefs_api.ollama_model);
|
||||
messagesArea.setLLMName("Ollama Local");
|
||||
worker.postMessage({ type: 'init', ollama_host: prefs_api.ollama_host, ollama_model: prefs_api.ollama_model, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
worker.postMessage({ type: 'init', ollama_host: prefs_api.ollama_host, ollama_model: prefs_api.ollama_model, ollama_num_ctx: prefs_api.ollama_num_ctx, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
browser.runtime.sendMessage({command: "ollama_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
messagesArea.appendUserMessage(browser.i18n.getMessage("ollama_api_connecting") + " \"" + prefs_api.ollama_host + "\" " +browser.i18n.getMessage("AndModel") + " \"" + prefs_api.ollama_model + "\"...", "info");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,9 @@ class MessagesArea extends HTMLElement {
|
|||
const fullTextHTMLAtAssignment = this.fullTextHTML.trim().replace(/^"|"$/g, '').replace(/^<p>"/, '<p>').replace(/"<\/p>$/, '</p>'); // strip quotation marks
|
||||
//console.log(">>>>>>>>>>>> fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
actionButton.addEventListener('click', async () => {
|
||||
if(promptData.mailMessageId == -1) { // we are using the reply from the compose window!
|
||||
promptData.action = "2"; // replace text
|
||||
}
|
||||
switch(promptData.action) {
|
||||
case "1": // do reply
|
||||
// console.log("[ThunderAI] (do reply) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
|
|
@ -239,7 +242,7 @@ class MessagesArea extends HTMLElement {
|
|||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
case "2": // replace text
|
||||
// console.log("[ThunderAI] (replace text) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
// console.log("[ThunderAI] (replace text) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replaceSelectedText", text: fullTextHTMLAtAssignment, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId});
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -21,11 +21,13 @@ export class Ollama {
|
|||
host = '';
|
||||
model = '';
|
||||
stream = false;
|
||||
num_ctx = 0;
|
||||
|
||||
constructor(host, model, stream = false) {
|
||||
constructor(host, model, stream = false, num_ctx = 0) {
|
||||
this.host = host.trim().replace(/\/+$/, "");
|
||||
this.model = model;
|
||||
this.stream = stream;
|
||||
this.num_ctx = num_ctx;
|
||||
}
|
||||
|
||||
fetchModels = async () => {
|
||||
|
|
@ -78,6 +80,7 @@ export class Ollama {
|
|||
model: this.model,
|
||||
messages: messages,
|
||||
stream: this.stream,
|
||||
...(this.num_ctx > 0 ? { options: { num_ctx: parseInt(this.num_ctx) } } : {})
|
||||
}),
|
||||
});
|
||||
return response;
|
||||
|
|
|
|||
|
|
@ -652,6 +652,9 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
current_message = message;
|
||||
current_tabId = message.tabId;
|
||||
current_mailMessageId = message.mailMessageId;
|
||||
if(current_mailMessageId == -1) { // we are using the reply from the compose window!
|
||||
current_action = '2'; // replace text
|
||||
}
|
||||
run();
|
||||
break;
|
||||
case "chatgpt_alive":
|
||||
|
|
|
|||
|
|
@ -24,12 +24,19 @@ switch (message.command) {
|
|||
|
||||
case "replaceSelectedText": {
|
||||
const selectedText = window.getSelection().toString();
|
||||
let force_insert = false;
|
||||
if (selectedText === '') {
|
||||
return Promise.resolve(false);
|
||||
if(!confirm(browser.i18n.getMessage("Replace_No_Selected_Text"))) {
|
||||
return Promise.resolve(false);
|
||||
}else{
|
||||
force_insert = true;
|
||||
}
|
||||
}
|
||||
const sel = window.getSelection();
|
||||
if (!sel || sel.type !== "Range" || !sel.rangeCount) {
|
||||
return Promise.resolve(false);
|
||||
if(!force_insert) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
const r = sel.getRangeAt(0);
|
||||
r.deleteContents();
|
||||
|
|
|
|||
|
|
@ -276,8 +276,12 @@ export const placeholdersUtils = {
|
|||
if (skip_additional_text && (p1 === 'additional_text')) {
|
||||
return match;
|
||||
}
|
||||
const currPlaceholder = defaultPlaceholders.find(ph => ph.id === p1);
|
||||
if (!currPlaceholder) {
|
||||
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);
|
||||
return replacements[p1] || (use_default_value ? currPlaceholder.default_value : match);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -121,41 +121,44 @@ export async function getMailSubject(tab){
|
|||
}
|
||||
}
|
||||
|
||||
export async function getMailBody(fullMessage){
|
||||
let text = '';
|
||||
let html = '';
|
||||
function extractTextParts(fullMessage) {
|
||||
const textParts = [];
|
||||
|
||||
// console.log(">>>>>>>>>> fullMessage.contentType.trim().toLowerCase(): " + fullMessage.contentType.trim().toLowerCase());
|
||||
// console.log(">>>>>>>>>> fullMessage.body: " + fullMessage.body);
|
||||
|
||||
if (fullMessage.contentType.trim().toLowerCase() === "text/plain") {
|
||||
text = fullMessage.body;
|
||||
}
|
||||
if (fullMessage.contentType.trim().toLowerCase() === "text/html") {
|
||||
html = fullMessage.body;
|
||||
}
|
||||
|
||||
if((text == undefined || text == null || text == '') && (html == undefined || html == null || html == '')) {
|
||||
for (let part of fullMessage.parts) {
|
||||
if (part.contentType.trim().toLowerCase() === "text/plain") {
|
||||
text = part.body;
|
||||
}
|
||||
if (part.contentType.trim().toLowerCase() === "text/html") {
|
||||
html = part.body;
|
||||
}
|
||||
if((text == undefined || text == null || text == '') && (html == undefined || html == null || html == '')) {
|
||||
for (let subpart of part.parts) {
|
||||
if (subpart.contentType.trim().toLowerCase() === "text/plain") {
|
||||
text = subpart.body;
|
||||
}
|
||||
if (subpart.contentType.trim().toLowerCase() === "text/html") {
|
||||
html = subpart.body;
|
||||
}
|
||||
function walkParts(parts) {
|
||||
for (const part of parts) {
|
||||
if (part.parts && part.parts.length > 0) {
|
||||
// Recursively walk through sub-parts
|
||||
walkParts(part.parts);
|
||||
} else {
|
||||
// Check if contentType starts with "text/"
|
||||
if (part.contentType && part.contentType.startsWith("text/")) {
|
||||
textParts.push(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fullMessage.parts && fullMessage.parts.length > 0) {
|
||||
walkParts(fullMessage.parts);
|
||||
}
|
||||
|
||||
return textParts;
|
||||
}
|
||||
|
||||
export function getMailBody(fullMessage){
|
||||
const textParts = extractTextParts(fullMessage);
|
||||
let text = "";
|
||||
let html = "";
|
||||
for (const part of textParts) {
|
||||
if (part.contentType === "text/plain") {
|
||||
text += part.body;
|
||||
} else if (part.contentType === "text/html") {
|
||||
html += part.body;
|
||||
}
|
||||
}
|
||||
if(html === "") {
|
||||
html = text.replace(/\n/g, "<br>");
|
||||
}
|
||||
return {text, html};
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +191,18 @@ export function sanitizeHtml(input) {
|
|||
return input.replace(/<(?!br\s*\/?)[^>]+>/gi, '');
|
||||
}
|
||||
|
||||
export function stripHtmlKeepLines(htmlString) {
|
||||
// Replaces <p> tags with a newline at the beginning
|
||||
// and removes all other HTML tags
|
||||
return htmlString
|
||||
.replace(/<p>/gi, '') // removes <p> tags
|
||||
.replace(/<\/p>/gi, '\n') // replaces </p> tags with newline
|
||||
.replace(/<[^>]*>/g, '') // removes any other HTML tags
|
||||
.trim(); // removes leading/trailing whitespace
|
||||
}
|
||||
|
||||
// This method is used to convert the model string id used in the URL
|
||||
// to the model string used in the webpage
|
||||
export function getGPTWebModelString(model) {
|
||||
model = model.toLowerCase().trim();
|
||||
switch (model) {
|
||||
|
|
@ -196,14 +211,6 @@ export function getGPTWebModelString(model) {
|
|||
return '4o';
|
||||
case 'gpt-4o-mini':
|
||||
return '4o mini';
|
||||
case 'gpt-4':
|
||||
return 'gpt-4';
|
||||
case 'o1':
|
||||
return 'o1';
|
||||
case 'o3-mini':
|
||||
return 'o3-mini';
|
||||
case 'o3-mini-high':
|
||||
return 'o3-mini-high';
|
||||
default:
|
||||
return model;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { taLogger } from '../mzta-logger.js';
|
|||
|
||||
let ollama_host = null;
|
||||
let ollama_model = '';
|
||||
let ollama_num_ctx = 0;
|
||||
let ollama = null;
|
||||
let stopStreaming = false;
|
||||
let i18nStrings = null;
|
||||
|
|
@ -39,8 +40,9 @@ self.onmessage = async function(event) {
|
|||
case 'init':
|
||||
ollama_host = event.data.ollama_host;
|
||||
ollama_model = event.data.ollama_model;
|
||||
ollama_num_ctx = event.data.ollama_num_ctx;
|
||||
//console.log(">>>>>>>>>>> ollama_host: " + ollama_host);
|
||||
ollama = new Ollama(ollama_host, ollama_model, true);
|
||||
ollama = new Ollama(ollama_host, ollama_model, true, ollama_num_ctx);
|
||||
do_debug = event.data.do_debug;
|
||||
i18nStrings = event.data.i18nStrings;
|
||||
taLog = new taLogger('model-worker-ollama', do_debug);
|
||||
|
|
|
|||
|
|
@ -20,7 +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 { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData } from './js/mzta-utils.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, stripHtmlKeepLines } from './js/mzta-utils.js';
|
||||
import { taPromptUtils } from './js/mzta-utils-prompt.js';
|
||||
import { mzta_specialCommand } from './js/mzta-special-commands.js';
|
||||
import { getSpamFilterPrompt } from './js/mzta-prompts.js';
|
||||
|
|
@ -205,15 +205,22 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
async function _replaceSelectedText(tabId, text) {
|
||||
//console.log('chatgpt_replaceSelectedText: [' + tabId +'] ' + text)
|
||||
original_html = await getOriginalBody(tabId);
|
||||
let prefs_repl = await browser.storage.sync.get({composing_plain_text: prefs_default.composing_plain_text});
|
||||
if(prefs_repl.composing_plain_text){
|
||||
text = stripHtmlKeepLines(text);
|
||||
}
|
||||
await browser.tabs.sendMessage(tabId, { command: "replaceSelectedText", text: text, tabId: tabId });
|
||||
return true;
|
||||
}
|
||||
return _replaceSelectedText(message.tabId, message.text);
|
||||
case 'chatgpt_replyMessage':
|
||||
async function _replyMessage(message) {
|
||||
const paragraphsHtmlString = message.text;
|
||||
let paragraphsHtmlString = message.text;
|
||||
//console.log(">>>>>>>>>>>> paragraphsHtmlString: " + paragraphsHtmlString);
|
||||
let prefs = await browser.storage.sync.get({reply_type: prefs_default.reply_type});
|
||||
let prefs = await browser.storage.sync.get({reply_type: prefs_default.reply_type, composing_plain_text: prefs_default.composing_plain_text});
|
||||
if(prefs.composing_plain_text){
|
||||
paragraphsHtmlString = stripHtmlKeepLines(paragraphsHtmlString);
|
||||
}
|
||||
//console.log('reply_type: ' + prefs.reply_type);
|
||||
let replyType = 'replyToAll';
|
||||
if(prefs.reply_type === 'reply_sender'){
|
||||
|
|
@ -878,7 +885,7 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
|
|||
|
||||
if (addTagsAuto || spamFilter) {
|
||||
curr_fullMessage = await browser.messages.getFull(message.id);
|
||||
msg_text = await getMailBody(curr_fullMessage);
|
||||
msg_text = getMailBody(curr_fullMessage);
|
||||
body_text = msg_text.text.replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const prefs_default = {
|
|||
chatgpt_win_width: 700,
|
||||
default_chatgpt_lang: '',
|
||||
default_sign_name: '',
|
||||
composing_plain_text: false,
|
||||
connection_type: 'chatgpt_web', //Other values: 'chatgpt_api', 'ollama_api', 'openai_comp_api', 'google_gemini_api'
|
||||
chatgpt_web_model: '',
|
||||
chatgpt_web_tempchat: false,
|
||||
|
|
@ -32,6 +33,7 @@ export const prefs_default = {
|
|||
chatgpt_developer_messages: '',
|
||||
ollama_host: '',
|
||||
ollama_model: '',
|
||||
ollama_num_ctx: 0,
|
||||
openai_comp_host: '', // For OpenAI Compatible API as LM-Studio
|
||||
openai_comp_model: '',
|
||||
openai_comp_api_key: '',
|
||||
|
|
|
|||
|
|
@ -101,6 +101,17 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>
|
||||
<span>__MSG_prefs_OptionText_composing_plain_text__</span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="composing_plain_text" name="composing_plain_text" class="option-input" />
|
||||
<span>__MSG_prefs_OptionText_composing_plain_text_info__</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label>
|
||||
|
|
@ -123,7 +134,7 @@
|
|||
<tr class="conntype_chatgpt_web">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_OptionText_chatgpt_web_model__</span>
|
||||
<br><table title="__MSG_prefs_OptionText_chatgpt_web_model_tooltip__"><tr><td><i class="small_info"><nobr>__MSG_AllowedValues__:</nobr></i></td><td><i class="small_info"> <nobr class="conntype_chatgpt_web_option">gpt-4o</nobr> <nobr class="conntype_chatgpt_web_option">gpt-4o-mini</nobr> <nobr class="conntype_chatgpt_web_option">gpt-4</nobr> <nobr class="conntype_chatgpt_web_option">o1</nobr> <nobr class="conntype_chatgpt_web_option">o3-mini</nobr> <nobr class="conntype_chatgpt_web_option">o3-mini-high</nobr></i></td></tr></table>
|
||||
<br><table title="__MSG_prefs_OptionText_chatgpt_web_model_tooltip__"><tr id="chatgpt_web_models_list"></tr></table>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
|
|
@ -277,6 +288,17 @@
|
|||
<br><br><button id="btnGiveAllUrlsPermission_ollama_api">__MSG_CORS_give_allurls_perm__</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_ollama_api">
|
||||
<td><label>
|
||||
<span>__MSG_prefs_ollama_num_ctx__ <i>[num_ctx]</i></span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="ollama_num_ctx" name="ollama_num_ctx" class="option-input"/>
|
||||
<br>__MSG_prefs_ollama_num_ctx_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_ollama_api">
|
||||
<td>
|
||||
<label>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ let taLog = new taLogger("mzta-options",true);
|
|||
let _isThunderbird128OrGreater = true;
|
||||
let permission_all_urls = false;
|
||||
|
||||
const ChatGPTWeb_models = ['gpt-4o', 'o3', 'o4-mini', 'o4-mini-high', 'gpt-4o-mini'];
|
||||
|
||||
function saveOptions(e) {
|
||||
e.preventDefault();
|
||||
let options = {};
|
||||
|
|
@ -319,6 +321,90 @@ async function disable_GetCalendarEvent(){
|
|||
wrong_sparks_text.style.display = (is_spark_present == 0) ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
|
||||
function getChatGPTWebModelsList_HTML(values, targetRowId) {
|
||||
const rowElement = document.getElementById(targetRowId);
|
||||
if (!rowElement) return;
|
||||
|
||||
// Clears any existing td elements
|
||||
rowElement.innerHTML = '';
|
||||
|
||||
// First TD: label
|
||||
const labelTd = document.createElement('td');
|
||||
const label = document.createElement('i');
|
||||
label.className = 'small_info';
|
||||
const labelNobr = document.createElement('nobr');
|
||||
labelNobr.textContent = browser.i18n.getMessage("AllowedValues") + ":";
|
||||
label.appendChild(labelNobr);
|
||||
labelTd.appendChild(label);
|
||||
|
||||
// Second TD: values
|
||||
const valuesTd = document.createElement('td');
|
||||
const valuesContainer = document.createElement('i');
|
||||
valuesContainer.className = 'small_info';
|
||||
|
||||
values.forEach(value => {
|
||||
const nbspBefore = document.createTextNode(' \u00A0 '); // " "
|
||||
const valueNobr = document.createElement('nobr');
|
||||
valueNobr.className = 'conntype_chatgpt_web_option';
|
||||
valueNobr.textContent = value;
|
||||
const nbspAfter = document.createTextNode(' \u00A0 ');
|
||||
|
||||
valuesContainer.appendChild(nbspBefore);
|
||||
valuesContainer.appendChild(valueNobr);
|
||||
valuesContainer.appendChild(nbspAfter);
|
||||
});
|
||||
|
||||
valuesTd.appendChild(valuesContainer);
|
||||
|
||||
// Adds the td elements to the row
|
||||
rowElement.appendChild(labelTd);
|
||||
rowElement.appendChild(valuesTd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getChatGPTWebModelsList_HTML(values, targetRowId) {
|
||||
const rowElement = document.getElementById(targetRowId);
|
||||
if (!rowElement) return;
|
||||
|
||||
// Clears any existing td elements
|
||||
rowElement.innerHTML = '';
|
||||
|
||||
// First TD: label
|
||||
const labelTd = document.createElement('td');
|
||||
const label = document.createElement('i');
|
||||
label.className = 'small_info';
|
||||
const labelNobr = document.createElement('nobr');
|
||||
labelNobr.textContent = browser.i18n.getMessage("AllowedValues") + ":";
|
||||
label.appendChild(labelNobr);
|
||||
labelTd.appendChild(label);
|
||||
|
||||
// Second TD: values
|
||||
const valuesTd = document.createElement('td');
|
||||
const valuesContainer = document.createElement('i');
|
||||
valuesContainer.className = 'small_info';
|
||||
|
||||
values.forEach(value => {
|
||||
const nbspBefore = document.createTextNode(' \u00A0 '); // " "
|
||||
const valueNobr = document.createElement('nobr');
|
||||
valueNobr.className = 'conntype_chatgpt_web_option';
|
||||
valueNobr.textContent = value;
|
||||
const nbspAfter = document.createTextNode(' \u00A0 ');
|
||||
|
||||
valuesContainer.appendChild(nbspBefore);
|
||||
valuesContainer.appendChild(valueNobr);
|
||||
valuesContainer.appendChild(nbspAfter);
|
||||
});
|
||||
|
||||
valuesTd.appendChild(valuesContainer);
|
||||
|
||||
// Adds the td elements to the row
|
||||
rowElement.appendChild(labelTd);
|
||||
rowElement.appendChild(valuesTd);
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await restoreOptions();
|
||||
|
||||
|
|
@ -337,14 +423,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
element.addEventListener("change", saveOptions);
|
||||
});
|
||||
document.querySelectorAll(".conntype_chatgpt_web_option").forEach(element => {
|
||||
element.addEventListener("click", () => {
|
||||
let el = document.getElementById("chatgpt_web_model");
|
||||
el.value = element.textContent;
|
||||
el.dispatchEvent(new Event('change'), { bubbles: true });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let addtags_el = document.getElementById('add_tags');
|
||||
let addtags_info_btn = document.getElementById('btnManageTagsInfo');
|
||||
addtags_el.addEventListener('click', (event) => {
|
||||
|
|
@ -441,6 +520,15 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
permission_all_urls = await messenger.permissions.request({ origins: ["<all_urls>"] });
|
||||
});
|
||||
|
||||
getChatGPTWebModelsList_HTML(ChatGPTWeb_models, 'chatgpt_web_models_list');
|
||||
document.querySelectorAll(".conntype_chatgpt_web_option").forEach(element => {
|
||||
element.addEventListener("click", () => {
|
||||
let el = document.getElementById("chatgpt_web_model");
|
||||
el.value = element.textContent;
|
||||
el.dispatchEvent(new Event('change'), { bubbles: true });
|
||||
});
|
||||
});
|
||||
|
||||
let conntype_select = document.getElementById("connection_type");
|
||||
conntype_select.addEventListener("change", showConnectionOptions);
|
||||
conntype_select.addEventListener("change", warn_ChatGPT_APIKeyEmpty);
|
||||
|
|
@ -457,7 +545,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
document.getElementById("chatgpt_web_project").addEventListener("input", validateCustomData_ChatGPTWeb);
|
||||
document.getElementById("chatgpt_web_custom_gpt").addEventListener("input", validateCustomData_ChatGPTWeb);
|
||||
|
||||
let prefs = await browser.storage.sync.get({chatgpt_model: '', ollama_model: '', openai_comp_model: '', google_gemini_model: '', chatgpt_win_height: 0, chatgpt_win_width: 0 });
|
||||
let prefs = await browser.storage.sync.get({chatgpt_web_model: '', chatgpt_model: '', ollama_model: '', openai_comp_model: '', google_gemini_model: '', chatgpt_win_height: 0, chatgpt_win_width: 0 });
|
||||
|
||||
// OpenAI API ChatGPT model fetching
|
||||
let select_chatgpt_model = document.getElementById('chatgpt_model');
|
||||
|
|
|
|||
|
|
@ -18,10 +18,25 @@
|
|||
<li>Added a check for the presence of the correct version of ThunderAI Sparks [<a href="https://github.com/micz/ThunderAI/issues/315">#315</a>].</li>
|
||||
<li>Added the <i>{%empty%}</i> placeholder to prevent the email body from being automatically appended at the end of the prompt [<a href="https://github.com/micz/ThunderAI/issues/345">#345</a>].</li>
|
||||
<li><i>[All APIs]</i> Improved the form asking for additional text [<a href="https://github.com/micz/ThunderAI/issues/97">#97</a>].</li>
|
||||
<li><i>[All APIs]</i> Fix: Ensure HTML body is generated from plain text if no parts are available when processing incoming messages for tags or spam.</li>
|
||||
<li>Custom Prompts form improved.</li>
|
||||
<li>Various improvements.</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
<h2>Version 3.3.5 - 22/04/2025</h2>
|
||||
<ul>
|
||||
<li>Using a prompt from the compose window with a "Do reply" action is changed in "Substitute Text", asking also to insert text if none is selected [<a href="https://github.com/micz/ThunderAI/issues/353">#353</a>].</li>
|
||||
<li>Added an option when composing in plain text to remove the extra empty lines [<a href="https://github.com/micz/ThunderAI/issues/350">#350</a>].</li>
|
||||
<li><i>[Ollama API]</i> It's now possibile to define the default context length (the <i>num_ctx</i> parameter) in the options page [<a href="https://github.com/micz/ThunderAI/issues/351">#351</a>].</li>
|
||||
<li><i>[ChatGPT Web]</i> Updated the list of available models in the option page.</li>
|
||||
<li><i>[ChatGPT Web]</i> Opening the ChatGPT webpage from the options now enforce the selected model, if any.</li>
|
||||
<li><i>[All APIs]</i> Fix: Really correctly getting the message body even in multilevel subpart messages when processing incoming messages for tags or spam [<a href="https://github.com/micz/ThunderAI/issues/335">#335</a>].</li>
|
||||
<li>Minor improvements.</li>
|
||||
</ul>
|
||||
<h2>Version 3.3.4 - 14/04/2025</h2>
|
||||
<ul>
|
||||
<li><i>[ChatGPT Web]</i> Fixed a blocking error with the " character in the mail text [<a href="https://github.com/micz/ThunderAI/issues/344">#344</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 3.3.3 - 12/04/2025</h2>
|
||||
<ul>
|
||||
<li><i>[All APIs]</i> Fix: Correctly getting the message body even in multilevel subpart messages when processing incoming messages for tags or spam [<a href="https://github.com/micz/ThunderAI/issues/335">#335</a>].</li>
|
||||
|
|
|
|||
Loading…
Reference in a new issue