Merge branch 'issue_438_autofeat_apimodel' into api_improvements

This commit is contained in:
Mic 2025-09-09 21:54:10 +02:00 committed by GitHub
commit b7953fe366
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 1899 additions and 1167 deletions

View file

@ -10,6 +10,7 @@
<li><i>[ChatGPT Web]</i> Added a message to explain to click on "Force completion" if the ChatGPT job is not done after 7 seconds [<a href="https://github.com/micz/ThunderAI/issues/419">#419</a>].</li> <li><i>[ChatGPT Web]</i> Added a message to explain to click on "Force completion" if the ChatGPT job is not done after 7 seconds [<a href="https://github.com/micz/ThunderAI/issues/419">#419</a>].</li>
<li><i>[All APIs]</i> The prompt id and name are now shown in the information header in the AI API chat [<a href="https://github.com/micz/ThunderAI/issues/436">#436</a>].</li> <li><i>[All APIs]</i> The prompt id and name are now shown in the information header in the AI API chat [<a href="https://github.com/micz/ThunderAI/issues/436">#436</a>].</li>
<li><i>[Google Gemini API]</i>Support for the thinkingBudget parameter has been added [<a href="https://github.com/micz/ThunderAI/issues/494">#494</a>].</li> <li><i>[Google Gemini API]</i>Support for the thinkingBudget parameter has been added [<a href="https://github.com/micz/ThunderAI/issues/494">#494</a>].</li>
<li>Various code improvements and minor bugs fixed.</li>
<li>...</li> <li>...</li>
</ul> </ul>
<h2>Version 3.6.1 - 23/08/2025</h2> <h2>Version 3.6.1 - 23/08/2025</h2>

View file

@ -1140,7 +1140,7 @@
"description": "" "description": ""
}, },
"prompt_add_tags_use_list": { "prompt_add_tags_use_list": {
"message": "Use only these tags, that are comma separated in the list", "message": "Use only the tags in this comma separated list",
"description": "" "description": ""
}, },
"prefs_OptionText_add_tags_auto_only_inbox": { "prefs_OptionText_add_tags_auto_only_inbox": {
@ -1151,6 +1151,10 @@
"message": "If checked, the AI will only add tags to emails received in the inbox folder.", "message": "If checked, the AI will only add tags to emails received in the inbox folder.",
"description": "" "description": ""
}, },
"prefs_OptionText_add_tags_use_specific_integration_Info": {
"message": "If checked, the Model and API specified below will be used for adding tags to emails, regardless the one choosen in the ThunderAI options page.",
"description": ""
},
"placeholder_thunderai_def_sign": { "placeholder_thunderai_def_sign": {
"message": "Default signature as defined in ThunderAI options.", "message": "Default signature as defined in ThunderAI options.",
"description": "" "description": ""
@ -1203,6 +1207,14 @@
"message": "Spam Filter Options", "message": "Spam Filter Options",
"description": "" "description": ""
}, },
"prefs_OptionText_use_specific_integration": {
"message": "Use specific Model and API",
"description": ""
},
"prefs_OptionText_spamfilter_use_specific_integration_Info": {
"message": "If checked, the Model and API specified below will be used for the spam filter, regardless the one chosen in the ThunderAI options page.",
"description": ""
},
"prefs_OptionText_spamfilter_threshold": { "prefs_OptionText_spamfilter_threshold": {
"message": "Spam threshold", "message": "Spam threshold",
"description": "" "description": ""
@ -1652,5 +1664,17 @@
"chatgpt_click_force_completion": { "chatgpt_click_force_completion": {
"message": "It seems that it's not possible to get if ChatGPT has finished. Click here to force the completion of the job.", "message": "It seems that it's not possible to get if ChatGPT has finished. Click here to force the completion of the job.",
"description": "" "description": ""
},
"warn_API_needed": {
"message": "To use this feature, you need an API integration rather than the ChatGPT Web Integration. You can define a specific API in the feature settings page by first checking the checkbox above and then clicking the button on the left.",
"description": ""
},
"prefs_google_gemini_thinking_budget": {
"message": "Thinking Budget",
"description": ""
},
"prefs_google_gemini_thinking_budget_Info": {
"message": "Define the number of tokens to be used for thinking. Leave this field blank if the selected model does not support thinking or if you want to use the default method. Enter 0 to disable thinking, or -1 to enable dynamic thinking.",
"description": ""
} }
} }

View file

@ -95,7 +95,7 @@ switch (llm) {
chatgpt_developer_messages: prefs_api.chatgpt_developer_messages, chatgpt_developer_messages: prefs_api.chatgpt_developer_messages,
chatgpt_api_store: prefs_api.chatgpt_api_store, chatgpt_api_store: prefs_api.chatgpt_api_store,
do_debug: prefs_api.do_debug, do_debug: prefs_api.do_debug,
i18nStrings: i18nStrings i18nStrings: i18nStrings,
}); });
let additional_text_elements = []; let additional_text_elements = [];
additional_text_elements.push({label: 'OpenAI Store', value: (prefs_api.chatgpt_api_store ? 'Yes' : 'No')}); additional_text_elements.push({label: 'OpenAI Store', value: (prefs_api.chatgpt_api_store ? 'Yes' : 'No')});
@ -140,7 +140,7 @@ switch (llm) {
google_gemini_system_instruction: prefs_api.google_gemini_system_instruction, google_gemini_system_instruction: prefs_api.google_gemini_system_instruction,
google_gemini_thinking_budget: prefs_api.google_gemini_thinking_budget, google_gemini_thinking_budget: prefs_api.google_gemini_thinking_budget,
do_debug: prefs_api.do_debug, do_debug: prefs_api.do_debug,
i18nStrings: i18nStrings i18nStrings: i18nStrings,
}); });
messagesArea.appendUserMessage(getAPIsInitMessageString({ messagesArea.appendUserMessage(getAPIsInitMessageString({
api_string: "Google Gemini API", api_string: "Google Gemini API",
@ -210,7 +210,7 @@ switch (llm) {
openai_comp_api_key: prefs_api.openai_comp_api_key, openai_comp_api_key: prefs_api.openai_comp_api_key,
openai_comp_use_v1: prefs_api.openai_comp_use_v1, openai_comp_use_v1: prefs_api.openai_comp_use_v1,
do_debug: prefs_api.do_debug, do_debug: prefs_api.do_debug,
i18nStrings: i18nStrings i18nStrings: i18nStrings,
}); });
let additional_text_elements = []; let additional_text_elements = [];
additional_text_elements.push({label: "Prompt", value: '[' + prompt_id + '] ' + decodeURIComponent(prompt_name)}); additional_text_elements.push({label: "Prompt", value: '[' + prompt_id + '] ' + decodeURIComponent(prompt_name)});
@ -246,7 +246,7 @@ switch (llm) {
anthropic_version: prefs_api.anthropic_version, anthropic_version: prefs_api.anthropic_version,
anthropic_max_tokens: prefs_api.anthropic_max_tokens, anthropic_max_tokens: prefs_api.anthropic_max_tokens,
do_debug: prefs_api.do_debug, do_debug: prefs_api.do_debug,
i18nStrings: i18nStrings i18nStrings: i18nStrings,
}); });
let additional_text_elements = []; let additional_text_elements = [];
additional_text_elements.push({label: "Prompt", value: '[' + prompt_id + '] ' + decodeURIComponent(prompt_name)}); additional_text_elements.push({label: "Prompt", value: '[' + prompt_id + '] ' + decodeURIComponent(prompt_name)});

View file

@ -20,7 +20,19 @@
import { getPrompts } from './mzta-prompts.js'; import { getPrompts } from './mzta-prompts.js';
import { prefs_default } from '../options/mzta-options-default.js'; import { prefs_default } from '../options/mzta-options-default.js';
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, extractJsonObject, convertNewlinesToBr, cleanupNewlines, checkIfTagLabelExists } from './mzta-utils.js' import {
getLanguageDisplayName,
getMenuContextCompose,
getMenuContextDisplay,
i18nConditionalGet,
getMailSubject,
getTagsList,
extractJsonObject,
convertNewlinesToBr,
cleanupNewlines,
checkIfTagLabelExists,
getConnectionType,
} from './mzta-utils.js'
import { taPromptUtils } from './mzta-utils-prompt.js'; import { taPromptUtils } from './mzta-utils-prompt.js';
import { taLogger } from './mzta-logger.js'; import { taLogger } from './mzta-logger.js';
import { placeholdersUtils } from './mzta-placeholders.js'; import { placeholdersUtils } from './mzta-placeholders.js';
@ -191,8 +203,9 @@ export class mzta_Menus {
default_chatgpt_lang: prefs_default.default_chatgpt_lang, default_chatgpt_lang: prefs_default.default_chatgpt_lang,
do_debug: prefs_default.do_debug, do_debug: prefs_default.do_debug,
}); });
if((prefs_at.connection_type === '')||(prefs_at.connection_type === null)||(prefs_at.connection_type === undefined)||(prefs_at.connection_type === 'chatgpt_web')){ let def_conntype = getConnectionType(prefs_at.connection_type, curr_prompt);
console.error("[ThunderAI | AddTags] Invalid connection type: " + prefs_at.connection_type); if((def_conntype === '')||(def_conntype === null)||(def_conntype === undefined)||(def_conntype === 'chatgpt_web')){
console.error("[ThunderAI | AddTags] Invalid connection type: " + def_conntype);
taWorkingStatus.stopWorking(); taWorkingStatus.stopWorking();
return {ok:'0'}; return {ok:'0'};
} }
@ -200,10 +213,17 @@ export class mzta_Menus {
this.logger.log("fullPrompt: " + fullPrompt); this.logger.log("fullPrompt: " + fullPrompt);
let create_new_tags = !prefs_at.add_tags_auto_force_existing; let create_new_tags = !prefs_at.add_tags_auto_force_existing;
let all_tags_list = tags_full_list[1]; let all_tags_list = tags_full_list[1];
// TODO: use the current API, abort if using chatgpt web
// COMMENTED TO DO TESTS // COMMENTED TO DO TESTS
// tags_current_email = "recipients, TEST, home, work, CAR, light"; // tags_current_email = "recipients, TEST, home, work, CAR, light";
let cmd_addTags = new mzta_specialCommand(fullPrompt,prefs_at.connection_type,prefs_at.do_debug); console.log(">>>>>>>>>>>>> curr_prompt: " + JSON.stringify(curr_prompt));
console.log(">>>>>>>>>>>>>> prefs_at.connection_type: " + JSON.stringify(prefs_at.connection_type));
console.log(">>>>>>>>>>>>>> def_conntype: " + JSON.stringify(def_conntype));
let cmd_addTags = new mzta_specialCommand({
prompt: fullPrompt,
llm: def_conntype,
custom_model: curr_prompt.model ? curr_prompt.model : '',
do_debug: prefs_at.do_debug
});
await cmd_addTags.initWorker(); await cmd_addTags.initWorker();
try{ try{
tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt()); tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt());
@ -255,7 +275,11 @@ export class mzta_Menus {
*/ */
fullPrompt = taPromptUtils.finalizePrompt_get_calendar_event(fullPrompt); fullPrompt = taPromptUtils.finalizePrompt_get_calendar_event(fullPrompt);
this.logger.log("fullPrompt: " + fullPrompt); this.logger.log("fullPrompt: " + fullPrompt);
let cmd_GetCalendarEvent = new mzta_specialCommand(fullPrompt,prefs_at.connection_type,true); let cmd_GetCalendarEvent = new mzta_specialCommand({
prompt: fullPrompt,
llm: prefs_at.connection_type,
do_debug: true
});
await cmd_GetCalendarEvent.initWorker(); await cmd_GetCalendarEvent.initWorker();
try{ try{
calendar_event_data = await cmd_GetCalendarEvent.sendPrompt(); calendar_event_data = await cmd_GetCalendarEvent.sendPrompt();
@ -323,7 +347,11 @@ export class mzta_Menus {
* } * }
*/ */
this.logger.log("fullPrompt: " + fullPrompt); this.logger.log("fullPrompt: " + fullPrompt);
let cmd_GetTask = new mzta_specialCommand(fullPrompt,prefs_at.connection_type,true); let cmd_GetTask = new mzta_specialCommand({
prompt: fullPrompt,
llm: prefs_at.connection_type,
do_debug: true
});
await cmd_GetTask.initWorker(); await cmd_GetTask.initWorker();
try{ try{
task_data = await cmd_GetTask.sendPrompt(); task_data = await cmd_GetTask.sendPrompt();

View file

@ -72,6 +72,12 @@
ChatGPT Web Custom GPT (chatgpt_web_custom_gpt attribute): ChatGPT Web Custom GPT (chatgpt_web_custom_gpt attribute):
<custom_gpt>: custom gpt id url <custom_gpt>: custom gpt id url
API Connection Type
<api_type>: api type
API Model
<api_model>: api model
*/ */
const defaultPrompts = [ const defaultPrompts = [
@ -89,6 +95,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -106,6 +114,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -123,6 +133,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -140,6 +152,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -157,6 +171,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -174,6 +190,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -191,6 +209,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -208,6 +228,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -225,6 +247,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -242,6 +266,8 @@ const defaultPrompts = [
chatgpt_web_model: '', chatgpt_web_model: '',
chatgpt_web_project: '', chatgpt_web_project: '',
chatgpt_web_custom_gpt: '', chatgpt_web_custom_gpt: '',
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "0", is_special: "0",
}, },
@ -259,6 +285,8 @@ const specialPrompts = [
need_custom_text: "0", need_custom_text: "0",
define_response_lang: "0", define_response_lang: "0",
use_diff_viewer: "0", use_diff_viewer: "0",
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "1", is_special: "1",
}, },
@ -273,6 +301,8 @@ const specialPrompts = [
need_custom_text: "0", need_custom_text: "0",
define_response_lang: "0", define_response_lang: "0",
use_diff_viewer: "0", use_diff_viewer: "0",
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "1", is_special: "1",
}, },
@ -287,6 +317,8 @@ const specialPrompts = [
need_custom_text: "0", need_custom_text: "0",
define_response_lang: "0", define_response_lang: "0",
use_diff_viewer: "0", use_diff_viewer: "0",
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "1", is_special: "1",
}, },
@ -301,24 +333,26 @@ const specialPrompts = [
need_custom_text: "0", need_custom_text: "0",
define_response_lang: "0", define_response_lang: "0",
use_diff_viewer: "0", use_diff_viewer: "0",
api_type: '',
api_model: '',
is_default: "1", is_default: "1",
is_special: "1", is_special: "1",
}, },
]; ];
export async function getPrompts(onlyEnabled = false, includeSpecial = []){ // includeSpecial is an array of active special prompts ids export async function getPrompts(onlyEnabled = false, includeSpecial = [], allSpecial = false){ // includeSpecial is an array of active special prompts ids
const _defaultPrompts = await getDefaultPrompts_withProps(); const _defaultPrompts = await getDefaultPrompts_withProps();
// console.log('>>>>>>>>>>>> getPrompts _defaultPrompts: ' + JSON.stringify(_defaultPrompts)); // console.log('>>>>>>>>>>>> getPrompts _defaultPrompts: ' + JSON.stringify(_defaultPrompts));
const customPrompts = await getCustomPrompts(); const customPrompts = await getCustomPrompts();
// console.log('>>>>>>>>>>>> getPrompts customPrompts: ' + JSON.stringify(customPrompts)); // console.log('>>>>>>>>>>>> getPrompts customPrompts: ' + JSON.stringify(customPrompts));
const specialPrompts = await getSpecialPrompts(); const specialPrompts = await getSpecialPrompts();
let output = specialPrompts.concat(_defaultPrompts).concat(customPrompts); let output = specialPrompts.concat(_defaultPrompts).concat(customPrompts);
if(includeSpecial.length == 0){ if((includeSpecial.length == 0) && !allSpecial){
output = output.filter(obj => obj.is_special != 1); // we do not want special prompts output = output.filter(obj => obj.is_special != 1); // we do not want special prompts
}else{ }else{
// console.log(">>>>>>>>>> getPrompts includeSpecial: " + JSON.stringify(includeSpecial)); // console.log(">>>>>>>>>> getPrompts includeSpecial: " + JSON.stringify(includeSpecial));
output = output.filter(obj => includeSpecial.includes(obj.id) || obj.is_special != 1); output = output.filter(obj => includeSpecial.includes(obj.id) || obj.is_special != 1 || allSpecial);
// output = output.filter(obj => { // output = output.filter(obj => {
// const isIncluded = includeSpecial.includes(obj.id); // const isIncluded = includeSpecial.includes(obj.id);
// const isNotSpecial = obj.is_special != 1; // const isNotSpecial = obj.is_special != 1;
@ -402,6 +436,11 @@ async function getDefaultPrompts_withProps() {
prompt.position_display = prefs._default_prompts_properties[prompt.id].position_display; prompt.position_display = prefs._default_prompts_properties[prompt.id].position_display;
prompt.enabled = prefs._default_prompts_properties[prompt.id].enabled; prompt.enabled = prefs._default_prompts_properties[prompt.id].enabled;
prompt.need_custom_text = prefs._default_prompts_properties[prompt.id].need_custom_text; prompt.need_custom_text = prefs._default_prompts_properties[prompt.id].need_custom_text;
prompt.chatgpt_web_model = prefs._default_prompts_properties[prompt.id].chatgpt_web_model;
prompt.chatgpt_web_project = prefs._default_prompts_properties[prompt.id].chatgpt_web_project;
prompt.chatgpt_web_custom_gpt = prefs._default_prompts_properties[prompt.id].chatgpt_web_custom_gpt;
prompt.api_type = prefs._default_prompts_properties[prompt.id].api_type;
prompt.api_model = prefs._default_prompts_properties[prompt.id].api_model;
}else{ }else{
prompt.position_display = pos; prompt.position_display = pos;
prompt.position_compose = pos; prompt.position_compose = pos;
@ -433,6 +472,12 @@ async function getCustomPrompts() {
if(prompt.chatgpt_web_custom_gpt === undefined){ if(prompt.chatgpt_web_custom_gpt === undefined){
prompt.chatgpt_web_custom_gpt = ""; prompt.chatgpt_web_custom_gpt = "";
} }
if(prompt.api_type === undefined){
prompt.api_type = "";
}
if(prompt.api_model === undefined){
prompt.api_model = "";
}
}); });
return prefs._custom_prompt; return prefs._custom_prompt;
} }
@ -441,7 +486,17 @@ async function getCustomPrompts() {
export async function setDefaultPromptsProperties(prompts) { export async function setDefaultPromptsProperties(prompts) {
let default_prompts_properties = {}; let default_prompts_properties = {};
prompts.forEach((prompt) => { prompts.forEach((prompt) => {
default_prompts_properties[prompt.id] = {position_compose: prompt.position_compose, position_display: prompt.position_display, enabled: prompt.enabled, need_custom_text: prompt.need_custom_text}; default_prompts_properties[prompt.id] = {
position_compose: prompt.position_compose,
position_display: prompt.position_display,
enabled: prompt.enabled,
need_custom_text: prompt.need_custom_text,
chatgpt_web_model: prompt.chatgpt_web_model,
chatgpt_web_project: prompt.chatgpt_web_project,
chatgpt_web_custom_gpt: prompt.chatgpt_web_custom_gpt,
api_type: prompt.api_type,
api_model: prompt.api_model
};
}); });
//console.log('>>>>>>>>>>>>>> default_prompts_properties: ' + JSON.stringify(default_prompts_properties)); //console.log('>>>>>>>>>>>>>> default_prompts_properties: ' + JSON.stringify(default_prompts_properties));
await browser.storage.local.set({_default_prompts_properties: default_prompts_properties}); await browser.storage.local.set({_default_prompts_properties: default_prompts_properties});
@ -486,4 +541,56 @@ export async function setSpecialPrompts(prompts) {
export async function getSpamFilterPrompt(){ export async function getSpamFilterPrompt(){
return (await getSpecialPrompts()).find(prompt => prompt.id == 'prompt_spamfilter'); return (await getSpecialPrompts()).find(prompt => prompt.id == 'prompt_spamfilter');
}
export async function loadPrompt(id) {
let allPrompts = await getPrompts(false,[],true);
// console.log(">>>>>>>>>>>> loadPrompt id: " + id + " - allPrompts: " + JSON.stringify(allPrompts));
return allPrompts.find(prompt => prompt.id === id);
}
export async function savePrompt(prompt) {
// console.log(">>>>>>>>>>>>> savePrompt prompt: " + JSON.stringify(prompt));
if (prompt.id === undefined) {
throw new Error("Invalid prompt: " + JSON.stringify(prompt));
}
// Special Prompt
if (prompt.is_special === "1") {
let specialPrompts = await getSpecialPrompts();
let index = specialPrompts.findIndex(p => p.id === prompt.id);
if (index === -1) {
specialPrompts.push(prompt);
} else {
specialPrompts[index] = prompt;
}
await setSpecialPrompts(specialPrompts);
return;
}
// Custom Prompt
if (prompt.is_default === "0") {
let customPrompts = await getCustomPrompts();
let index = customPrompts.findIndex(p => p.id === prompt.id);
if (index === -1) {
customPrompts.push(prompt);
} else {
customPrompts[index] = prompt;
}
await setCustomPrompts(customPrompts);
} else { // Default Prompt
let defaultPrompts = getDefaultPrompts_withProps();
let index = defaultPrompts.findIndex(p => p.id === prompt.id);
if (index === -1) {
defaultPrompts.push(prompt);
} else {
defaultPrompts[index] = prompt;
}
await setDefaultPromptsProperties(defaultPrompts);
}
}
export async function clearPromptAPI(id){
let _prompt = await loadPrompt(id);
_prompt.api = "";
_prompt.model = "";
await savePrompt(_prompt);
} }

View file

@ -17,7 +17,7 @@
*/ */
// Call the API to use a special prompt // Call the API to use a special prompt
import { prefs_default } from "../options/mzta-options-default.js";
import { taLogger } from './mzta-logger.js'; import { taLogger } from './mzta-logger.js';
import { prefs_default } from '../options/mzta-options-default.js'; import { prefs_default } from '../options/mzta-options-default.js';
@ -27,13 +27,21 @@
prompt = ""; prompt = "";
worker = null; worker = null;
llm = ""; llm = "";
custom_model = "";
full_message = ""; full_message = "";
logger = null; logger = null;
do_debug = false; do_debug = false;
constructor(prompt, llm, do_debug = false) { constructor(args = {}) {
let {
prompt = '',
llm = '',
custom_model = '',
do_debug = false
} = args;
this.prompt = prompt; this.prompt = prompt;
this.llm = llm; this.llm = llm;
this.custom_model = custom_model;
this.logger = new taLogger('mzta_specialCommand', do_debug); this.logger = new taLogger('mzta_specialCommand', do_debug);
this.do_debug = do_debug; this.do_debug = do_debug;
switch (this.llm) { switch (this.llm) {
@ -59,6 +67,7 @@
} }
async initWorker() { async initWorker() {
// console.log((">>>>>>>>>>>> this.custom_model: " + this.custom_model));
switch (this.llm) { switch (this.llm) {
case "chatgpt_api": { case "chatgpt_api": {
let prefs_api = await browser.storage.sync.get({ let prefs_api = await browser.storage.sync.get({
@ -69,7 +78,7 @@
this.worker.postMessage({ this.worker.postMessage({
type: 'init', type: 'init',
chatgpt_api_key: prefs_api.chatgpt_api_key, chatgpt_api_key: prefs_api.chatgpt_api_key,
chatgpt_model: prefs_api.chatgpt_model, chatgpt_model: this.custom_model != '' ? this.custom_model : prefs_api.chatgpt_model,
chatgpt_developer_messages: prefs_api.chatgpt_developer_messages, chatgpt_developer_messages: prefs_api.chatgpt_developer_messages,
do_debug: this.do_debug, do_debug: this.do_debug,
i18nStrings: '' i18nStrings: ''
@ -86,7 +95,7 @@
this.worker.postMessage({ this.worker.postMessage({
type: 'init', type: 'init',
google_gemini_api_key: prefs_api.google_gemini_api_key, google_gemini_api_key: prefs_api.google_gemini_api_key,
google_gemini_model: prefs_api.google_gemini_model, google_gemini_model: this.custom_model != '' ? this.custom_model : prefs_api.google_gemini_model,
google_gemini_system_instruction: prefs_api.google_gemini_system_instruction, google_gemini_system_instruction: prefs_api.google_gemini_system_instruction,
google_gemini_thinking_budget: prefs_api.google_gemini_thinking_budget, google_gemini_thinking_budget: prefs_api.google_gemini_thinking_budget,
do_debug: this.do_debug, do_debug: this.do_debug,
@ -102,7 +111,7 @@
this.worker.postMessage({ this.worker.postMessage({
type: 'init', type: 'init',
ollama_host: prefs_api.ollama_host, ollama_host: prefs_api.ollama_host,
ollama_model: prefs_api.ollama_model, ollama_model: this.custom_model != '' ? this.custom_model : prefs_api.ollama_model,
do_debug: this.do_debug, do_debug: this.do_debug,
i18nStrings: '' i18nStrings: ''
}); });
@ -120,7 +129,7 @@
this.worker.postMessage({ this.worker.postMessage({
type: 'init', type: 'init',
openai_comp_host: prefs_api.openai_comp_host, openai_comp_host: prefs_api.openai_comp_host,
openai_comp_model: prefs_api.openai_comp_model, openai_comp_model: this.custom_model != '' ? this.custom_model : prefs_api.openai_comp_model,
openai_comp_api_key: prefs_api.openai_comp_api_key, openai_comp_api_key: prefs_api.openai_comp_api_key,
openai_comp_use_v1: prefs_api.openai_comp_use_v1, openai_comp_use_v1: prefs_api.openai_comp_use_v1,
do_debug: this.do_debug, do_debug: this.do_debug,
@ -138,7 +147,7 @@
this.worker.postMessage({ this.worker.postMessage({
type: 'init', type: 'init',
anthropic_api_key: prefs_api.anthropic_api_key, anthropic_api_key: prefs_api.anthropic_api_key,
anthropic_model: prefs_api.anthropic_model, anthropic_model: this.custom_model != '' ? this.custom_model : prefs_api.anthropic_model,
anthropic_version: prefs_api.anthropic_version, anthropic_version: prefs_api.anthropic_version,
anthropic_max_tokens: prefs_api.anthropic_max_tokens, anthropic_max_tokens: prefs_api.anthropic_max_tokens,
do_debug: this.do_debug, do_debug: this.do_debug,

View file

@ -89,7 +89,7 @@ export const taPromptUtils = {
fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + default_chatgpt_lang + "."; fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + default_chatgpt_lang + ".";
} }
if(add_tags_auto_uselist && add_tags_auto_uselist_list && add_tags_auto_uselist_list.length > 0){ if(add_tags_auto_uselist && add_tags_auto_uselist_list && add_tags_auto_uselist_list.length > 0){
fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_use_list") + " " + add_tags_auto_uselist_list + "."; fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_use_list") + ": " + add_tags_auto_uselist_list + ".";
} }
return fullPrompt; return fullPrompt;

View file

@ -549,10 +549,21 @@ export function getAPIsInitMessageString(args = {}) {
} }
export function getActiveSpecialPromptsIDs(args = {}) { export function getActiveSpecialPromptsIDs(args = {}) {
const { addtags = false, get_calendar_event = false, get_task = false, is_chatgpt_web = false } = args; const {
addtags = false,
addtags_api = false,
get_calendar_event = false,
get_task = false,
is_chatgpt_web = false
} = args;
// The Antispam filter is not here, because this method is used only
// to reload the ThunderAI button menu, not the context menu
let output = []; let output = [];
// console.log(">>>>>>>>>> getActiveSpecialPromptsIDs args: " + JSON.stringify(args)); // console.log(">>>>>>>>>> getActiveSpecialPromptsIDs args: " + JSON.stringify(args));
if (is_chatgpt_web) { if (is_chatgpt_web) {
if (addtags_api && addtags) {
output.push('prompt_add_tags');
}
return output; return output;
} }
if (addtags) { if (addtags) {
@ -568,6 +579,10 @@ export function getActiveSpecialPromptsIDs(args = {}) {
return output; return output;
} }
export function checkSpecificIntegration(use, conntype){
return use && (conntype != null) && (conntype !== '');
}
export function extractJsonObject(inputString) { export function extractJsonObject(inputString) {
try { try {
const jsonMatch = inputString.match(/\{[\s\S]*\}/); const jsonMatch = inputString.match(/\{[\s\S]*\}/);
@ -587,6 +602,22 @@ export function extractJsonObject(inputString) {
} }
} }
export function isAPIKeyValue(id){
return id=="chatgpt_api_key" || id=="openai_comp_api_key" || id=="google_gemini_api_key" || id=="anthropic_api_key";
}
export function getConnectionType(conntype, prompt, use_promptspecific_api = true) {
if(!use_promptspecific_api) {
return conntype;
}
console.log(">>>>>>>>>>> getConnectionType conntype: " + conntype + " prompt: " + JSON.stringify(prompt));
if (prompt?.api != null && prompt.api !== '') {
return prompt.api;
} else {
return conntype;
}
}
export async function checkSparksPresence() { export async function checkSparksPresence() {
try { try {
let sparks_current = await browser.runtime.sendMessage('thunderai-sparks@micz.it',{action: "checkPresence"}); let sparks_current = await browser.runtime.sendMessage('thunderai-sparks@micz.it',{action: "checkPresence"});

View file

@ -36,6 +36,7 @@ let assistantResponseAccumulator = '';
self.onmessage = async function(event) { self.onmessage = async function(event) {
if (event.data.type === 'init') { if (event.data.type === 'init') {
// console.log(">>>>>>>>>>>>>> event.data: " + JSON.stringify(event.data));
anthropic_api_key = event.data.anthropic_api_key; anthropic_api_key = event.data.anthropic_api_key;
anthropic_model = event.data.anthropic_model; anthropic_model = event.data.anthropic_model;
anthropic = new Anthropic({ anthropic = new Anthropic({

View file

@ -20,7 +20,35 @@ import { mzta_script } from './js/mzta-chatgpt.js';
import { prefs_default } from './options/mzta-options-default.js'; import { prefs_default } from './options/mzta-options-default.js';
import { mzta_Menus } from './js/mzta-menus.js'; import { mzta_Menus } from './js/mzta-menus.js';
import { taLogger } from './js/mzta-logger.js'; import { taLogger } from './js/mzta-logger.js';
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagLabelExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, stripHtmlKeepLines, htmlBodyToPlainText, convertNewlinesToParagraphs } from './js/mzta-utils.js'; import {
getCurrentIdentity,
getOriginalBody,
replaceBody,
setBody,
i18nConditionalGet,
generateCallID,
migrateCustomPromptsStorage,
migrateDefaultPromptsPropStorage,
getGPTWebModelString,
getTagsList,
createTag,
assignTagsToMessage,
checkIfTagLabelExists,
getActiveSpecialPromptsIDs,
checkSparksPresence,
getMessages,
getMailBody,
extractJsonObject,
contextMenuID_AddTags,
contextMenuID_Spamfilter,
sanitizeChatGPTModelData,
sanitizeChatGPTWebCustomData,
stripHtmlKeepLines,
htmlBodyToPlainText,
convertNewlinesToParagraphs,
getConnectionType,
checkSpecificIntegration,
} from './js/mzta-utils.js';
import { taPromptUtils } from './js/mzta-utils-prompt.js'; import { taPromptUtils } from './js/mzta-utils-prompt.js';
import { mzta_specialCommand } from './js/mzta-special-commands.js'; import { mzta_specialCommand } from './js/mzta-special-commands.js';
import { getSpamFilterPrompt } from './js/mzta-prompts.js'; import { getSpamFilterPrompt } from './js/mzta-prompts.js';
@ -56,6 +84,7 @@ taWorkingStatus.taLog = taLog;
let special_prompts_ids = getActiveSpecialPromptsIDs({ let special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags, addtags: prefs_init.add_tags,
addtags_api: checkSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: doGetSparkFeature(prefs_init.get_calendar_event), get_calendar_event: doGetSparkFeature(prefs_init.get_calendar_event),
get_task: doGetSparkFeature(prefs_init.get_task), get_task: doGetSparkFeature(prefs_init.get_task),
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web") is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
@ -146,6 +175,7 @@ async function _reload_menus() {
let getTask = doGetSparkFeature(prefs_reload.get_task); let getTask = doGetSparkFeature(prefs_reload.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({ const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_reload.add_tags, addtags: prefs_reload.add_tags,
addtags_api: checkSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent, get_calendar_event: getCalendarEvent,
get_task: getTask, get_task: getTask,
is_chatgpt_web: (prefs_reload.connection_type === "chatgpt_web") is_chatgpt_web: (prefs_reload.connection_type === "chatgpt_web")
@ -749,7 +779,25 @@ function doGetSparkFeature(spark_feature_active) {
} }
async function reload_pref_init(){ async function reload_pref_init(){
prefs_init = await browser.storage.sync.get({do_debug: prefs_default.do_debug, add_tags: prefs_default.add_tags, get_calendar_event: prefs_default.get_calendar_event, get_task: prefs_default.get_task, connection_type: prefs_default.connection_type, add_tags_auto: prefs_default.add_tags_auto, add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing, add_tags_auto_only_inbox: prefs_default.add_tags_auto_only_inbox, spamfilter: prefs_default.spamfilter, spamfilter_threshold: prefs_default.spamfilter_threshold, dynamic_menu_force_enter: prefs_default.dynamic_menu_force_enter, add_tags_context_menu: prefs_default.add_tags_context_menu, spamfilter_context_menu: prefs_default.spamfilter_context_menu}); prefs_init = await browser.storage.sync.get({
do_debug: prefs_default.do_debug,
add_tags: prefs_default.add_tags,
get_calendar_event: prefs_default.get_calendar_event,
get_task: prefs_default.get_task,
connection_type: prefs_default.connection_type,
add_tags_auto: prefs_default.add_tags_auto,
add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing,
add_tags_auto_only_inbox: prefs_default.add_tags_auto_only_inbox,
spamfilter: prefs_default.spamfilter,
spamfilter_threshold: prefs_default.spamfilter_threshold,
dynamic_menu_force_enter: prefs_default.dynamic_menu_force_enter,
add_tags_context_menu: prefs_default.add_tags_context_menu,
spamfilter_context_menu: prefs_default.spamfilter_context_menu,
add_tags_use_specific_integration: prefs_default.add_tags_use_specific_integration,
add_tags_connection_type: prefs_default.add_tags_connection_type,
spamfilter_use_specific_integration: prefs_default.spamfilter_use_specific_integration,
spamfilter_connection_type: prefs_default.spamfilter_connection_type
});
_process_incoming = prefs_init.add_tags_auto || prefs_init.spamfilter; _process_incoming = prefs_init.add_tags_auto || prefs_init.spamfilter;
_sparks_presence = await checkSparksPresence(); _sparks_presence = await checkSparksPresence();
} }
@ -767,6 +815,7 @@ function setupStorageChangeListener() {
let getTask = doGetSparkFeature(prefs_init.get_task); let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({ const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: newTags, addtags: newTags,
addtags_api: checkSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent, get_calendar_event: getCalendarEvent,
get_task: getTask, get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web") is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
@ -781,6 +830,7 @@ function setupStorageChangeListener() {
let getTask = doGetSparkFeature(prefs_init.get_task); let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({ const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags, addtags: prefs_init.add_tags,
addtags_api: checkSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent, get_calendar_event: getCalendarEvent,
get_task: getTask, get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web") is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
@ -795,6 +845,7 @@ function setupStorageChangeListener() {
let getTask = doGetSparkFeature(newTask); let getTask = doGetSparkFeature(newTask);
const special_prompts_ids = getActiveSpecialPromptsIDs({ const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags, addtags: prefs_init.add_tags,
addtags_api: checkSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent, get_calendar_event: getCalendarEvent,
get_task: getTask, get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web") is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
@ -809,6 +860,7 @@ function setupStorageChangeListener() {
let getTask = doGetSparkFeature(prefs_init.get_task); let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({ const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags, addtags: prefs_init.add_tags,
addtags_api: checkSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent, get_calendar_event: getCalendarEvent,
get_task: getTask, get_task: getTask,
is_chatgpt_web: (newConnectionType === "chatgpt_web") is_chatgpt_web: (newConnectionType === "chatgpt_web")
@ -895,6 +947,7 @@ menus.loadMenus(special_prompts_ids);
// Context Menus // Context Menus
function addContextMenu(menu_id) { function addContextMenu(menu_id) {
browser.menus.remove(menu_id);
browser.menus.create({ browser.menus.create({
id: menu_id, id: menu_id,
title: browser.i18n.getMessage("context_menu_" + menu_id), title: browser.i18n.getMessage("context_menu_" + menu_id),
@ -909,12 +962,12 @@ function removeContextMenu(menu_id) {
} }
// Add Context menu: Add tags // Add Context menu: Add tags
if(prefs_init.add_tags && prefs_init.add_tags_context_menu && (prefs_init.connection_type !== "chatgpt_web")){ if(prefs_init.add_tags && prefs_init.add_tags_context_menu && ((prefs_init.connection_type !== "chatgpt_web")||checkSpecificIntegration(prefs_init.add_tags_use_specific_integration,prefs_init.add_tags_connection_type))){
addContextMenu(contextMenuID_AddTags); addContextMenu(contextMenuID_AddTags);
} }
// Add Context menu: Spamfilter // Add Context menu: Spamfilter
if(prefs_init.spamfilter && prefs_init.spamfilter_context_menu && (prefs_init.connection_type !== "chatgpt_web")){ if(prefs_init.spamfilter && prefs_init.spamfilter_context_menu && ((prefs_init.connection_type !== "chatgpt_web")||checkSpecificIntegration(prefs_init.spamfilter_use_specific_integration,prefs_init.spamfilter_connection_type))){
addContextMenu(contextMenuID_Spamfilter); addContextMenu(contextMenuID_Spamfilter);
} }
@ -976,6 +1029,9 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
add_tags_auto_uselist: prefs_default.add_tags_auto_uselist, add_tags_auto_uselist: prefs_default.add_tags_auto_uselist,
add_tags_auto_uselist_list: prefs_default.add_tags_auto_uselist_list, add_tags_auto_uselist_list: prefs_default.add_tags_auto_uselist_list,
spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts, spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts,
add_tags_use_specific_integration: prefs_default.add_tags_use_specific_integration,
spamfilter_use_specific_integration: prefs_default.spamfilter_use_specific_integration,
do_debug: prefs_default.do_debug,
}); });
for await (let message of messages) { for await (let message of messages) {
@ -1005,7 +1061,7 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
let specialFullPrompt_add_tags = ''; let specialFullPrompt_add_tags = '';
let curr_prompt_add_tags = menus.allPrompts.find(p => p.id === 'prompt_add_tags'); let curr_prompt_add_tags = menus.allPrompts.find(p => p.id === 'prompt_add_tags');
let tags_full_list = await getTagsList(); let tags_full_list = await getTagsList();
// console.log(">>>>>>>>>>>>> curr_prompt_add_tags: " + curr_prompt_add_tags); // console.log(">>>>>>>>>>>>> curr_prompt_add_tags: " + JSON.stringify(curr_prompt_add_tags));
let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_add_tags); let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_add_tags);
specialFullPrompt_add_tags = await taPromptUtils.preparePrompt({ specialFullPrompt_add_tags = await taPromptUtils.preparePrompt({
curr_prompt: curr_prompt_add_tags, curr_prompt: curr_prompt_add_tags,
@ -1018,7 +1074,13 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
}); });
specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang, prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang, prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list);
taLog.log("Special prompt: " + specialFullPrompt_add_tags); taLog.log("Special prompt: " + specialFullPrompt_add_tags);
let cmd_addTags = new mzta_specialCommand(specialFullPrompt_add_tags, prefs_aats.connection_type, prefs_init.do_debug); // console.log(">>>>>>>>>> curr_prompt_add_tags.model: " + curr_prompt_add_tags.model);
let cmd_addTags = new mzta_specialCommand({
prompt: specialFullPrompt_add_tags,
llm: getConnectionType(prefs_aats.connection_type, curr_prompt_add_tags, prefs_aats.add_tags_use_specific_integration),
custom_model: curr_prompt_add_tags.model ? curr_prompt_add_tags.model : '',
do_debug: prefs_aats.do_debug
});
await cmd_addTags.initWorker(); await cmd_addTags.initWorker();
let tags_current_email = []; let tags_current_email = [];
try { try {
@ -1052,7 +1114,12 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
}); });
taLog.log("Special prompt: " + specialFullPrompt_spamfilter); taLog.log("Special prompt: " + specialFullPrompt_spamfilter);
// console.log(">>>>>>>> Special prompt for spamfilter: " + specialFullPrompt_spamfilter); // console.log(">>>>>>>> Special prompt for spamfilter: " + specialFullPrompt_spamfilter);
let cmd_spamfilter = new mzta_specialCommand(specialFullPrompt_spamfilter, prefs_init.connection_type, prefs_init.do_debug); let cmd_spamfilter = new mzta_specialCommand({
prompt: specialFullPrompt_spamfilter,
llm: getConnectionType(prefs_aats.connection_type, curr_prompt_spamfilter, prefs_aats.spamfilter_use_specific_integration),
custom_model: curr_prompt_spamfilter.model ? curr_prompt_spamfilter.model : '',
do_debug: prefs_aats.do_debug
});
await cmd_spamfilter.initWorker(); await cmd_spamfilter.initWorker();
let spamfilter_result = ''; let spamfilter_result = '';
taLog.log("Sending the prompt..."); taLog.log("Sending the prompt...");

View file

@ -67,6 +67,13 @@ export const prefs_default = {
add_tags_auto_uselist_list: '', add_tags_auto_uselist_list: '',
add_tags_context_menu: true, add_tags_context_menu: true,
add_tags_enabled_accounts: [], add_tags_enabled_accounts: [],
add_tags_use_specific_integration: false,
add_tags_connection_type: 'chatgpt_api',
add_tags_chatgpt_model: '',
add_tags_ollama_model: '',
add_tags_openai_comp_model: '',
add_tags_google_gemini_model: '',
add_tags_anthropic_model: '',
get_calendar_event: true, get_calendar_event: true,
get_task: true, get_task: true,
calendar_enforce_timezone: false, calendar_enforce_timezone: false,
@ -75,4 +82,11 @@ export const prefs_default = {
spamfilter_threshold: 70, spamfilter_threshold: 70,
spamfilter_context_menu: true, spamfilter_context_menu: true,
spamfilter_enabled_accounts: [], spamfilter_enabled_accounts: [],
} spamfilter_use_specific_integration: false,
spamfilter_connection_type: 'chatgpt_api',
spamfilter_chatgpt_model: '',
spamfilter_ollama_model: '',
spamfilter_openai_comp_model: '',
spamfilter_google_gemini_model: '',
spamfilter_anthropic_model: '',
}

View file

@ -82,10 +82,6 @@ span.dims_label{
display: inline-block; display: inline-block;
} }
span.opt_title{
font-weight: bold;
}
#btn_custom_prompts{ #btn_custom_prompts{
text-align: center; text-align: center;
width: 100%; width: 100%;
@ -104,38 +100,9 @@ div#miczTranslate{
font-size:smaller; font-size:smaller;
} }
tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{ .warn_API_needed{
background-color: rgb(185, 220, 252);
}
tr.conntype_chatgpt_web, tr.conntype_chatgpt_web2{
background-color: rgb(255, 209, 183);
}
tr.conntype_ollama_api, tr.conntype_ollama_api2{
background-color: rgb(177, 238, 169);
}
tr.conntype_openai_comp_api, tr.conntype_openai_comp_api2{
background-color: rgb(213, 169, 238);
}
tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{
background-color: rgb(233, 238, 169);
}
tr.conntype_anthropic_api, tr.conntype_anthropic_api2{
background-color: rgb(255, 168, 204);
}
#chatgpt_model_fetch_loading{
display: none; display: none;
font-style: italic; font-weight: bold;
}
#google_gemini_model_fetch_loading{
display: none;
font-style: italic;
} }
#no_sparks td{ #no_sparks td{
@ -144,53 +111,6 @@ tr.conntype_anthropic_api, tr.conntype_anthropic_api2{
background: #bbf7f1; background: #bbf7f1;
} }
textarea.option-textarea{
width: -moz-available;
height: 10em;
}
.api_key-container {
position: relative;
width: 100%;
}
.api_key-container input {
width: -moz-available;
margin-right: 25px;
}
input[type="text"], input[type="password"]{
border-radius: 4px;
padding: 2px;
}
input.option-input[type="text"]{
width: -moz-available;
}
.api_key-container .toggle-icon {
position: absolute;
right: 0px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
}
#ollama_model_fetch_loading{
display: none;
font-style: italic;
}
#openai_comp_model_fetch_loading{
display: none;
font-style: italic;
}
#anthropic_model_fetch_loading{
display: none;
font-style: italic;
}
#owl_warning{ #owl_warning{
display: none; display: none;
} }
@ -235,10 +155,6 @@ input.option-input[type="text"]{
color: #FF6600; color: #FF6600;
} }
.conntype_chatgpt_web_option{
cursor: pointer;
}
.btn_small{ .btn_small{
font-size: 0.8em; font-size: 0.8em;
} }

View file

@ -3,6 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="stylesheet" href="mzta-options.css"> <link rel="stylesheet" href="mzta-options.css">
<link rel="stylesheet" href="../pages/_lib/connection-ui.css">
</head> </head>
<body> <body>
<div id="miczRelNotes"><a href="mzta-release-notes.html">__MSG_prefs_OptionText_release_notes__</a></div> <div id="miczRelNotes"><a href="mzta-release-notes.html">__MSG_prefs_OptionText_release_notes__</a></div>
@ -113,375 +114,7 @@
</label> </label>
</td> </td>
</tr> </tr>
<tr> <tr id="connection_ui_anchor"></tr>
<td>
<label>
<span class="opt_title">__MSG_prefs_Connection_type__</span>
</label>
</td>
<td>
<label>
<select id="connection_type" name="connection_type" class="option-input">
<option value="chatgpt_web">__MSG_prefs_Connection_type_ChatGPT_Web__</option>
<option value="chatgpt_api">__MSG_prefs_Connection_type_ChatGPT_API__</option>
<option value="google_gemini_api">__MSG_prefs_Connection_type_Google_Gemini_API__</option>
<option value="anthropic_api">__MSG_prefs_Connection_type_Anthropic_API__</option>
<option value="ollama_api">__MSG_prefs_Connection_type_Ollama_API__</option>
<option value="openai_comp_api">__MSG_prefs_Connection_type_OpenAI_Comp_API__</option>
</select>
</label>
</td>
</tr>
<tr>
<tr class="conntype_chatgpt_web">
<td><label>
<span class="opt_title">__MSG_apiwebchat_info__</span>
</label></td>
<td>
<label>
__MSG_prefs_OptionText_chatgpt_web_br_replace_info__
</label>
</td>
</tr>
<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 id="chatgpt_web_models_list"></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 class="opt_title">__MSG_prefs_OptionText_chatgpt_web_project__</span>
<br><i class="small_info" id="chatgpt_web_project_info">__MSG_prefs_OptionText_chatgpt_web_custom_data_info__ <b class="lightbold">/g/PROJECT-ID-PROJECT-NAME/project</b>
<br>__MSG_prefs_OptionText_chatgpt_web_custom_data_info2__</i>
</label></td>
<td>
<label>
<input type="text" id="chatgpt_web_project" name="chatgpt_web_project" class="option-input" />
<br>__MSG_prefs_OptionText_chatgpt_web_project_info__
</label>
</td>
</tr>
<tr class="conntype_chatgpt_web">
<td><label>
<span class="opt_title">__MSG_prefs_OptionText_chatgpt_web_custom_gpt__</span>
<br><i class="small_info" id="chatgpt_web_custom_gpt_info">__MSG_prefs_OptionText_chatgpt_web_custom_data_info__ <b class="lightbold">/g/CUSTOM-GPT-ID</b>
<br>__MSG_prefs_OptionText_chatgpt_web_custom_data_info2__</i>
</label></td>
<td>
<label>
<input type="text" id="chatgpt_web_custom_gpt" name="chatgpt_web_custom_gpt" class="option-input" />
<br>__MSG_prefs_OptionText_chatgpt_web_custom_gpt_info__
<br>__MSG_prefs_OptionText_CustomGPT_Warn__
</label>
</td>
</tr>
<tr class="conntype_chatgpt_web">
<td><label>
<span class="opt_title">__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" />
&nbsp;<span>__MSG_prefs_OptionText_chatgpt_web_tempchat_info__
<br>__MSG_prefs_OptionText_Project_No_temporary_chat_warn__
</span>
</label>
</td>
</tr>
<tr class="conntype_chatgpt_web">
<td colspan="2" style="padding:0px 2em;text-align:center;"><span>__MSG_OpenChatGPTTab_Info__</span>
<br><br><button id="btnChatGPTWeb_Tab">__MSG_OpenChatGPTTab__</button>
<br><br>__MSG_OpenChatGPTTab_Info2__
</td>
</tr>
<tr class="conntype_chatgpt_api">
<td><label>
<span class="opt_title">__MSG_prefs_ChatGPT_API_Key__</span>
</label></td>
<td>
<div class="api_key-container">
<label>
<input type="password" id="chatgpt_api_key" name="chatgpt_api_key" class="option-input"/>
</label>
<span class="toggle-icon" id="toggle_chatgpt_api_key"><img src="../images/pwd-show.png" id="pwd-icon_chatgpt_api_key"></span>
</div>
</td>
</tr>
<tr class="conntype_chatgpt_api">
<td>
<label>
<span class="opt_title">__MSG_ChatGPT_Models__</span>
</label>
</td>
<td>
<button id="btnUpdateChatGPTModels">__MSG_ChatGPT_Models_Fetch__</button> <span id="chatgpt_model_fetch_loading">__MSG_Loading__</span><br>
<label>
<select id="chatgpt_model" name="chatgpt_model" class="option-input">
</select>
</label>
</td>
</tr>
<tr class="conntype_chatgpt_api">
<td>
<label>
<span class="opt_title">__MSG_ChatGPT_chatgpt_api_store__</span>
</label>
</td>
<td>
<label>
<input type="checkbox" id="chatgpt_api_store" name="chatgpt_api_store" class="option-input" />
&nbsp;<span>__MSG_ChatGPT_chatgpt_api_store_info__</span>
</label>
</td>
</tr>
<tr class="conntype_chatgpt_api">
<td>
<label>
<span class="opt_title">__MSG_ChatGPT_Developer_Messages__</span>
</label>
</td>
<td>
<label>
<textarea id="chatgpt_developer_messages" name="chatgpt_developer_messages" class="option-input option-textarea"></textarea>
<br>__MSG_ChatGPT_Developer_Messages_Info__
</label>
</td>
</tr>
<tr class="conntype_google_gemini_api">
<td><label>
<span class="opt_title">__MSG_prefs_GoogleGemini_API_Key__</span>
</label></td>
<td>
<div class="api_key-container">
<label>
<input type="password" id="google_gemini_api_key" name="google_gemini_api_key" class="option-input"/>
</label>
<span class="toggle-icon" id="toggle_google_gemini_api_key"><img src="../images/pwd-show.png" id="pwd-icon_google_gemini_api_key"></span>
</div>
</td>
</tr>
<tr class="conntype_google_gemini_api">
<td>
<label>
<span class="opt_title">__MSG_GoogleGemini_Models__</span>
</label>
</td>
<td>
<button id="btnUpdateGoogleGeminiModels">__MSG_GoogleGemini_Models_Fetch__</button> <span id="google_gemini_model_fetch_loading">__MSG_Loading__</span><br>
<label>
<select id="google_gemini_model" name="google_gemini_model" class="option-input">
</select>
</label>
</td>
</tr>
<tr class="conntype_google_gemini_api">
<td>
<label>
<span class="opt_title">__MSG_GoogleGemini_SystemInstruction__</span>
</label>
</td>
<td>
<label>
<textarea id="google_gemini_system_instruction" name="google_gemini_system_instruction" class="option-input option-textarea"></textarea>
<br>__MSG_GoogleGemini_SystemInstruction_Info__
</label>
</td>
</tr>
<tr class="conntype_ollama_api">
<td><label>
<span class="opt_title">__MSG_prefs_API_Host__</span>
<br><i class="small_info">__MSG_prefs_API_Host_Info__ http://127.0.0.1:11434</i>
</label></td>
<td>
<label>
<input type="text" id="ollama_host" name="ollama_host" class="option-input"/>
</label>
</td>
</tr>
<tr class="conntype_ollama_api" id="ollama_api_cors_warning">
<td colspan="2" style="text-align:center;">
__MSG_remember_CORS__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_more_info_string__</a>]
<br><br><b>__MSG_CORS_alternative_1__</b>
<br>__MSG_CORS_alternative_2__
<br><br><button id="btnGiveAllUrlsPermission_ollama_api">__MSG_CORS_give_allurls_perm__</button>
</td>
</tr>
<tr class="conntype_ollama_api">
<td>
<label>
<span class="opt_title">__MSG_Ollama_Models__</span>
</label>
</td>
<td>
<button id="btnUpdateOllamaModels">__MSG_Ollama_Models_Fetch__</button> <span id="ollama_model_fetch_loading">__MSG_Loading__</span><br>
<label>
<select id="ollama_model" name="ollama_model" class="option-input">
</select>
</label>
</td>
</tr>
<tr class="conntype_ollama_api">
<td><label>
<span class="opt_title">__MSG_prefs_ollama_think__</span>
</label></td>
<td>
<label>
<input type="checkbox" id="ollama_think" name="ollama_think" class="option-input"/>
__MSG_prefs_ollama_think_Info__
</label>
</td>
</tr>
<tr class="conntype_ollama_api">
<td><label>
<span class="opt_title">__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_openai_comp_api">
<td><label>
<span class="opt_title">__MSG_prefs_OpenAIComp_AvailableServices__</span>
</label></td>
<td>
<label>
<select id="openai_comp_services_shortcut">
</select>
<br>__MSG_prefs_OpenAIComp_AvailableServices_Info__
</label>
</td>
</tr>
<tr class="conntype_openai_comp_api">
<td><label>
<span class="opt_title">__MSG_prefs_API_Host__</span>
<br><i class="small_info">__MSG_prefs_API_Host_Info__ http://localhost:1234</i>
</label></td>
<td>
<label>
<input type="text" id="openai_comp_host" name="openai_comp_host" class="option-input" />
<br>__MSG_prefs_OptionText_openai_comp_info_remote__
</label>
</td>
</tr>
<tr class="conntype_openai_comp_api" id="openai_comp_api_cors_warning">
<td colspan="2" style="text-align:center;">
__MSG_maybe_CORS_openai_comp__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_more_info_string__</a>]
<br><br><b>__MSG_CORS_alternative_1__</b>
<br>__MSG_CORS_alternative_2__
<br><br><button id="btnGiveAllUrlsPermission_openai_comp_api">__MSG_CORS_give_allurls_perm__</button>
</td>
</tr>
<tr class="conntype_openai_comp_api">
<td><label>
<span class="opt_title">__MSG_prefs_OptionText_openai_comp_use_v1__</span>
</label></td>
<td>
<label>
<input type="checkbox" id="openai_comp_use_v1" name="openai_comp_use_v1" class="option-input" />
&nbsp;<span>__MSG_prefs_OptionText_openai_comp_use_v1_info__</span>
</label>
</td>
</tr>
<tr class="conntype_openai_comp_api">
<td><label>
<span class="opt_title">__MSG_prefs_OpenAIComp_API_Key__</span>
<br><i class="small_info">__MSG_Optional__</i>
</label></td>
<td>
<div class="api_key-container">
<label>
<input type="password" id="openai_comp_api_key" name="openai_comp_api_key" class="option-input"/>
</label>
<span class="toggle-icon" id="toggle_openai_comp_api_key"><img src="../images/pwd-show.png" id="pwd-icon_openai_comp_api_key"></span>
</div>
</td>
</tr>
<tr class="conntype_openai_comp_api">
<td>
<label>
<span class="opt_title">__MSG_OpenAIComp_Models__</span>
<br><button id="btnOpenAICompForceModel" class="btn_small">__MSG_prefs_OpenAIComp_ForceModel__</button>
<br><button id="btnOpenAICompClearModelsList" class="btn_small">__MSG_prefs_OpenAIComp_ClearModelsList__</button></td>
</label>
</td>
<td>
<button id="btnUpdateOpenAICompModels">__MSG_OpenAIComp_Models_Fetch__</button> <span id="openai_comp_model_fetch_loading">__MSG_Loading__</span><br>
<label>
<select id="openai_comp_model" name="openai_comp_model" class="option-input">
</select>
</label>
</td>
</tr>
<tr class="conntype_openai_comp_api">
<td><label>
<span class="opt_title">__MSG_prefs_OpenAIComp_ChatName__</span>
</label></td>
<td>
<label>
<input type="text" id="openai_comp_chat_name" name="openai_comp_chat_name" class="option-input" />
<br>__MSG_prefs_OpenAIComp_ChatName_Info__
</label>
</td>
</tr>
<tr class="conntype_anthropic_api">
<td><label>
<span class="opt_title">__MSG_prefs_Anthropic_API_Key__</span>
</label></td>
<td>
<div class="api_key-container">
<label>
<input type="password" id="anthropic_api_key" name="anthropic_api_key" class="option-input"/>
</label>
<span class="toggle-icon" id="toggle_anthropic_api_key"><img src="../images/pwd-show.png" id="pwd-icon_anthropic_api_key"></span>
</div>
</td>
</tr>
<tr class="conntype_anthropic_api">
<td>
<label>
<span class="opt_title">__MSG_Anthropic_Models__</span>
</label>
</td>
<td>
<button id="btnUpdateAnthropicModels">__MSG_Anthropic_Models_Fetch__</button> <span id="anthropic_model_fetch_loading">__MSG_Loading__</span><br>
<label>
<select id="anthropic_model" name="anthropic_model" class="option-input">
</select>
</label>
</td>
</tr>
<tr class="conntype_anthropic_api">
<td>
<label>
<span class="opt_title">__MSG_Anthropic_Version__</span>
</label>
</td>
<td>
<label>
<input type="text" id="anthropic_version" name="anthropic_version" class="option-input" />
<br>__MSG_Anthropic_Version_Info__ <a href="https://docs.anthropic.com/en/api/versioning">https://docs.anthropic.com/en/api/versioning</a>
</label>
</td>
</tr>
<tr class="conntype_anthropic_api">
<td><span class="opt_title">__MSG_prefs_OptionText_anthropic_max_tokens__</span></td>
<td>
<label>
<input type="number" id="anthropic_max_tokens" name="anthropic_max_tokens" class="option-input" />
<br>__MSG_prefs_OptionText_anthropic_max_tokens_Info__
</label>
</td>
</tr>
<tr id="max_prompt_length_tr"> <tr id="max_prompt_length_tr">
<td><span class="opt_title">__MSG_prefs_OptionText_max_prompt_length__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_max_prompt_length__</span></td>
<td> <td>
@ -499,6 +132,7 @@
<label> <label>
<input type="checkbox" id="add_tags" name="add_tags" class="option-input" /> <input type="checkbox" id="add_tags" name="add_tags" class="option-input" />
__MSG_prefs_OptionText_add_tags_Info__ __MSG_prefs_OptionText_add_tags_Info__
<br><span class="warn_API_needed" id="add_tags_warn_API_needed">__MSG_warn_API_needed__</span>
</label> </label>
</td> </td>
</tr> </tr>
@ -509,6 +143,7 @@
<label> <label>
<input type="checkbox" id="spamfilter" name="spamfilter" class="option-input" /> <input type="checkbox" id="spamfilter" name="spamfilter" class="option-input" />
__MSG_prefs_OptionText_spamfilter_Info__ __MSG_prefs_OptionText_spamfilter_Info__
<br><span class="warn_API_needed" id="spamfilter_warn_API_needed">__MSG_warn_API_needed__</span>
</label> </label>
</td> </td>
</tr> </tr>

View file

@ -18,17 +18,24 @@
import { prefs_default } from './mzta-options-default.js'; import { prefs_default } from './mzta-options-default.js';
import { taLogger } from '../js/mzta-logger.js'; import { taLogger } from '../js/mzta-logger.js';
import { OpenAI } from '../js/api/openai.js'; import {
import { Ollama } from '../js/api/ollama.js'; ChatGPTWeb_models,
import { OpenAIComp } from '../js/api/openai_comp.js' checkSparksPresence,
import { GoogleGemini } from '../js/api/google_gemini.js'; isThunderbird128OrGreater,
import { Anthropic } from '../js/api/anthropic.js'; openTab,
import { ChatGPTWeb_models, checkSparksPresence, isThunderbird128OrGreater, openTab, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML } from '../js/mzta-utils.js'; getChatGPTWebModelsList_HTML,
import { openAICompConfigs } from '../js/api/openai_comp_configs.js'; isAPIKeyValue,
getConnectionType,
} from '../js/mzta-utils.js';
import {
injectConnectionUI,
varConnectionUI,
showConnectionOptions,
updateWarnings
} from '../pages/_lib/connection-ui.js';
let taLog = new taLogger("mzta-options",true); let taLog = new taLogger("mzta-options",true);
let _isThunderbird128OrGreater = true; let _isThunderbird128OrGreater = true;
let permission_all_urls = false;
function saveOptions(e) { function saveOptions(e) {
e.preventDefault(); e.preventDefault();
@ -70,7 +77,7 @@ function saveOptions(e) {
async function restoreOptions() { async function restoreOptions() {
function setCurrentChoice(result) { function setCurrentChoice(result) {
document.querySelectorAll(".option-input").forEach(element => { document.querySelectorAll(".option-input").forEach(element => {
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" || element.id=="google_gemini_api_key" || element.id=="anthropic_api_key" ? "****************" : result[element.id])); taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
switch (element.type) { switch (element.type) {
case 'checkbox': case 'checkbox':
element.checked = result[element.id] || false; element.checked = result[element.id] || false;
@ -109,211 +116,6 @@ async function restoreOptions() {
setCurrentChoice(getting); setCurrentChoice(getting);
} }
function showConnectionOptions() {
disable_MaxPromptLength();
disable_AddTags();
disable_SpamFilter();
disable_GetCalendarEvent();
let chatgpt_web_display = 'table-row';
let chatgpt_api_display = 'none';
let ollama_api_display = 'none';
let openai_comp_api_display = 'none';
let google_gemini_api_display = 'none';
let anthropic_api_display = 'none';
let conntype_select = document.getElementById("connection_type");
let parent = conntype_select.parentElement.parentElement.parentElement;
parent.classList.toggle("conntype_chatgpt_web", (conntype_select.value === "chatgpt_web"));
parent.classList.toggle("conntype_chatgpt_api", (conntype_select.value === "chatgpt_api"));
parent.classList.toggle("conntype_ollama_api", (conntype_select.value === "ollama_api"));
parent.classList.toggle("conntype_openai_comp_api", (conntype_select.value === "openai_comp_api"));
parent.classList.toggle("conntype_google_gemini_api", (conntype_select.value === "google_gemini_api"));
parent.classList.toggle("conntype_anthropic_api", (conntype_select.value === "anthropic_api"));
if (conntype_select.value === "chatgpt_web") {
chatgpt_web_display = 'table-row';
}else{
chatgpt_web_display = 'none';
}
if (conntype_select.value === "chatgpt_api") {
chatgpt_api_display = 'table-row';
}else{
chatgpt_api_display = 'none';
}
if (conntype_select.value === "ollama_api") {
ollama_api_display = 'table-row';
}else{
ollama_api_display = 'none';
}
if (conntype_select.value === "openai_comp_api") {
openai_comp_api_display = 'table-row';
}else{
openai_comp_api_display = 'none';
}
if (conntype_select.value === "google_gemini_api") {
google_gemini_api_display = 'table-row';
}else{
google_gemini_api_display = 'none';
}
if (conntype_select.value === "anthropic_api") {
anthropic_api_display = 'table-row';
}else{
anthropic_api_display = 'none';
}
document.querySelectorAll(".conntype_chatgpt_web").forEach(element => {
element.style.display = chatgpt_web_display;
});
document.querySelectorAll(".conntype_chatgpt_api").forEach(element => {
element.style.display = chatgpt_api_display;
});
document.querySelectorAll(".conntype_ollama_api").forEach(element => {
element.style.display = ollama_api_display;
});
document.querySelectorAll(".conntype_openai_comp_api").forEach(element => {
element.style.display = openai_comp_api_display;
});
document.querySelectorAll(".conntype_google_gemini_api").forEach(element => {
element.style.display = google_gemini_api_display;
});
document.querySelectorAll(".conntype_anthropic_api").forEach(element => {
element.style.display = anthropic_api_display;
});
if (permission_all_urls) {
document.getElementById('openai_comp_api_cors_warning').style.display = 'none';
document.getElementById('ollama_api_cors_warning').style.display = 'none';
}
}
function warn_ChatGPT_APIKeyEmpty() {
let apiKeyInput = document.getElementById('chatgpt_api_key');
let btnFetchChatGPTModels = document.getElementById('btnUpdateChatGPTModels');
let modelChatGPT = document.getElementById('chatgpt_model');
if(apiKeyInput.value === ''){
apiKeyInput.style.border = '2px solid red';
btnFetchChatGPTModels.disabled = true;
modelChatGPT.disabled = true;
modelChatGPT.selectedIndex = -1;
modelChatGPT.style.border = '';
}else{
apiKeyInput.style.border = '';
btnFetchChatGPTModels.disabled = false;
modelChatGPT.disabled = false;
if((modelChatGPT.selectedIndex === -1)||(modelChatGPT.value === '')){
modelChatGPT.style.border = '2px solid red';
}else{
modelChatGPT.style.border = '';
}
}
}
function warn_GoogleGemini_APIKeyEmpty() {
let apiKeyInput = document.getElementById('google_gemini_api_key');
let btnFetchGoogleGeminiModels = document.getElementById('btnUpdateGoogleGeminiModels');
let modelGoogleGemini = document.getElementById('google_gemini_model');
if(apiKeyInput.value === ''){
apiKeyInput.style.border = '2px solid red';
btnFetchGoogleGeminiModels.disabled = true;
modelGoogleGemini.disabled = true;
modelGoogleGemini.selectedIndex = -1;
modelGoogleGemini.style.border = '';
}else{
apiKeyInput.style.border = '';
btnFetchGoogleGeminiModels.disabled = false;
modelGoogleGemini.disabled = false;
if((modelGoogleGemini.selectedIndex === -1)||(modelGoogleGemini.value === '')){
modelGoogleGemini.style.border = '2px solid red';
}else{
modelGoogleGemini.style.border = '';
}
}
}
function warn_Ollama_HostEmpty() {
let hostInput = document.getElementById('ollama_host');
let btnFetchOllamaModels = document.getElementById('btnUpdateOllamaModels');
let modelOllama = document.getElementById('ollama_model');
if(hostInput.value === ''){
hostInput.style.border = '2px solid red';
btnFetchOllamaModels.disabled = true;
modelOllama.disabled = true;
modelOllama.selectedIndex = -1;
modelOllama.style.border = '';
}else{
hostInput.style.border = '';
btnFetchOllamaModels.disabled = false;
modelOllama.disabled = false;
if((modelOllama.selectedIndex === -1)||(modelOllama.value === '')){
modelOllama.style.border = '2px solid red';
}else{
modelOllama.style.border = '';
}
}
}
function warn_OpenAIComp_HostEmpty() {
let hostInput = document.getElementById('openai_comp_host');
let btnUpdateOpenAICompModels = document.getElementById('btnUpdateOpenAICompModels');
let modelOpenAIComp = document.getElementById('openai_comp_model');
if(hostInput.value === ''){
hostInput.style.border = '2px solid red';
btnUpdateOpenAICompModels.disabled = true;
modelOpenAIComp.disabled = true;
modelOpenAIComp.selectedIndex = -1;
modelOpenAIComp.style.border = '';
}else{
hostInput.style.border = '';
btnUpdateOpenAICompModels.disabled = false;
modelOpenAIComp.disabled = false;
if((modelOpenAIComp.selectedIndex === -1)||(modelOpenAIComp.value === '')){
modelOpenAIComp.style.border = '2px solid red';
}else{
modelOpenAIComp.style.border = '';
}
}
}
function warn_Anthropic_APIKeyEmpty() {
let apiKeyInput = document.getElementById('anthropic_api_key');
let btnFetchAnthropicModels = document.getElementById('btnUpdateAnthropicModels');
let modelAnthropic = document.getElementById('anthropic_model');
if(apiKeyInput.value === ''){
apiKeyInput.style.border = '2px solid red';
btnFetchAnthropicModels.disabled = true;
modelAnthropic.disabled = true;
modelAnthropic.selectedIndex = -1;
modelAnthropic.style.border = '';
}else{
apiKeyInput.style.border = '';
btnFetchAnthropicModels.disabled = false;
modelAnthropic.disabled = false;
if((modelAnthropic.selectedIndex === -1)||(modelAnthropic.value === '')){
modelAnthropic.style.border = '2px solid red';
}else{
modelAnthropic.style.border = '';
}
}
}
function warn_Anthropic_VersionEmpty() {
let versionInput = document.getElementById('anthropic_version');
let btnFetchAnthropicModels = document.getElementById('btnUpdateAnthropicModels');
let modelAnthropic = document.getElementById('anthropic_model');
if(versionInput.value === ''){
versionInput.style.border = '2px solid red';
btnFetchAnthropicModels.disabled = true;
modelAnthropic.disabled = true;
modelAnthropic.selectedIndex = -1;
modelAnthropic.style.border = '';
}else{
versionInput.style.border = '';
btnFetchAnthropicModels.disabled = false;
modelAnthropic.disabled = false;
if((modelAnthropic.selectedIndex === -1)||(modelAnthropic.value === '')){
modelAnthropic.style.border = '2px solid red';
}else{
modelAnthropic.style.border = '';
}
}
}
function disable_MaxPromptLength(){ function disable_MaxPromptLength(){
let maxPromptLength = document.getElementById('max_prompt_length'); let maxPromptLength = document.getElementById('max_prompt_length');
let conntype_select = document.getElementById("connection_type"); let conntype_select = document.getElementById("connection_type");
@ -322,39 +124,36 @@ function disable_MaxPromptLength(){
maxPromptLength_tr.style.display = (maxPromptLength.disabled) ? 'none' : 'table-row'; maxPromptLength_tr.style.display = (maxPromptLength.disabled) ? 'none' : 'table-row';
} }
function disable_AddTags(){ function disable_AddTags(prefs_opt){
let add_tags = document.getElementById('add_tags'); let add_tags = document.getElementById('add_tags');
let conntype_select = document.getElementById("connection_type"); let conntype_select = document.getElementById("connection_type");
add_tags.disabled = (conntype_select.value === "chatgpt_web"); let add_tags_disabled = (getConnectionType(conntype_select.value, {api: prefs_opt.add_tags_use_specific_integration ? prefs_opt.add_tags_connection_type : ''}) === "chatgpt_web");
add_tags.checked = add_tags.disabled ? false : add_tags.checked; console.log('>>>>>>>>>>>>> add_tags_disabled: ' + add_tags_disabled);
add_tags.checked = add_tags_disabled ? false : add_tags.checked;
let add_tags_checked_original = add_tags.checked; let add_tags_checked_original = add_tags.checked;
if(!add_tags.checked){ if(!add_tags.checked){
let add_tags_info_btn = document.getElementById('btnManageTagsInfo'); let add_tags_info_btn = document.getElementById('btnManageTagsInfo');
add_tags_info_btn.disabled = 'disabled'; add_tags_info_btn.disabled = 'disabled';
} }
let add_tags_tr_elements = document.querySelectorAll('.add_tags_tr'); let add_tags_warn_API_needed = document.getElementById('add_tags_warn_API_needed');
add_tags_tr_elements.forEach(add_tags_tr => { add_tags_warn_API_needed.style.display = (add_tags_disabled) ? 'inline-block' : 'none';
add_tags_tr.style.display = (add_tags.disabled) ? 'none' : 'table-row';
});
if(add_tags_checked_original != add_tags.checked){ if(add_tags_checked_original != add_tags.checked){
browser.storage.sync.set({add_tags: add_tags.checked}); browser.storage.sync.set({add_tags: add_tags.checked});
} }
} }
function disable_SpamFilter(){ function disable_SpamFilter(prefs_opt){
let spamfilter = document.getElementById('spamfilter'); let spamfilter = document.getElementById('spamfilter');
let conntype_select = document.getElementById("connection_type"); let conntype_select = document.getElementById("connection_type");
spamfilter.disabled = (conntype_select.value === "chatgpt_web"); let spamfilter_disabled = (getConnectionType(conntype_select.value, {api: prefs_opt.spamfilter_use_specific_integration ? prefs_opt.spamfilter_connection_type : ''}) === "chatgpt_web");;
let spamfilter_checked_original = spamfilter.checked; let spamfilter_checked_original = spamfilter.checked;
spamfilter.checked = spamfilter.disabled ? false : spamfilter.checked; spamfilter.checked = spamfilter_disabled ? false : spamfilter.checked;
if(!spamfilter.checked){ if(!spamfilter.checked){
let spamfilter_info_btn = document.getElementById('btnManageSpamFilterInfo'); let spamfilter_info_btn = document.getElementById('btnManageSpamFilterInfo');
spamfilter_info_btn.disabled = 'disabled'; spamfilter_info_btn.disabled = 'disabled';
} }
let spamfilter_tr_elements = document.querySelectorAll('.spamfilter_tr'); let spamfilter_warn_API_needed = document.getElementById('spamfilter_warn_API_needed');
spamfilter_tr_elements.forEach(spamfilter_tr => { spamfilter_warn_API_needed.style.display = (spamfilter_disabled) ? 'inline-block' : 'none';
spamfilter_tr.style.display = (spamfilter.disabled) ? 'none' : 'table-row';
});
if(spamfilter_checked_original != spamfilter.checked){ if(spamfilter_checked_original != spamfilter.checked){
browser.storage.sync.set({spamfilter: spamfilter.checked}); browser.storage.sync.set({spamfilter: spamfilter.checked});
} }
@ -383,21 +182,6 @@ async function disable_GetCalendarEvent(){
wrong_sparks_text.style.display = (is_spark_present == 0) ? 'inline' : 'none'; wrong_sparks_text.style.display = (is_spark_present == 0) ? 'inline' : 'none';
} }
function loadOpenAICompConfigs(){
let select_openai_comp_model = document.getElementById('openai_comp_services_shortcut');
openAICompConfigs.forEach(config => {
const option = document.createElement('option');
option.value = config.id;
option.text = config.name;
select_openai_comp_model.appendChild(option);
});
}
function resetOpenAICompConfigs(){
let select_openai_comp_model = document.getElementById('openai_comp_services_shortcut');
select_openai_comp_model.value = 'custom';
}
function resetMaxPromptLength(){ function resetMaxPromptLength(){
let maxPromptLength = document.getElementById('max_prompt_length'); let maxPromptLength = document.getElementById('max_prompt_length');
maxPromptLength.value = prefs_default.max_prompt_length; maxPromptLength.value = prefs_default.max_prompt_length;
@ -405,9 +189,15 @@ function resetMaxPromptLength(){
} }
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
await injectConnectionUI({
afterTrId: 'connection_ui_anchor',
selectId: 'connection_type',
taLog: taLog
});
await restoreOptions(); await restoreOptions();
permission_all_urls = await messenger.permissions.contains({ origins: ["<all_urls>"] }) varConnectionUI.permission_all_urls = await messenger.permissions.contains({ origins: ["<all_urls>"] })
_isThunderbird128OrGreater = await isThunderbird128OrGreater(); _isThunderbird128OrGreater = await isThunderbird128OrGreater();
@ -502,39 +292,6 @@ document.addEventListener('DOMContentLoaded', async () => {
openTab('/pages/get-task/mzta-get-task.html'); openTab('/pages/get-task/mzta-get-task.html');
}); });
document.getElementById('btnOpenAICompForceModel').addEventListener('click', () => {
let modelName = prompt(browser.i18n.getMessage('OpenAIComp_force_model_ask')).trim();
if ((modelName !== null) && (modelName !== undefined) && (modelName !== '')) {
let select_openai_comp_model = document.getElementById('openai_comp_model');
let option = document.createElement('option');
option.value = modelName;
option.text = modelName;
select_openai_comp_model.appendChild(option);
select_openai_comp_model.value = modelName;
select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true }));
}
});
document.getElementById('btnOpenAICompClearModelsList').addEventListener('click', () => {
if (!confirm(browser.i18n.getMessage('OpenAIComp_ClearModelsList_Confirm'))) {
return;
}
let select_openai_comp_model = document.getElementById('openai_comp_model');
while (select_openai_comp_model.options.length > 0) {
select_openai_comp_model.remove(0);
}
select_openai_comp_model.value = '';
select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true }));
});
document.getElementById('btnGiveAllUrlsPermission_ollama_api').addEventListener('click', async () => {
permission_all_urls = await messenger.permissions.request({ origins: ["<all_urls>"] });
});
document.getElementById('btnGiveAllUrlsPermission_openai_comp_api').addEventListener('click', async () => {
permission_all_urls = await messenger.permissions.request({ origins: ["<all_urls>"] });
});
getChatGPTWebModelsList_HTML(ChatGPTWeb_models, 'chatgpt_web_models_list'); getChatGPTWebModelsList_HTML(ChatGPTWeb_models, 'chatgpt_web_models_list');
document.querySelectorAll(".conntype_chatgpt_web_option").forEach(element => { document.querySelectorAll(".conntype_chatgpt_web_option").forEach(element => {
element.addEventListener("click", () => { element.addEventListener("click", () => {
@ -544,348 +301,26 @@ document.addEventListener('DOMContentLoaded', async () => {
}); });
}); });
let prefs_opt = await browser.storage.sync.get({
add_tags_use_specific_integration: prefs_default.add_tags_use_specific_integration,
add_tags_connection_type: prefs_default.add_tags_connection_type,
spamfilter_use_specific_integration: prefs_default.spamfilter_use_specific_integration,
spamfilter_connection_type: prefs_default.spamfilter_connection_type,
});
let conntype_select = document.getElementById("connection_type"); let conntype_select = document.getElementById("connection_type");
conntype_select.addEventListener("change", showConnectionOptions); conntype_select.addEventListener("change", disable_MaxPromptLength);
conntype_select.addEventListener("change", warn_ChatGPT_APIKeyEmpty); conntype_select.addEventListener("change", () => disable_AddTags(prefs_opt));
conntype_select.addEventListener("change", warn_Ollama_HostEmpty); conntype_select.addEventListener("change", () => disable_SpamFilter(prefs_opt));
conntype_select.addEventListener("change", warn_OpenAIComp_HostEmpty);
conntype_select.addEventListener("change", warn_GoogleGemini_APIKeyEmpty);
conntype_select.addEventListener("change", warn_Anthropic_APIKeyEmpty);
conntype_select.addEventListener("change", warn_Anthropic_VersionEmpty);
conntype_select.addEventListener("change", disable_AddTags);
conntype_select.addEventListener("change", disable_SpamFilter);
conntype_select.addEventListener("change", disable_GetCalendarEvent); conntype_select.addEventListener("change", disable_GetCalendarEvent);
document.getElementById("chatgpt_api_key").addEventListener("change", warn_ChatGPT_APIKeyEmpty);
document.getElementById("ollama_host").addEventListener("change", warn_Ollama_HostEmpty);
document.getElementById("openai_comp_host").addEventListener("change", warn_OpenAIComp_HostEmpty);
document.getElementById("google_gemini_api_key").addEventListener("change", warn_GoogleGemini_APIKeyEmpty);
document.getElementById("chatgpt_web_project").addEventListener("input", validateCustomData_ChatGPTWeb);
document.getElementById("chatgpt_web_custom_gpt").addEventListener("input", validateCustomData_ChatGPTWeb);
document.getElementById("anthropic_api_key").addEventListener("change", warn_Anthropic_APIKeyEmpty);
document.getElementById("anthropic_version").addEventListener("change", warn_Anthropic_VersionEmpty);
document.getElementById("openai_comp_host").addEventListener("input", resetOpenAICompConfigs);
document.getElementById("openai_comp_chat_name").addEventListener("input", resetOpenAICompConfigs);
document.getElementById("openai_comp_use_v1").addEventListener("input", resetOpenAICompConfigs);
showConnectionOptions(conntype_select);
let prefs = await browser.storage.sync.get({chatgpt_web_model: '', chatgpt_model: '', ollama_model: '', openai_comp_model: '', google_gemini_model: '', anthropic_model: '', anthropic_version: '', chatgpt_win_height: 0, chatgpt_win_width: 0 });
// OpenAI API ChatGPT model fetching
let select_chatgpt_model = document.getElementById('chatgpt_model');
const chatgpt_option = document.createElement('option');
chatgpt_option.value = prefs.chatgpt_model;
chatgpt_option.text = prefs.chatgpt_model;
select_chatgpt_model.appendChild(chatgpt_option);
select_chatgpt_model.addEventListener("change", warn_ChatGPT_APIKeyEmpty);
document.getElementById('btnUpdateChatGPTModels').addEventListener('click', async () => {
document.getElementById('chatgpt_model_fetch_loading').style.display = 'inline';
let openai = new OpenAI({
apiKey: document.getElementById("chatgpt_api_key").value,
stream: true
});
openai.fetchModels().then((data) => {
if(!data.ok){
let errorDetail;
try {
errorDetail = JSON.parse(data.error);
errorDetail = errorDetail.error.message;
} catch (e) {
errorDetail = data.error;
}
document.getElementById('chatgpt_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("ChatGPT_Models_Error_fetching"));
alert(browser.i18n.getMessage("ChatGPT_Models_Error_fetching")+": " + errorDetail);
return;
}
taLog.log("ChatGPT models: " + JSON.stringify(data));
data.response.forEach(model => {
if (!Array.from(select_chatgpt_model.options).some(option => option.value === model.id)) {
const option = document.createElement('option');
option.value = model.id;
option.text = model.id;
select_chatgpt_model.appendChild(option);
}
});
document.getElementById('chatgpt_model_fetch_loading').style.display = 'none';
});
warn_ChatGPT_APIKeyEmpty();
});
// Google Gemini API model fetching
let select_google_gemini_model = document.getElementById('google_gemini_model');
const google_gemini_option = document.createElement('option');
google_gemini_option.value = prefs.google_gemini_model;
google_gemini_option.text = prefs.google_gemini_model;
select_google_gemini_model.appendChild(google_gemini_option);
select_google_gemini_model.addEventListener("change", warn_GoogleGemini_APIKeyEmpty);
document.getElementById('btnUpdateGoogleGeminiModels').addEventListener('click', async () => {
document.getElementById('google_gemini_model_fetch_loading').style.display = 'inline';
let google_gemini = new GoogleGemini({
apiKey: document.getElementById("google_gemini_api_key").value,
stream: true
});
google_gemini.fetchModels().then((data) => {
if(!data.ok){
let errorDetail;
try {
errorDetail = JSON.parse(data.error);
errorDetail = errorDetail.error.message;
} catch (e) {
errorDetail = data.error;
}
document.getElementById('google_gemini_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("GoogleGemini_Models_Error_fetching"));
alert(browser.i18n.getMessage("GoogleGemini_Models_Error_fetching")+": " + errorDetail);
return;
}
taLog.log("GoogleGemini models: " + JSON.stringify(data));
data.response.forEach(model => {
if (!Array.from(select_google_gemini_model.options).some(option => option.value === model.name.substring(model.name.lastIndexOf("/") + 1))) {
const option = document.createElement('option');
option.value = model.name.substring(model.name.lastIndexOf("/") + 1);
option.text = model.displayName;
select_google_gemini_model.appendChild(option);
}
});
document.getElementById('google_gemini_model_fetch_loading').style.display = 'none';
});
warn_GoogleGemini_APIKeyEmpty();
});
// Ollama API Model fetching
let select_ollama_model = document.getElementById('ollama_model');
const ollama_option = document.createElement('option');
ollama_option.value = prefs.ollama_model;
ollama_option.text = prefs.ollama_model;
select_ollama_model.appendChild(ollama_option);
select_ollama_model.addEventListener("change", warn_Ollama_HostEmpty);
document.getElementById('btnUpdateOllamaModels').addEventListener('click', async () => {
document.getElementById('ollama_model_fetch_loading').style.display = 'inline';
let ollama = new Ollama({
host: document.getElementById("ollama_host").value,
stream: true
});
try {
let data = await ollama.fetchModels();
if(!data){
document.getElementById('ollama_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("Ollama_Models_Error_fetching"));
alert(browser.i18n.getMessage("Ollama_Models_Error_fetching"));
return;
}
if(!data.ok){
let errorDetail;
try {
errorDetail = JSON.parse(data.error);
errorDetail = errorDetail.error.message;
} catch (e) {
errorDetail = data.error;
}
document.getElementById('ollama_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("Ollama_Models_Error_fetching"));
alert(browser.i18n.getMessage("Ollama_Models_Error_fetching")+": " + errorDetail);
return;
}
if(data.response.models.length == 0){
document.getElementById('ollama_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("Ollama_Models_Error_fetching"));
alert(browser.i18n.getMessage("Ollama_Models_Error_fetching")+": " + browser.i18n.getMessage("API_Models_Error_NoModels"));
return;
}
taLog.log("Ollama models: " + JSON.stringify(data));
data.response.models.forEach(model => {
if (!Array.from(select_ollama_model.options).some(option => option.value === model.model)) {
const option = document.createElement('option');
option.value = model.model;
option.text = model.name + " (" + model.model + ")";
select_ollama_model.appendChild(option);
}
});
document.getElementById('ollama_model_fetch_loading').style.display = 'none';
} catch (error) {
document.getElementById('ollama_model_fetch_loading').style.display = 'none';
taLog.error(browser.i18n.getMessage("Ollama_Models_Error_fetching"));
alert(browser.i18n.getMessage("Ollama_Models_Error_fetching")+": " + error.message);
}
warn_Ollama_HostEmpty();
});
// OpenAI Comp API Model fetching
let select_openai_comp_model = document.getElementById('openai_comp_model');
const openai_comp_option = document.createElement('option');
openai_comp_option.value = prefs.openai_comp_model;
openai_comp_option.text = prefs.openai_comp_model;
select_openai_comp_model.appendChild(openai_comp_option);
select_openai_comp_model.addEventListener("change", warn_OpenAIComp_HostEmpty);
document.getElementById('btnUpdateOpenAICompModels').addEventListener('click', async () => {
document.getElementById('openai_comp_model_fetch_loading').style.display = 'inline';
let openai_comp = new OpenAIComp({
host: document.getElementById("openai_comp_host").value,
model: null,
apiKey: document.getElementById("openai_comp_api_key").value,
stream: true,
use_v1: document.getElementById("openai_comp_use_v1").checked
});
openai_comp.fetchModels().then((data) => {
if(!data.ok){
let errorDetail;
try {
errorDetail = JSON.parse(data.error);
errorDetail = errorDetail.error.message;
} catch (e) {
errorDetail = data.error;
}
document.getElementById('openai_comp_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("OpenAIComp_Models_Error_fetching"));
alert(browser.i18n.getMessage("OpenAIComp_Models_Error_fetching")+": " + errorDetail);
return;
}
taLog.log("OpenAIComp models: " + JSON.stringify(data));
data.response.forEach(model => {
if (!Array.from(select_openai_comp_model.options).some(option => option.value === model.id)) {
const option = document.createElement('option');
option.value = model.id;
option.text = model.id;
select_openai_comp_model.appendChild(option);
}
});
document.getElementById('openai_comp_model_fetch_loading').style.display = 'none';
});
warn_OpenAIComp_HostEmpty();
});
// Anthropic API model fetching
let select_anthropic_model = document.getElementById('anthropic_model');
const anthropic_option = document.createElement('option');
anthropic_option.value = prefs.anthropic_model;
anthropic_option.text = prefs.anthropic_model;
select_anthropic_model.appendChild(anthropic_option);
select_anthropic_model.addEventListener("change", warn_Anthropic_APIKeyEmpty);
select_anthropic_model.addEventListener("change", warn_Anthropic_VersionEmpty);
document.getElementById('btnUpdateAnthropicModels').addEventListener('click', async () => {
document.getElementById('anthropic_model_fetch_loading').style.display = 'inline';
let anthropic = new Anthropic({
apiKey: document.getElementById("anthropic_api_key").value,
version: document.getElementById("anthropic_version").value
});
anthropic.fetchModels().then((data) => {
if(!data.ok){
let errorDetail;
try {
errorDetail = JSON.parse(data.error);
errorDetail = errorDetail.error.message;
} catch (e) {
errorDetail = data.error;
}
document.getElementById('anthropic_model_fetch_loading').style.display = 'none';
console.error("[ThunderAI] " + browser.i18n.getMessage("Anthropic_Models_Error_fetching"));
alert(browser.i18n.getMessage("Anthropic_Models_Error_fetching")+": " + errorDetail);
return;
}
taLog.log("Anthropic models: " + JSON.stringify(data));
data.response.forEach(model => {
const existingOption = Array.from(select_anthropic_model.options).find(option => option.value === model.id);
if (existingOption) {
existingOption.text = model.display_name + " (" + model.id + ")";
} else {
const option = document.createElement('option');
option.value = model.id;
option.text = model.display_name + " (" + model.id + ")";
select_anthropic_model.appendChild(option);
}
});
document.getElementById('anthropic_model_fetch_loading').style.display = 'none';
});
warn_Anthropic_APIKeyEmpty();
});
showConnectionOptions();
warn_ChatGPT_APIKeyEmpty();
warn_Ollama_HostEmpty();
warn_OpenAIComp_HostEmpty();
warn_GoogleGemini_APIKeyEmpty();
warn_Anthropic_APIKeyEmpty();
warn_Anthropic_VersionEmpty();
disable_MaxPromptLength(); disable_MaxPromptLength();
disable_AddTags(); disable_AddTags(prefs_opt);
disable_SpamFilter(); disable_SpamFilter(prefs_opt);
disable_GetCalendarEvent(); disable_GetCalendarEvent();
const passwordField_chatgpt_api_key = document.getElementById('chatgpt_api_key'); document.getElementById('reset_max_prompt_length').addEventListener('click', resetMaxPromptLength);
const toggleIcon_chatgpt_api_key = document.getElementById('toggle_chatgpt_api_key');
const icon_img_chatgpt_api_key = document.getElementById('pwd-icon_chatgpt_api_key');
toggleIcon_chatgpt_api_key.addEventListener('click', () => {
const type = passwordField_chatgpt_api_key.getAttribute('type') === 'password' ? 'text' : 'password';
passwordField_chatgpt_api_key.setAttribute('type', type);
icon_img_chatgpt_api_key.src = type === 'password' ? "../images/pwd-show.png" : "../images/pwd-hide.png";
});
const passwordField_google_gemini_api_key = document.getElementById('google_gemini_api_key');
const toggleIcon_google_gemini_api_key = document.getElementById('toggle_google_gemini_api_key');
const icon_img_google_gemini_api_key = document.getElementById('pwd-icon_google_gemini_api_key');
toggleIcon_google_gemini_api_key.addEventListener('click', () => {
const type = passwordField_google_gemini_api_key.getAttribute('type') === 'password' ? 'text' : 'password';
passwordField_google_gemini_api_key.setAttribute('type', type);
icon_img_google_gemini_api_key.src = type === 'password' ? "../images/pwd-show.png" : "../images/pwd-hide.png";
});
const passwordField_openai_comp_api_key = document.getElementById('openai_comp_api_key');
const toggleIcon_openai_comp_api_key = document.getElementById('toggle_openai_comp_api_key');
const icon_img_openai_comp_api_key = document.getElementById('pwd-icon_openai_comp_api_key');
toggleIcon_openai_comp_api_key.addEventListener('click', () => {
const type = passwordField_openai_comp_api_key.getAttribute('type') === 'password' ? 'text' : 'password';
passwordField_openai_comp_api_key.setAttribute('type', type);
icon_img_openai_comp_api_key.src = type === 'password' ? "../images/pwd-show.png" : "../images/pwd-hide.png";
});
const passwordField_anthropic_api_key = document.getElementById('anthropic_api_key');
const toggleIcon_anthropic_api_key = document.getElementById('toggle_anthropic_api_key');
const icon_img_anthropic_api_key = document.getElementById('pwd-icon_anthropic_api_key');
toggleIcon_anthropic_api_key.addEventListener('click', () => {
const type = passwordField_anthropic_api_key.getAttribute('type') === 'password' ? 'text' : 'password';
passwordField_anthropic_api_key.setAttribute('type', type);
icon_img_anthropic_api_key.src = type === 'password' ? "../images/pwd-show.png" : "../images/pwd-hide.png";
});
const btnChatGPTWeb_Tab = document.getElementById('btnChatGPTWeb_Tab');
btnChatGPTWeb_Tab.addEventListener('click', async () => {
let prefs_mod = await browser.storage.sync.get({chatgpt_web_model: prefs_default.chatgpt_web_model, chatgpt_web_project: prefs_default.chatgpt_web_project, chatgpt_web_custom_gpt: prefs_default.chatgpt_web_custom_gpt});
let base_url = 'https://chatgpt.com';
let model_opt = '';
let webproject_set = false;
if((prefs_mod.chatgpt_web_model != '') && (prefs_mod.chatgpt_web_model != undefined)){
model_opt = '?model=' + sanitizeChatGPTModelData(prefs_mod.chatgpt_web_model);
}
if((prefs_mod.chatgpt_web_project != '') && (prefs_mod.chatgpt_web_project != undefined)){
base_url += sanitizeChatGPTWebCustomData(prefs_mod.chatgpt_web_project);
webproject_set = true;
}
if(!webproject_set && (prefs_mod.chatgpt_web_custom_gpt != '') && (prefs_mod.chatgpt_web_custom_gpt != undefined)){
base_url += sanitizeChatGPTWebCustomData(prefs_mod.chatgpt_web_custom_gpt);
}
browser.tabs.create({ url: base_url + model_opt });
});
browser.runtime.getPlatformInfo().then(info => { browser.runtime.getPlatformInfo().then(info => {
taLog.log("OS: " + info.os); taLog.log("OS: " + info.os);
@ -894,32 +329,6 @@ document.addEventListener('DOMContentLoaded', async () => {
} }
}); });
loadOpenAICompConfigs(); updateWarnings();
let select_openai_comp_services_shortcut = document.getElementById('openai_comp_services_shortcut');
select_openai_comp_services_shortcut.addEventListener("change", () => {
let selectedOption = select_openai_comp_services_shortcut.options[select_openai_comp_services_shortcut.selectedIndex];
const config = openAICompConfigs.find(cfg => cfg.id === selectedOption.value);
if (config) {
if (!confirm(browser.i18n.getMessage('OpenAIComp_Configs_ConfirmApply', config.name))) {
return;
}
document.getElementById('openai_comp_host').value = config.host || '';
// Clear all options from the select except the first (placeholder) one
const openaiCompModelSelect = document.getElementById('openai_comp_model');
openaiCompModelSelect.value = '';
while (openaiCompModelSelect.options.length > 0) {
openaiCompModelSelect.remove(0);
}
document.getElementById('openai_comp_use_v1').checked = !!config.use_v1;
document.getElementById('openai_comp_chat_name').value = config.chat_name || '';
// Trigger change events if needed
document.getElementById('openai_comp_host').dispatchEvent(new Event('change', { bubbles: true }));
document.getElementById('openai_comp_model').dispatchEvent(new Event('change', { bubbles: true }));
document.getElementById('openai_comp_use_v1').dispatchEvent(new Event('change', { bubbles: true }));
document.getElementById('openai_comp_chat_name').dispatchEvent(new Event('change', { bubbles: true }));
}
});
document.getElementById('reset_max_prompt_length').addEventListener('click', resetMaxPromptLength);
}, { once: true }); }, { once: true });

View file

@ -13,6 +13,7 @@
<li><i>[ChatGPT Web]</i> Added a message to explain to click on "Force completion" if the ChatGPT job is not done after 7 seconds [<a href="https://github.com/micz/ThunderAI/issues/419">#419</a>].</li> <li><i>[ChatGPT Web]</i> Added a message to explain to click on "Force completion" if the ChatGPT job is not done after 7 seconds [<a href="https://github.com/micz/ThunderAI/issues/419">#419</a>].</li>
<li><i>[All APIs]</i> The prompt id and name are now shown in the information header in the AI API chat [<a href="https://github.com/micz/ThunderAI/issues/436">#436</a>].</li> <li><i>[All APIs]</i> The prompt id and name are now shown in the information header in the AI API chat [<a href="https://github.com/micz/ThunderAI/issues/436">#436</a>].</li>
<li><i>[Google Gemini API]</i>Support for the thinkingBudget parameter has been added [<a href="https://github.com/micz/ThunderAI/issues/494">#494</a>].</li> <li><i>[Google Gemini API]</i>Support for the thinkingBudget parameter has been added [<a href="https://github.com/micz/ThunderAI/issues/494">#494</a>].</li>
<li>Various code improvements and minor bugs fixed.</li>
<li>...</li> <li>...</li>
</ul> </ul>
<h2>Version 3.6.1 - 23/08/2025</h2> <h2>Version 3.6.1 - 23/08/2025</h2>

View file

@ -0,0 +1,118 @@
tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{
background-color: rgb(185, 220, 252);
}
tr.conntype_chatgpt_web, tr.conntype_chatgpt_web2{
background-color: rgb(255, 209, 183);
}
tr.conntype_ollama_api, tr.conntype_ollama_api2{
background-color: rgb(177, 238, 169);
}
tr.conntype_openai_comp_api, tr.conntype_openai_comp_api2{
background-color: rgb(213, 169, 238);
}
tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{
background-color: rgb(233, 238, 169);
}
tr.conntype_anthropic_api, tr.conntype_anthropic_api2{
background-color: rgb(255, 168, 204);
}
#chatgpt_model_fetch_loading{
display: none;
font-style: italic;
}
#google_gemini_model_fetch_loading{
display: none;
font-style: italic;
}
textarea.option-textarea{
width: -moz-available;
height: 10em;
}
.api_key-container {
position: relative;
width: 100%;
}
.api_key-container input {
width: -moz-available;
margin-right: 25px;
}
input[type="text"], input[type="password"]{
border-radius: 4px;
padding: 2px;
}
input.option-input[type="text"]{
width: -moz-available;
}
.api_key-container .toggle-icon {
position: absolute;
right: 0px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
}
#ollama_model_fetch_loading{
display: none;
font-style: italic;
}
#openai_comp_model_fetch_loading{
display: none;
font-style: italic;
}
#anthropic_model_fetch_loading{
display: none;
font-style: italic;
}
.conntype_chatgpt_web_option{
cursor: pointer;
}
span.opt_title{
font-weight: bold;
}
@media (prefers-color-scheme: dark) {
tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{
background-color: rgb(0, 0, 58);
}
tr.conntype_chatgpt_web,tr.conntype_chatgpt_web2{
background-color: rgb(39, 11, 0);
}
tr.conntype_ollama_api, tr.conntype_ollama_api2{
background-color: rgb(7, 58, 0);
}
tr.conntype_openai_comp_api, tr.conntype_openai_comp_api2{
background-color: rgb(89, 20, 129);
}
tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{
background-color: rgb(72, 77, 3);
}
tr.conntype_anthropic_api, tr.conntype_anthropic_api2{
background-color: rgb(83, 0, 35);
}
.api_key-container .toggle-icon img {
filter: invert(1);
}
}

1103
pages/_lib/connection-ui.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -43,10 +43,46 @@
background-color: #e9ffdf; background-color: #e9ffdf;
} }
tr.add_tags_auto_sub td{ .specific_integration{
background-color: #dfeaff;
}
tr.add_tags_auto_sub td,
tr.specific_integration_sub td{
padding-left: 0.8em !important; padding-left: 0.8em !important;
} }
.specific_integration_sub{
display: none;
}
table {
border-collapse: separate;
border-spacing: 0;
}
.group td {
border-top: none;
border-bottom: none;
}
.specific_integration_sub td:first-child {
border-left: 10px solid #dfeaff;
}
.specific_integration_sub td:last-child {
border-right: 10px solid #dfeaff;
}
#connection_ui_end td{
height: 6px;
background-color: #dfeaff;
}
#connection_ui_end{
display: none;
}
.btn_div{ .btn_div{
width: 100%; width: 100%;
display: flex; display: flex;
@ -72,6 +108,7 @@ table#miczPrefs {
.section_title{ .section_title{
font-weight: bold; font-weight: bold;
font-size: 1.2em;
} }
table#miczPrefs td{ table#miczPrefs td{
@ -159,4 +196,20 @@ table#miczPrefs tr:last-child td {
.add_tags_auto{ .add_tags_auto{
background-color: #415c35; background-color: #415c35;
} }
.specific_integration{
background-color: #2E3A4F;
}
.specific_integration_sub td:first-child {
border-left: 10px solid #2E3A4F;
}
.specific_integration_sub td:last-child {
border-right: 10px solid #2E3A4F;
}
#connection_ui_end td{
background-color: #2E3A4F;
}
} }

View file

@ -4,6 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>ThunderAI - __MSG_AddTags_PageTitle__</title> <title>ThunderAI - __MSG_AddTags_PageTitle__</title>
<link rel="stylesheet" href="mzta-add-tags.css"> <link rel="stylesheet" href="mzta-add-tags.css">
<link rel="stylesheet" href="../_lib/connection-ui.css">
<link rel="icon" href="../../images/icon-16px.png"> <link rel="icon" href="../../images/icon-16px.png">
</head> </head>
<body> <body>
@ -13,8 +14,20 @@
</div> </div>
<div class="addtags_table_title section_title">__MSG_AddTags_prompt_prefs_title__</div> <div class="addtags_table_title section_title">__MSG_AddTags_prompt_prefs_title__</div>
<table id="miczPrefs"> <table id="miczPrefs">
<tr class="add_tags_tr specific_integration">
<td><span class="opt_title">__MSG_prefs_OptionText_use_specific_integration__</span>
</td>
<td>
<label>
<input type="checkbox" id="add_tags_use_specific_integration" name="add_tags_use_specific_integration" class="option-input" />
__MSG_prefs_OptionText_add_tags_use_specific_integration_Info__
</label>
</td>
</tr>
<tr id="connection_ui_anchor"></tr>
<tr id="connection_ui_end"><td colspan="2"></td></tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_maxnum__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_maxnum__</span></td>
<td> <td>
<label> <label>
<input type="number" id="add_tags_maxnum" name="add_tags_maxnum" class="option-input" /> <input type="number" id="add_tags_maxnum" name="add_tags_maxnum" class="option-input" />
@ -23,7 +36,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_exclusions_exact_match__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_exclusions_exact_match__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_exclusions_exact_match" name="add_tags_exclusions_exact_match" class="option-input" /> <input type="checkbox" id="add_tags_exclusions_exact_match" name="add_tags_exclusions_exact_match" class="option-input" />
@ -32,7 +45,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_hide_exclusions__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_hide_exclusions__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_hide_exclusions" name="add_tags_hide_exclusions" class="option-input" /> <input type="checkbox" id="add_tags_hide_exclusions" name="add_tags_hide_exclusions" class="option-input" />
@ -41,7 +54,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_first_uppercase__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_first_uppercase__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_first_uppercase" name="add_tags_first_uppercase" class="option-input" /> <input type="checkbox" id="add_tags_first_uppercase" name="add_tags_first_uppercase" class="option-input" />
@ -50,7 +63,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_force_lang__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_force_lang__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_force_lang" name="add_tags_force_lang" class="option-input" /> <input type="checkbox" id="add_tags_force_lang" name="add_tags_force_lang" class="option-input" />
@ -59,7 +72,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr add_tags_auto"> <tr class="add_tags_tr add_tags_auto">
<td><span>__MSG_prefs_OptionText_add_tags_auto__</span> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_auto__</span>
<span class="infoline" id="add_tags_auto_infoline"><br>__MSG_prefs_OptionText_add_tags_auto_Info2__</span></td> <span class="infoline" id="add_tags_auto_infoline"><br>__MSG_prefs_OptionText_add_tags_auto_Info2__</span></td>
<td> <td>
<label> <label>
@ -69,7 +82,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr add_tags_auto add_tags_auto_sub" id="add_tags_auto_only_inbox_tr"> <tr class="add_tags_tr add_tags_auto add_tags_auto_sub" id="add_tags_auto_only_inbox_tr">
<td><span>__MSG_prefs_OptionText_add_tags_auto_only_inbox__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_auto_only_inbox__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_auto_only_inbox" name="add_tags_auto_only_inbox" class="option-input" /> <input type="checkbox" id="add_tags_auto_only_inbox" name="add_tags_auto_only_inbox" class="option-input" />
@ -78,7 +91,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr add_tags_auto add_tags_auto_sub" id="add_tags_auto_uselist_tr"> <tr class="add_tags_tr add_tags_auto add_tags_auto_sub" id="add_tags_auto_uselist_tr">
<td><span>__MSG_prefs_OptionText_add_tags_auto_uselist__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_auto_uselist__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_auto_uselist" name="add_tags_auto_uselist" class="option-input" /> <input type="checkbox" id="add_tags_auto_uselist" name="add_tags_auto_uselist" class="option-input" />
@ -89,7 +102,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_context_menu__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_context_menu__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_context_menu" name="add_tags_context_menu" class="option-input" /> <input type="checkbox" id="add_tags_context_menu" name="add_tags_context_menu" class="option-input" />
@ -98,7 +111,7 @@
</td> </td>
</tr> </tr>
<tr class="add_tags_tr"> <tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_auto_force_existing__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_add_tags_auto_force_existing__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="add_tags_auto_force_existing" name="add_tags_auto_force_existing" class="option-input" /> <input type="checkbox" id="add_tags_auto_force_existing" name="add_tags_auto_force_existing" class="option-input" />

View file

@ -18,17 +18,48 @@
import { prefs_default } from '../../options/mzta-options-default.js'; import { prefs_default } from '../../options/mzta-options-default.js';
import { taLogger } from '../../js/mzta-logger.js'; import { taLogger } from '../../js/mzta-logger.js';
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js"; import {
getSpecialPrompts,
setSpecialPrompts,
loadPrompt,
savePrompt,
clearPromptAPI
} from "../../js/mzta-prompts.js";
import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js";
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
import { addTags_getExclusionList, addTags_setExclusionList } from "../../js/mzta-addatags-exclusion-list.js"; import {
import { getAccountsList, normalizeStringList } from "../../js/mzta-utils.js"; addTags_getExclusionList,
addTags_setExclusionList
} from "../../js/mzta-addatags-exclusion-list.js";
import {
getAccountsList,
normalizeStringList,
isAPIKeyValue
} from "../../js/mzta-utils.js";
import {
injectConnectionUI,
updateWarnings,
changeConnTypeRowColor
} from "../_lib/connection-ui.js";
let autocompleteSuggestions = []; let autocompleteSuggestions = [];
let taLog = new taLogger("mzta-addtags-page",true); let taLog = new taLogger("mzta-addtags-page",true);
let conntype_select_id = 'add_tags_connection_type';
let model_prefix = 'add_tags_';
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
try {
await injectConnectionUI({
afterTrId: 'connection_ui_anchor',
tr_class: 'specific_integration_sub',
selectId: conntype_select_id,
modelId_prefix: model_prefix,
no_chatgpt_web: true,
taLog: taLog
});
} catch (e) {
console.error('Failed to inject connection UI (add-tags)', e);
}
i18n.updateDocument(); i18n.updateDocument();
await restoreOptions(); await restoreOptions();
@ -36,6 +67,47 @@ document.addEventListener('DOMContentLoaded', async () => {
element.addEventListener("change", saveOptions); element.addEventListener("change", saveOptions);
}); });
document.querySelectorAll(".option-input-model").forEach(element => {
element.addEventListener("change", updatePromptAPIInfo);
});
let conntype_el = document.getElementById(conntype_select_id);
let conntype_end_el = document.getElementById('connection_ui_end');
conntype_el.addEventListener('change', updatePromptAPIInfo);
let add_tags_use_specific_integration_el = document.getElementById('add_tags_use_specific_integration');
let prefs_add_tags = await browser.storage.sync.get({ add_tags_enabled_accounts: [], connection_type: 'chatgpt_web' });
if(prefs_add_tags.connection_type == 'chatgpt_web'){
add_tags_use_specific_integration_el.checked = true;
add_tags_use_specific_integration_el.dispatchEvent(new Event('change'));
add_tags_use_specific_integration_el.disabled = true;
}
let conntype_row = document.getElementById(conntype_select_id + '_tr');
add_tags_use_specific_integration_el.addEventListener('change', (event) => {
// console.log(">>>>>>>>>>>>> conntype_el.value: " + conntype_el.value);
document.querySelectorAll(".specific_integration_sub").forEach(tr => {
tr.style.display = event.target.checked && tr.classList.contains('conntype_' + conntype_el.value) ? 'table-row' : 'none';
});
conntype_el.style.display = event.target.checked ? 'table-row' : 'none';
conntype_end_el.style.display = event.target.checked ? 'table-row' : 'none';
changeConnTypeRowColor(conntype_row, conntype_el);
if(!event.target.checked){
clearPromptAPI('prompt_add_tags');
}else{
updatePromptAPIInfo();
}
});
// console.log(">>>>>>>>>>>>> conntype_el.value: " + conntype_el.value);
document.querySelectorAll(".specific_integration_sub").forEach(tr => {
tr.style.display = add_tags_use_specific_integration_el.checked && tr.classList.contains('conntype_' + conntype_el.value) ? 'table-row' : 'none';
});
document.getElementById(conntype_select_id + '_tr').style.display = add_tags_use_specific_integration_el.checked ? 'table-row' : 'none';
conntype_end_el.style.display = add_tags_use_specific_integration_el.checked ? 'table-row' : 'none';
changeConnTypeRowColor(conntype_row, conntype_el);
let addtags_textarea = document.getElementById('addtags_prompt_text'); let addtags_textarea = document.getElementById('addtags_prompt_text');
let addtags_save_btn = document.getElementById('btn_save_prompt'); let addtags_save_btn = document.getElementById('btn_save_prompt');
let addtags_reset_btn = document.getElementById('btn_reset_prompt'); let addtags_reset_btn = document.getElementById('btn_reset_prompt');
@ -148,7 +220,6 @@ document.addEventListener('DOMContentLoaded', async () => {
accountsContainer.appendChild(document.createElement('br')); accountsContainer.appendChild(document.createElement('br'));
}); });
let prefs_add_tags = await browser.storage.sync.get({ add_tags_enabled_accounts: [] });
let add_tags_enabled_accounts = prefs_add_tags.add_tags_enabled_accounts; let add_tags_enabled_accounts = prefs_add_tags.add_tags_enabled_accounts;
taLog.log("add_tags_enabled_accounts = " + JSON.stringify(add_tags_enabled_accounts) + "."); taLog.log("add_tags_enabled_accounts = " + JSON.stringify(add_tags_enabled_accounts) + ".");
document.querySelectorAll('.accountCheckbox').forEach(checkbox => { document.querySelectorAll('.accountCheckbox').forEach(checkbox => {
@ -187,6 +258,7 @@ document.addEventListener('DOMContentLoaded', async () => {
checkboxes.forEach(checkbox => checkbox.checked = false); checkboxes.forEach(checkbox => checkbox.checked = false);
}); });
updateWarnings(model_prefix);
}); });
@ -218,6 +290,19 @@ async function updateAdditionalPromptStatements(){
} }
} }
async function updatePromptAPIInfo(){
let conntype = document.getElementById(conntype_select_id).value;
let model_value = conntype.substring(0, conntype.length - 4) + '_model';
let model = document.getElementById(model_prefix + model_value).value;
// console.log(">>>>>>>>>>> updatePromptAPIInfo: conntype: " + conntype + " - model: " + model + " - model_value: " + model_value);
let add_tags_prompt = await loadPrompt('prompt_add_tags');
// console.log(">>>>>>>>>>> updatePromptAPIInfo: BEFORE add_tags_prompt: " + JSON.stringify(add_tags_prompt));
add_tags_prompt.api = conntype;
add_tags_prompt.model = model;
// console.log(">>>>>>>>>>> updatePromptAPIInfo: AFTER add_tags_prompt: " + JSON.stringify(add_tags_prompt));
await savePrompt(add_tags_prompt);
}
// Methods to manage options, derived from: /options/mzta-options.js // Methods to manage options, derived from: /options/mzta-options.js
@ -225,7 +310,7 @@ function saveOptions(e) {
e.preventDefault(); e.preventDefault();
let options = {}; let options = {};
let element = e.target; let element = e.target;
// console.log(">>>>>>>>>> Saving option: " + element.id + " = " + element.value);
switch (element.type) { switch (element.type) {
case 'checkbox': case 'checkbox':
options[element.id] = element.checked; options[element.id] = element.checked;
@ -238,6 +323,7 @@ function saveOptions(e) {
options[element.id] = element.value.trim(); options[element.id] = element.value.trim();
break; break;
case 'select-one': case 'select-one':
// console.log(">>>>>>>>>> Saving option [select-one]: " + element.id + " = " + element.value);
options[element.id] = element.value; options[element.id] = element.value;
break; break;
case 'textarea': case 'textarea':
@ -256,7 +342,7 @@ function saveOptions(e) {
async function restoreOptions() { async function restoreOptions() {
function setCurrentChoice(result) { function setCurrentChoice(result) {
document.querySelectorAll(".option-input").forEach(element => { document.querySelectorAll(".option-input").forEach(element => {
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" ? "****************" : result[element.id])); taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
switch (element.type) { switch (element.type) {
case 'checkbox': case 'checkbox':
element.checked = result[element.id] || false; element.checked = result[element.id] || false;
@ -279,13 +365,20 @@ async function restoreOptions() {
break; break;
default: default:
if (element.tagName === 'SELECT') { if (element.tagName === 'SELECT') {
let default_select_value = ''; let default_select_value = '';
if(element.id == 'reply_type') default_select_value = 'reply_all'; const restoreValue = result[element.id] || default_select_value;
if(element.id == 'connection_type') default_select_value = 'chatgpt_web'; // Check if option exists
element.value = result[element.id] || default_select_value; let optionExists = Array.from(element.options).some(opt => opt.value === restoreValue);
if (element.value === '') { // If it doesn't exist and restoreValue is not empty, create it
element.selectedIndex = -1; if (!optionExists && restoreValue !== '') {
} let newOption = new Option(restoreValue, restoreValue);
element.add(newOption);
}
// Set value
element.value = restoreValue;
if (element.value === '') {
element.selectedIndex = -1;
}
}else{ }else{
console.error("[ThunderAI] Unhandled input type:", element.type); console.error("[ThunderAI] Unhandled input type:", element.type);
} }
@ -295,4 +388,4 @@ async function restoreOptions() {
let getting = await browser.storage.sync.get(prefs_default); let getting = await browser.storage.sync.get(prefs_default);
setCurrentChoice(getting); setCurrentChoice(getting);
} }

View file

@ -21,6 +21,7 @@ import { taLogger } from '../../js/mzta-logger.js';
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js"; import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js";
import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js";
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
import { isAPIKeyValue } from "../../js/mzta-utils.js";
let autocompleteSuggestions = []; let autocompleteSuggestions = [];
let taLog = new taLogger("mzta-get-calendar-event-page",true); let taLog = new taLogger("mzta-get-calendar-event-page",true);
@ -110,7 +111,7 @@ function saveOptions(e) {
async function restoreOptions() { async function restoreOptions() {
function setCurrentChoice(result) { function setCurrentChoice(result) {
document.querySelectorAll(".option-input").forEach(element => { document.querySelectorAll(".option-input").forEach(element => {
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" ? "****************" : result[element.id])); taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
switch (element.type) { switch (element.type) {
case 'checkbox': case 'checkbox':
element.checked = result[element.id] || false; element.checked = result[element.id] || false;

View file

@ -21,6 +21,7 @@ import { taLogger } from '../../js/mzta-logger.js';
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js"; import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js";
import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js";
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
import { isAPIKeyValue } from "../../js/mzta-utils.js";
let autocompleteSuggestions = []; let autocompleteSuggestions = [];
let taLog = new taLogger("mzta-get-calendar-event-page",true); let taLog = new taLogger("mzta-get-calendar-event-page",true);
@ -110,7 +111,7 @@ function saveOptions(e) {
async function restoreOptions() { async function restoreOptions() {
function setCurrentChoice(result) { function setCurrentChoice(result) {
document.querySelectorAll(".option-input").forEach(element => { document.querySelectorAll(".option-input").forEach(element => {
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" ? "****************" : result[element.id])); taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
switch (element.type) { switch (element.type) {
case 'checkbox': case 'checkbox':
element.checked = result[element.id] || false; element.checked = result[element.id] || false;

View file

@ -46,6 +46,7 @@ table#miczPrefs {
.section_title{ .section_title{
font-weight: bold; font-weight: bold;
font-size: 1.2em;
} }
table#miczPrefs td{ table#miczPrefs td{

View file

@ -4,6 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>ThunderAI - __MSG_SpamFilter_PageTitle__</title> <title>ThunderAI - __MSG_SpamFilter_PageTitle__</title>
<link rel="stylesheet" href="mzta-spamfilter.css"> <link rel="stylesheet" href="mzta-spamfilter.css">
<link rel="stylesheet" href="../_lib/connection-ui.css">
<link rel="icon" href="../../images/icon-16px.png"> <link rel="icon" href="../../images/icon-16px.png">
</head> </head>
<body> <body>
@ -13,8 +14,20 @@
</div> </div>
<div class="spamfilter_table_title section_title">__MSG_SpamFilter_prompt_prefs_title__</div> <div class="spamfilter_table_title section_title">__MSG_SpamFilter_prompt_prefs_title__</div>
<table id="miczPrefs"> <table id="miczPrefs">
<tr class="spamfilter_tr specific_integration">
<td><span class="opt_title">__MSG_prefs_OptionText_use_specific_integration__</span>
</td>
<td>
<label>
<input type="checkbox" id="spamfilter_use_specific_integration" name="spamfilter_use_specific_integration" class="option-input" />
__MSG_prefs_OptionText_spamfilter_use_specific_integration_Info__
</label>
</td>
</tr>
<tr id="connection_ui_anchor"></tr>
<tr id="connection_ui_end"><td colspan="2"></td></tr>
<tr class="spamfilter_tr"> <tr class="spamfilter_tr">
<td><span>__MSG_prefs_OptionText_spamfilter_threshold__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_spamfilter_threshold__</span></td>
<td> <td>
<label> <label>
<input type="number" id="spamfilter_threshold" name="spamfilter_threshold" min="0" max="100" class="option-input" /><span id="spamfilter_threshold_too_low">__MSG_spamfilter_threshold_too_low__</span> <input type="number" id="spamfilter_threshold" name="spamfilter_threshold" min="0" max="100" class="option-input" /><span id="spamfilter_threshold_too_low">__MSG_spamfilter_threshold_too_low__</span>
@ -23,7 +36,7 @@
</td> </td>
</tr> </tr>
<tr class="spamfilter_tr"> <tr class="spamfilter_tr">
<td><span>__MSG_prefs_OptionText_spamfilter_context_menu__</span></td> <td><span class="opt_title">__MSG_prefs_OptionText_spamfilter_context_menu__</span></td>
<td> <td>
<label> <label>
<input type="checkbox" id="spamfilter_context_menu" name="spamfilter_context_menu" class="option-input" /> <input type="checkbox" id="spamfilter_context_menu" name="spamfilter_context_menu" class="option-input" />
@ -74,4 +87,4 @@
<script src="mzta-spamfilter.js" type="module"></script> <script src="mzta-spamfilter.js" type="module"></script>
<script src="../../js/mzta-i18n.js"></script> <script src="../../js/mzta-i18n.js"></script>
</body> </body>
</html> </html>

View file

@ -18,18 +18,39 @@
import { prefs_default } from '../../options/mzta-options-default.js'; import { prefs_default } from '../../options/mzta-options-default.js';
import { taLogger } from '../../js/mzta-logger.js'; import { taLogger } from '../../js/mzta-logger.js';
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js"; import { getSpecialPrompts, setSpecialPrompts, loadPrompt, savePrompt, clearPromptAPI } from "../../js/mzta-prompts.js";
import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js";
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
import { taSpamReport } from '../../js/mzta-spamreport.js'; import { taSpamReport } from '../../js/mzta-spamreport.js';
import { getAccountsList } from "../../js/mzta-utils.js"; import { getAccountsList, isAPIKeyValue } from "../../js/mzta-utils.js";
import {
injectConnectionUI,
updateWarnings,
changeConnTypeRowColor
} from "../_lib/connection-ui.js";
let autocompleteSuggestions = []; let autocompleteSuggestions = [];
let taLog = new taLogger("mzta-spamfilter-page",true); let taLog = new taLogger("mzta-spamfilter-page",true);
taSpamReport.logger = taLog; taSpamReport.logger = taLog;
let conntype_select_id = 'spamfilter_connection_type';
let model_prefix = 'spamfilter_';
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
try {
await injectConnectionUI({
afterTrId: 'connection_ui_anchor',
tr_class: 'specific_integration_sub',
selectId: conntype_select_id,
modelId_prefix: model_prefix,
no_chatgpt_web: true,
taLog: taLog
});
} catch (e) {
console.error('Failed to inject connection UI (spamfilter)', e);
}
i18n.updateDocument(); i18n.updateDocument();
await restoreOptions(); await restoreOptions();
@ -40,6 +61,48 @@ document.addEventListener('DOMContentLoaded', async () => {
document.getElementById("spamfilter_threshold").addEventListener("input", check_spamfilter_threshold); document.getElementById("spamfilter_threshold").addEventListener("input", check_spamfilter_threshold);
check_spamfilter_threshold({target: document.getElementById("spamfilter_threshold")}); check_spamfilter_threshold({target: document.getElementById("spamfilter_threshold")});
// Bind prompt API updates to connection type and model selects
document.querySelectorAll(".option-input-model").forEach(element => {
element.addEventListener("change", updatePromptAPIInfo);
});
const conntype_el = document.getElementById(conntype_select_id);
if (conntype_el) {
conntype_el.addEventListener('change', updatePromptAPIInfo);
const conntype_row = document.getElementById(conntype_select_id + '_tr');
if (conntype_row) changeConnTypeRowColor(conntype_row, conntype_el);
}
// Specific integration toggle behavior
const spamfilter_use_specific_integration_el = document.getElementById('spamfilter_use_specific_integration');
let prefs_spamfilter_init = await browser.storage.sync.get({ spamfilter_enabled_accounts: [], connection_type: 'chatgpt_web' });
if(prefs_spamfilter_init.connection_type == 'chatgpt_web'){
spamfilter_use_specific_integration_el.checked = true;
spamfilter_use_specific_integration_el.dispatchEvent(new Event('change'));
spamfilter_use_specific_integration_el.disabled = true;
}
const conntype_end_el = document.getElementById('connection_ui_end');
const conntype_row = document.getElementById(conntype_select_id + '_tr');
spamfilter_use_specific_integration_el.addEventListener('change', async (event) => {
document.querySelectorAll('.specific_integration_sub').forEach(tr => {
tr.style.display = event.target.checked && tr.classList.contains('conntype_' + conntype_el.value) ? 'table-row' : 'none';
});
if (conntype_row) conntype_row.style.display = event.target.checked ? 'table-row' : 'none';
if (conntype_end_el) conntype_end_el.style.display = event.target.checked ? 'table-row' : 'none';
if(!event.target.checked){
await clearPromptAPI('prompt_spamfilter');
}else{
updatePromptAPIInfo();
}
if (conntype_row) changeConnTypeRowColor(conntype_row, conntype_el);
});
// Initialize visibility per current toggle value
document.querySelectorAll('.specific_integration_sub').forEach(tr => {
tr.style.display = spamfilter_use_specific_integration_el.checked && tr.classList.contains('conntype_' + conntype_el.value) ? 'table-row' : 'none';
});
if (conntype_row) conntype_row.style.display = spamfilter_use_specific_integration_el.checked ? 'table-row' : 'none';
if (conntype_end_el) conntype_end_el.style.display = spamfilter_use_specific_integration_el.checked ? 'table-row' : 'none';
let spamfilter_textarea = document.getElementById('spamfilter_prompt_text'); let spamfilter_textarea = document.getElementById('spamfilter_prompt_text');
let spamfilter_save_btn = document.getElementById('btn_save_prompt'); let spamfilter_save_btn = document.getElementById('btn_save_prompt');
let spamfilter_reset_btn = document.getElementById('btn_reset_prompt'); let spamfilter_reset_btn = document.getElementById('btn_reset_prompt');
@ -136,6 +199,9 @@ document.addEventListener('DOMContentLoaded', async () => {
}); });
loadSpamReport(); loadSpamReport();
updateWarnings(model_prefix);
// Sync prompt API/model once on load
updatePromptAPIInfo();
}); });
function check_spamfilter_threshold(event) { function check_spamfilter_threshold(event) {
@ -165,6 +231,21 @@ async function loadSpamReport(){
} }
} }
async function updatePromptAPIInfo(){
const conntypeEl = document.getElementById(conntype_select_id);
if (!conntypeEl || !conntypeEl.value) return;
const conntype = conntypeEl.value;
const model_value = conntype.substring(0, conntype.length - 4) + '_model';
const modelEl = document.getElementById(model_prefix + model_value);
if (!modelEl) return;
const model = modelEl.value;
let spamfilter_prompt = await loadPrompt('prompt_spamfilter');
if (!spamfilter_prompt) return;
spamfilter_prompt.api = conntype;
spamfilter_prompt.model = model;
await savePrompt(spamfilter_prompt);
}
// Function to populate the table // Function to populate the table
function populateTable(data) { function populateTable(data) {
const tableBody = document.getElementById("report_data_body"); const tableBody = document.getElementById("report_data_body");
@ -228,13 +309,16 @@ function saveOptions(e) {
case 'number': case 'number':
options[element.id] = element.valueAsNumber; options[element.id] = element.valueAsNumber;
break; break;
case 'text': case 'text':
case 'password': case 'password':
options[element.id] = element.value.trim(); options[element.id] = element.value.trim();
break; break;
case 'select-one': case 'select-one':
options[element.id] = element.value; options[element.id] = element.value;
break; break;
case 'textarea':
options[element.id] = element.value;
break;
default: default:
console.error("[ThunderAI] Unhandled input type:", element.type); console.error("[ThunderAI] Unhandled input type:", element.type);
} }
@ -245,7 +329,7 @@ function saveOptions(e) {
async function restoreOptions() { async function restoreOptions() {
function setCurrentChoice(result) { function setCurrentChoice(result) {
document.querySelectorAll(".option-input").forEach(element => { document.querySelectorAll(".option-input").forEach(element => {
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" ? "****************" : result[element.id])); taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
switch (element.type) { switch (element.type) {
case 'checkbox': case 'checkbox':
element.checked = result[element.id] || false; element.checked = result[element.id] || false;
@ -257,6 +341,7 @@ async function restoreOptions() {
element.value = result[element.id] ?? default_number_value; element.value = result[element.id] ?? default_number_value;
break; break;
case 'text': case 'text':
case 'textarea':
case 'password': case 'password':
let default_text_value = ''; let default_text_value = '';
if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang; if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang;
@ -267,7 +352,15 @@ async function restoreOptions() {
let default_select_value = ''; let default_select_value = '';
if(element.id == 'reply_type') default_select_value = 'reply_all'; if(element.id == 'reply_type') default_select_value = 'reply_all';
if(element.id == 'connection_type') default_select_value = 'chatgpt_web'; if(element.id == 'connection_type') default_select_value = 'chatgpt_web';
element.value = result[element.id] || default_select_value; if(element.id == 'spamfilter_connection_type') default_select_value = 'chatgpt_api';
const restoreValue = result[element.id] || default_select_value;
// Ensure option exists before restoring
let optionExists = Array.from(element.options).some(opt => opt.value === restoreValue);
if (!optionExists && restoreValue !== '') {
let newOption = new Option(restoreValue, restoreValue);
element.add(newOption);
}
element.value = restoreValue;
if (element.value === '') { if (element.value === '') {
element.selectedIndex = -1; element.selectedIndex = -1;
} }
@ -280,4 +373,4 @@ async function restoreOptions() {
let getting = await browser.storage.sync.get(prefs_default); let getting = await browser.storage.sync.get(prefs_default);
setCurrentChoice(getting); setCurrentChoice(getting);
} }