Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
c622c07c66 Supporting v140+
After testing in Betterbird v140, updating manifest.
2025-08-18 19:39:35 -05:00
33003365fb
Merge pull request #111 from wagesj45/codex/capture-unaltered-message-body-in-background.js
Capture raw email text for debug view
2025-07-19 22:51:24 -05:00
9cad2674e3 Capture raw message text for debug 2025-07-19 22:44:04 -05:00
d3ee2f128f
Merge pull request #110 from wagesj45/codex/reorganize-debug-options-and-improve-diff-display
Fix debug tab controls
2025-07-19 21:58:50 -05:00
3 changed files with 29 additions and 8 deletions

View file

@ -16,7 +16,7 @@ message meets a specified criterion.
- **Advanced parameters** tune generation settings like temperature, topp and more from the options page.
- **Markdown conversion** optionally convert HTML bodies to Markdown before sending them to the AI service.
- **Debug logging** optional colorized logs help troubleshoot interactions with the AI service.
- **Debug tab** view the last request payload and message diff with live updates.
- **Debug tab** view the last request payload and a diff between the unaltered message text and the final prompt.
- **Light/Dark themes** automatically match Thunderbird's appearance with optional manual override.
- **Automatic rules** create rules that tag, move, copy, forward, reply, delete, archive, mark read/unread or flag/unflag messages based on AI classification. Rules can optionally apply only to unread messages and can ignore messages outside a chosen age range.
- **Rule ordering** drag rules to prioritize them and optionally stop processing after a match.

View file

@ -210,17 +210,38 @@ function collectText(part, bodyParts, attachments) {
}
}
function buildEmailText(full) {
function collectRawText(part, bodyParts, attachments) {
if (part.parts && part.parts.length) {
for (const p of part.parts) collectRawText(p, bodyParts, attachments);
return;
}
const ct = (part.contentType || "text/plain").toLowerCase();
const cd = (part.headers?.["content-disposition"]?.[0] || "").toLowerCase();
const body = String(part.body || "");
if (cd.includes("attachment") || !ct.startsWith("text/")) {
const nameMatch = /filename\s*=\s*"?([^";]+)/i.exec(cd) || /name\s*=\s*"?([^";]+)/i.exec(part.headers?.["content-type"]?.[0] || "");
const name = nameMatch ? nameMatch[1] : "";
attachments.push(`${name} (${ct}, ${part.size || byteSize(body)} bytes)`);
} else if (ct.startsWith("text/html")) {
const doc = new DOMParser().parseFromString(body, 'text/html');
bodyParts.push(doc.body.textContent || "");
} else {
bodyParts.push(body);
}
}
function buildEmailText(full, applyTransforms = true) {
const bodyParts = [];
const attachments = [];
collectText(full, bodyParts, attachments);
const collect = applyTransforms ? collectText : collectRawText;
collect(full, bodyParts, attachments);
const headers = Object.entries(full.headers || {})
.map(([k, v]) => `${k}: ${v.join(' ')}`)
.join('\n');
const attachInfo = `Attachments: ${attachments.length}` +
(attachments.length ? "\n" + attachments.map(a => ` - ${a}`).join('\n') : "");
let combined = `${headers}\n${attachInfo}\n\n${bodyParts.join('\n')}`.trim();
if (tokenReduction) {
if (applyTransforms && tokenReduction) {
const seen = new Set();
combined = combined.split('\n').filter(l => {
if (seen.has(l)) return false;
@ -228,7 +249,7 @@ function buildEmailText(full) {
return true;
}).join('\n');
}
return sanitizeString(combined);
return applyTransforms ? sanitizeString(combined) : combined;
}
function updateTimingStats(elapsed) {
@ -262,8 +283,8 @@ async function processMessage(id) {
updateActionIcon();
try {
const full = await messenger.messages.getFull(id);
const originalText = buildEmailText(full, false);
let text = buildEmailText(full);
const originalText = text;
if (tokenReduction && maxTokens > 0) {
const limit = Math.floor(maxTokens * 0.9);
if (text.length > limit) {

View file

@ -1,13 +1,13 @@
{
"manifest_version": 2,
"name": "Sortana",
"version": "2.1.2",
"version": "2.2.0",
"default_locale": "en-US",
"applications": {
"gecko": {
"id": "ai-filter@jordanwages",
"strict_min_version": "128.0",
"strict_max_version": "139.*"
"strict_max_version": "140.*"
}
},
"icons": {