add customizable model options for summarize
This commit is contained in:
parent
c3e27f0356
commit
3d2c2b9320
4 changed files with 270 additions and 35 deletions
|
|
@ -1003,6 +1003,10 @@
|
|||
"message": "Extract all relevant details required to generate a calendar event from the following text. The extracted information should include:\n- Event Title\n- Start Date and Time (including timezone, if specified)\n- End Date and Time (including timezone, if specified)\n- Full day (if mentioned)\n- Attendees\nEnsure the data is formatted clearly and consistently so that it can be directly used for creating a calendar event.\nIf there are relative time references, consider that the date and time of the email are \"{%mail_datetime%}\". Calculate the start date and time based on this reference. If the calculated start date and time are earlier than \"{%current_datetime%}\", recalculate the start date and time using \"{%current_datetime%}\" as the base.\nIf the duration is not specified, set it to one hour.\nThese are the attendees: {%author%}, {%recipients%}, {%cc_list%}. If present, exclude my address: {%account_email_address%}.\nIf you're not able to get one or more of the required information, please respond with an empty string.\nGenerate a response in JSON format only. Do not include any additional text or explanations; provide only the JSON. Here is the format to be used:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Calendar event summary here\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHere's the text:\"{%selected_text%}\"",
|
||||
"description": ""
|
||||
},
|
||||
"Summarize_prompt_prefs_title": {
|
||||
"message": "Add Summarization Options",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_summarize": {
|
||||
"message": "Summarize this email or these emails",
|
||||
"description": ""
|
||||
|
|
@ -1215,6 +1219,10 @@
|
|||
"message": "Summarize mail",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_summarize_use_specific_integration_Info": {
|
||||
"message": "If checked, the Model and API specified below will be used for summarizing email(s), regardless the one choosen in the ThunderAI options page.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_summarize_Info": {
|
||||
"message": "If checked, adds an option to context menu to summarize mail.",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -16,6 +16,49 @@
|
|||
font-style: italic;
|
||||
}
|
||||
|
||||
#account_selector_container{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#account_selector_checkboxes{
|
||||
padding: 10px;
|
||||
border: 1px solid gray;
|
||||
width: 24em;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.specific_integration{
|
||||
background-color: #dfeaff;
|
||||
}
|
||||
|
||||
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 {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
|
@ -30,6 +73,11 @@ table#miczPrefs {
|
|||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.addtags_table_title{
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.section_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
@ -90,27 +138,21 @@ table#miczPrefs tr:last-child td {
|
|||
color: red;
|
||||
}
|
||||
|
||||
label:has(input[type="checkbox"]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #1c1b22;
|
||||
color: rgb(251, 251, 254);
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #409eff;
|
||||
}
|
||||
a:visited {
|
||||
color: #409eff;
|
||||
}
|
||||
a:hover {
|
||||
color: #66b1ff;
|
||||
}
|
||||
a:active {
|
||||
color: #66b1ff;
|
||||
}
|
||||
a:active {
|
||||
color: #66b1ff;
|
||||
}
|
||||
a:link { color: #409eff; }
|
||||
a:visited { color: #409eff; }
|
||||
a:hover { color: #66b1ff; }
|
||||
a:active { color: #66b1ff; }
|
||||
a:active { color: #66b1ff; }
|
||||
|
||||
.autocomplete-list {
|
||||
background-color: #2e2f36;
|
||||
|
|
@ -124,4 +166,24 @@ table#miczPrefs tr:last-child td {
|
|||
.autocomplete-list li.active {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
|
||||
.summarize_auto{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,29 @@
|
|||
<meta charset="UTF-8" />
|
||||
<title>ThunderAI - __MSG_Summarize_PageTitle__</title>
|
||||
<link rel="stylesheet" href="mzta-summarize.css" />
|
||||
<link rel="stylesheet" href="../_lib/connection-ui.css">
|
||||
<link rel="icon" href="../../images/icon-16px.png" />
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1 class="page_title">__MSG_Summarize_PageTitle__</h1>
|
||||
<p>__MSG_Summarize_info_default__</p>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="page_title">__MSG_Summarize_PageTitle__</h1>
|
||||
<p>__MSG_Summarize_info_default__</p>
|
||||
</div>
|
||||
<div class="summarize_table_title section_title">__MSG_Summarize_prompt_prefs_title__</div>
|
||||
<table id="miczPrefs">
|
||||
<tr class="summarize_tr specific_integration">
|
||||
<td><span class="opt_title">__MSG_prefs_OptionText_use_specific_integration__</span>
|
||||
</td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="summarize_use_specific_integration" name="summarize_use_specific_integration" class="option-input" />
|
||||
__MSG_prefs_OptionText_summarize_use_specific_integration_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="connection_ui_anchor"></tr>
|
||||
<tr id="connection_ui_end"><td colspan="2"></td></tr>
|
||||
</table>
|
||||
<div id="summarize_prompt_container">
|
||||
<!--title and description-->
|
||||
<span class="section_title">
|
||||
|
|
|
|||
|
|
@ -16,29 +16,71 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { prefs_default, integration_options_config } from '../../options/mzta-options-default.js';
|
||||
import { taLogger } from "../../js/mzta-logger.js";
|
||||
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js";
|
||||
import { getPlaceholders } from "../../js/mzta-placeholders.js";
|
||||
import {
|
||||
getSpecialPrompts,
|
||||
setSpecialPrompts
|
||||
} from "../../js/mzta-prompts.js";
|
||||
import {
|
||||
getPlaceholders,
|
||||
mapPlaceholderToSuggestion
|
||||
} from "../../js/mzta-placeholders.js";
|
||||
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
|
||||
import {
|
||||
getAccountsList,
|
||||
normalizeStringList,
|
||||
isAPIKeyValue
|
||||
} from "../../js/mzta-utils.js";
|
||||
import {
|
||||
initializeSpecificIntegrationUI
|
||||
} from "../_lib/connection-ui.js";
|
||||
|
||||
let autocompleteSuggestions = [];
|
||||
let taLog = new taLogger("mzta-summarize-page", true);
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
|
||||
i18n.updateDocument();
|
||||
|
||||
|
||||
const summarize_textarea = document.getElementById("summarize_prompt_text");
|
||||
const summarize_save_btn = document.getElementById("btn_save_prompt");
|
||||
const summarize_reset_btn = document.getElementById("btn_reset_prompt");
|
||||
const summarize_textarea_email_template = document.getElementById("summarize_email_template_text");
|
||||
const summarize_reset_email_template_btn = document.getElementById("btn_reset_email_template");
|
||||
const summarize_save_email_template_btn = document.getElementById("btn_save_email_template");
|
||||
|
||||
let specialPrompts = await getSpecialPrompts();
|
||||
let summarize_prompt = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize');
|
||||
let summarize_email_template = specialPrompts.find((prompt) => prompt.id === 'prompt_summarize_email_template');
|
||||
|
||||
if (summarize_prompt && summarize_prompt.api_type && summarize_prompt.api_type !== '') {
|
||||
let update_prefs = {};
|
||||
update_prefs['summarize_connection_type'] = summarize_prompt.api_type;
|
||||
|
||||
let integration = summarize_prompt.api_type.replace('_api', '');
|
||||
if (integration_options_config && integration_options_config[integration]) {
|
||||
for (const key of Object.keys(integration_options_config[integration])) {
|
||||
if (summarize_prompt[key] !== undefined) {
|
||||
update_prefs[`summarize_${integration}_${key}`] = summarize_prompt[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
await browser.storage.sync.set(update_prefs);
|
||||
}
|
||||
|
||||
await initializeSpecificIntegrationUI({
|
||||
prefix: 'summarize',
|
||||
promptId: 'prompt_summarize',
|
||||
taLog: taLog,
|
||||
restoreOptionsCallback: restoreOptions
|
||||
});
|
||||
|
||||
i18n.updateDocument();
|
||||
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
element.addEventListener("change", saveOptions);
|
||||
});
|
||||
let prefs_summarize = await browser.storage.sync.get({ summarize_enabled_accounts: [], connection_type: 'chatgpt_web' });
|
||||
|
||||
let summarize_textarea = document.getElementById("summarize_prompt_text");
|
||||
let summarize_save_btn = document.getElementById("btn_save_prompt");
|
||||
let summarize_reset_btn = document.getElementById("btn_reset_prompt");
|
||||
let summarize_textarea_email_template = document.getElementById("summarize_email_template_text");
|
||||
let summarize_reset_email_template_btn = document.getElementById("btn_reset_email_template");
|
||||
let summarize_save_email_template_btn = document.getElementById("btn_save_email_template");
|
||||
|
||||
|
||||
summarize_textarea.addEventListener("input", (event) => {
|
||||
summarize_reset_btn.disabled = (event.target.value === browser.i18n.getMessage('prompt_summarize_full_text'));
|
||||
|
|
@ -84,16 +126,123 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
if(summarize_email_template === 'prompt_summarize_email_template'){
|
||||
summarize_email_template.text = browser.i18n.getMessage(summarize_email_template.text);
|
||||
}
|
||||
|
||||
summarize_textarea_email_template.value = summarize_email_template.text;
|
||||
summarize_reset_email_template_btn.disabled = (summarize_email_template.value === browser.i18n.getMessage("prompt_summarize_email_template"));
|
||||
|
||||
summarize_textarea.value = summarize_prompt.text;
|
||||
summarize_reset_btn.disabled = (summarize_textarea.value === browser.i18n.getMessage("prompt_summarize_full_text"));
|
||||
|
||||
|
||||
autocompleteSuggestions = (await getPlaceholders(true))
|
||||
.filter((p) => p.id !== "additional_text")
|
||||
.map((p) => ({ command: `{%${p.id}%}`, type: p.type }));
|
||||
.map(mapPlaceholderToSuggestion);
|
||||
textareaAutocomplete(summarize_textarea, autocompleteSuggestions, 1);
|
||||
textareaAutocomplete(summarize_textarea_email_template, autocompleteSuggestions, 1);
|
||||
|
||||
});
|
||||
|
||||
// Methods to manage options, derived from: /options/mzta-options.js
|
||||
|
||||
function saveOptions(e) {
|
||||
e.preventDefault();
|
||||
let options = {};
|
||||
let element = e.target;
|
||||
// console.log(">>>>>>>>>> Saving option: " + element.id + " = " + element.value);
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
options[element.id] = element.checked;
|
||||
break;
|
||||
case 'number':
|
||||
options[element.id] = element.valueAsNumber;
|
||||
break;
|
||||
case 'text':
|
||||
case 'password':
|
||||
options[element.id] = element.value.trim();
|
||||
break;
|
||||
case 'select-one':
|
||||
// console.log(">>>>>>>>>> Saving option [select-one]: " + element.id + " = " + element.value);
|
||||
options[element.id] = element.value;
|
||||
break;
|
||||
case 'textarea':
|
||||
if(element.id === 'add_tags_auto_uselist_list') {
|
||||
element.value = normalizeStringList(element.value, 1);
|
||||
}
|
||||
options[element.id] = normalizeStringList(element.value);
|
||||
break;
|
||||
default:
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
}
|
||||
|
||||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
element.checked = result[element.id] || false;
|
||||
break;
|
||||
case 'number':
|
||||
let default_number_value = 0;
|
||||
if(element.id == 'chatgpt_win_height') default_number_value = prefs_default.chatgpt_win_height;
|
||||
if(element.id == 'chatgpt_win_width') default_number_value = prefs_default.chatgpt_win_width;
|
||||
element.value = result[element.id] ?? default_number_value;
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
case 'password':
|
||||
let default_text_value = '';
|
||||
if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang;
|
||||
if(element.id === 'add_tags_auto_uselist_list') {
|
||||
result[element.id] = normalizeStringList(result[element.id], 1);
|
||||
}
|
||||
element.value = result[element.id] || default_text_value;
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
let default_select_value = '';
|
||||
const restoreValue = result[element.id] || default_select_value;
|
||||
// Check if option exists
|
||||
let optionExists = Array.from(element.options).some(opt => opt.value === restoreValue);
|
||||
// If it doesn't exist and restoreValue is not empty, create it
|
||||
if (!optionExists && restoreValue !== '') {
|
||||
let newOption = new Option(restoreValue, restoreValue);
|
||||
element.add(newOption);
|
||||
}
|
||||
// Set value
|
||||
element.value = restoreValue;
|
||||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let getting = await browser.storage.sync.get(prefs_default);
|
||||
|
||||
let specialPrompts = await getSpecialPrompts();
|
||||
let addtags_prompt = specialPrompts.find(prompt => prompt.id === 'prompt_add_tags');
|
||||
|
||||
if (addtags_prompt) {
|
||||
if (addtags_prompt.api_type && addtags_prompt.api_type !== '') {
|
||||
getting['add_tags_connection_type'] = addtags_prompt.api_type;
|
||||
} else {
|
||||
getting['add_tags_connection_type'] = getting['connection_type'];
|
||||
}
|
||||
for (const [integration, options] of Object.entries(integration_options_config)) {
|
||||
for (const key of Object.keys(options)) {
|
||||
const propName = `${integration}_${key}`;
|
||||
if (addtags_prompt[propName] !== undefined && addtags_prompt[propName] !== '') {
|
||||
getting[`add_tags_${propName}`] = addtags_prompt[propName];
|
||||
} else {
|
||||
getting[`add_tags_${propName}`] = getting[propName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentChoice(getting);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue