correctly using the ai webchat if the relative option is configured accordingly. see #580

This commit is contained in:
mic 2026-03-25 23:43:48 +01:00
parent 8a0e6e5cae
commit 3cb1fb0972
5 changed files with 95 additions and 13 deletions

View file

@ -235,6 +235,10 @@
"message": "Close", "message": "Close",
"description": "" "description": ""
}, },
"webchat_save_as_summary": {
"message": "Save as Summary",
"description": "Button label in the webchat window to save the AI response as a message summary"
},
"chatgpt_textarea_not_found_error": { "chatgpt_textarea_not_found_error": {
"message": "It seems that the ChatGPT page is taking too long to load. If it finishes loading, click the button on the right. If the problem persists, please check the service status.", "message": "It seems that the ChatGPT page is taking too long to load. If it finishes loading, click the button on the right. If the problem persists, please check the service status.",
"description": "" "description": ""
@ -1388,17 +1392,13 @@
"description": "" "description": ""
}, },
"spamfilter_no_reports": { "spamfilter_no_reports": {
"message": "No messages have screened for spam yet. Here you'll find a list of the last 100 spam reports for the current session only.", "message": "No messages have screened for spam yet. Here you'll find a list of the last 100 spam reports.",
"description": "" "description": ""
}, },
"SpamReport_Title": { "SpamReport_Title": {
"message": "Spam Filter Reports", "message": "Spam Filter Reports",
"description": "" "description": ""
}, },
"SpamReport_infoline": {
"message": "This information is saved only for the current session.",
"description": ""
},
"Date": { "Date": {
"message": "Date", "message": "Date",
"description": "" "description": ""

View file

@ -454,6 +454,29 @@ class MessagesArea extends HTMLElement {
selectionInfo.style.display = "block"; // show selection info selectionInfo.style.display = "block"; // show selection info
} }
// Save as Summary button (only shown for summary webchat sessions)
if(promptData.prompt_info?.headerMessageId) {
const saveSummaryButton = document.createElement('button');
saveSummaryButton.textContent = browser.i18n.getMessage("webchat_save_as_summary");
saveSummaryButton.classList.add('action_btn');
saveSummaryButton.addEventListener('click', async () => {
let finalText = removeAloneBRs(fullTextHTMLAtAssignment);
const selectedHTML = this.getCurrentSelectionHTML();
if(selectedHTML != "") {
finalText = removeAloneBRs(selectedHTML);
}
await browser.runtime.sendMessage({
command: "chatgpt_saveSummary",
text: finalText,
headerMessageId: promptData.prompt_info.headerMessageId,
tabId: promptData.prompt_info.summaryTabId || promptData.tabId,
});
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
});
actionButtons.appendChild(saveSummaryButton);
selectionInfo.style.display = "block";
}
// diff viewer button // diff viewer button
if(promptData.prompt_info?.use_diff_viewer == "1") { if(promptData.prompt_info?.use_diff_viewer == "1") {
const diffvButton = document.createElement('button'); const diffvButton = document.createElement('button');

View file

@ -52,6 +52,16 @@
0: Do not use the diff viewer 0: Do not use the diff viewer
1: Use the diff viewer 1: Use the diff viewer
================ DYNAMIC PROPERTIES (set at runtime via prompt_info)
headerMessageId (set by _openSummaryWebchat in mzta-background.js):
When present, the webchat UI shows a "Save as Summary" button to capture
the AI response and save it as an inline summary for the message identified
by this headerMessageId.
summaryTabId (set by _openSummaryWebchat in mzta-background.js):
The tab ID of the message display tab to update with the saved summary.
================ USER PROPERTIES ================ USER PROPERTIES
Enabled (enabled attribute): Enabled (enabled attribute):
0: Disabled 0: Disabled

View file

@ -282,13 +282,45 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
async function _refreshSummary(message) { async function _refreshSummary(message) {
let tabId = sender.tab.id; let tabId = sender.tab.id;
await summaryStore.removeSummary(message.headerMessageId); await summaryStore.removeSummary(message.headerMessageId);
let prefs_refresh = await browser.storage.sync.get({ summarize_display_mode: prefs_default.summarize_display_mode });
if (prefs_refresh.summarize_display_mode === 'webchat') {
await _openSummaryWebchat(message.headerMessageId, tabId);
} else {
await _generateSummaryForMessage(message.headerMessageId, tabId); await _generateSummaryForMessage(message.headerMessageId, tabId);
} }
}
_refreshSummary(message); _refreshSummary(message);
break; break;
case 'removeSummary': case 'removeSummary':
summaryStore.removeSummary(message.headerMessageId); summaryStore.removeSummary(message.headerMessageId);
break; break;
case 'chatgpt_saveSummary':
async function _saveSummaryFromWebchat(msg) {
try {
let cleanedSummary = cleanSummaryText(msg.text);
const summaryData = {
summary: cleanedSummary,
summary_date: new Date(),
headerMessageId: msg.headerMessageId
};
await summaryStore.saveSummary(summaryData, msg.headerMessageId);
let prefs_summary = await browser.storage.sync.get({
summarize_max_display_length: prefs_default.summarize_max_display_length
});
try {
browser.tabs.sendMessage(msg.tabId, {
command: "showSummary",
data: { ...summaryData, maxDisplayLength: prefs_summary.summarize_max_display_length }
});
} catch (e) {
taLog.error("Error sending showSummary to tab: " + e);
}
} catch (error) {
console.error("[ThunderAI] Error saving summary from webchat:", error);
}
}
_saveSummaryFromWebchat(message);
break;
// case 'chatgpt_open': // case 'chatgpt_open':
// openChatGPT(message.prompt,message.action,message.tabId); // openChatGPT(message.prompt,message.action,message.tabId);
// return true; // return true;
@ -458,6 +490,17 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
return false; return false;
}); });
// Clean summary text by stripping HTML, markdown, and formatting artifacts.
// Used by both inline summary generation and webchat summary save.
function cleanSummaryText(text) {
let cleaned = text.replace(/<\/?[^>]+(>|$)/g, ''); // strip HTML tags
cleaned = cleaned.replace(/```[\s\S]*?```/g, '');
cleaned = cleaned.replace(/[\*#_~`]/g, '');
cleaned = cleaned.replace(/\s+/g, ' ').trim();
cleaned = cleaned.replace(/^Summary:\s*/i, '');
return cleaned;
}
async function _generateSummaryForMessage(headerMessageId, tabId) { async function _generateSummaryForMessage(headerMessageId, tabId) {
try { try {
let prefs = await browser.storage.sync.get({ let prefs = await browser.storage.sync.get({
@ -514,10 +557,7 @@ async function _generateSummaryForMessage(headerMessageId, tabId) {
await cmd.initWorker(); await cmd.initWorker();
const aiResponse = await cmd.sendPrompt(); const aiResponse = await cmd.sendPrompt();
let cleanedSummary = aiResponse.replace(/```[\s\S]*?```/g, ''); let cleanedSummary = cleanSummaryText(aiResponse);
cleanedSummary = cleanedSummary.replace(/[\*#_~`]/g, '');
cleanedSummary = cleanedSummary.replace(/\s+/g, ' ').trim();
cleanedSummary = cleanedSummary.replace(/^Summary:\s*/i, '');
const summaryData = { const summaryData = {
summary: cleanedSummary, summary: cleanedSummary,
@ -665,7 +705,17 @@ async function _openSummaryWebchat(headerMessageId, tabId) {
const curr_message = messageResult.messages[0]; const curr_message = messageResult.messages[0];
const curr_message_full = await browser.messages.getFull(curr_message.id); const curr_message_full = await browser.messages.getFull(curr_message.id);
const connectionType = getConnectionType(await browser.storage.sync.get(prefs_default), {}, 'summarize');
if (connectionType === 'chatgpt_web') {
const errorMsg = browser.i18n.getMessage('summarize_chatgpt_web_not_supported');
await summaryStore.saveError(headerMessageId, errorMsg);
browser.tabs.sendMessage(tabId, { command: "showSummary", data: { error: true, message: errorMsg } });
return;
}
const { promptText, promptInfo } = await taPromptUtils.buildSummaryPrompt([{ message: curr_message, fullMessage: curr_message_full }]); const { promptText, promptInfo } = await taPromptUtils.buildSummaryPrompt([{ message: curr_message, fullMessage: curr_message_full }]);
promptInfo.headerMessageId = headerMessageId;
promptInfo.summaryTabId = tabId;
openChatGPT(promptText, promptInfo.action, tabId, promptInfo.name, promptInfo.need_custom_text, promptInfo); openChatGPT(promptText, promptInfo.action, tabId, promptInfo.name, promptInfo.need_custom_text, promptInfo);
} catch (error) { } catch (error) {

View file

@ -66,8 +66,7 @@
<button type="button" id="accounts_deselect_all">__MSG_DeselectAll__</button> <button type="button" id="accounts_deselect_all">__MSG_DeselectAll__</button>
</div> </div>
<div id="spamfitler_reports_container"> <div id="spamfitler_reports_container">
<div><span class="section_title">__MSG_SpamReport_Title__</span> <div><span class="section_title">__MSG_SpamReport_Title__</span></div>
<br><span class="infoline">__MSG_SpamReport_infoline__</span></div>
<table id="report_data"> <table id="report_data">
<thead> <thead>
<tr> <tr>