Compare commits
No commits in common. "main" and "codex/find-real-time-updates-for-diff-view" have entirely different histories.
main
...
codex/find
5 changed files with 16 additions and 58 deletions
|
@ -16,7 +16,7 @@ message meets a specified criterion.
|
||||||
- **Advanced parameters** – tune generation settings like temperature, top‑p and more from the options page.
|
- **Advanced parameters** – tune generation settings like temperature, top‑p and more from the options page.
|
||||||
- **Markdown conversion** – optionally convert HTML bodies to Markdown before sending them to the AI service.
|
- **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 logging** – optional colorized logs help troubleshoot interactions with the AI service.
|
||||||
- **Debug tab** – view the last request payload and a diff between the unaltered message text and the final prompt.
|
- **Debug tab** – view the last request payload and message diff with live updates.
|
||||||
- **Light/Dark themes** – automatically match Thunderbird's appearance with optional manual override.
|
- **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.
|
- **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.
|
- **Rule ordering** – drag rules to prioritize them and optionally stop processing after a match.
|
||||||
|
|
|
@ -210,38 +210,17 @@ function collectText(part, bodyParts, attachments) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectRawText(part, bodyParts, attachments) {
|
function buildEmailText(full) {
|
||||||
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 bodyParts = [];
|
||||||
const attachments = [];
|
const attachments = [];
|
||||||
const collect = applyTransforms ? collectText : collectRawText;
|
collectText(full, bodyParts, attachments);
|
||||||
collect(full, bodyParts, attachments);
|
|
||||||
const headers = Object.entries(full.headers || {})
|
const headers = Object.entries(full.headers || {})
|
||||||
.map(([k, v]) => `${k}: ${v.join(' ')}`)
|
.map(([k, v]) => `${k}: ${v.join(' ')}`)
|
||||||
.join('\n');
|
.join('\n');
|
||||||
const attachInfo = `Attachments: ${attachments.length}` +
|
const attachInfo = `Attachments: ${attachments.length}` +
|
||||||
(attachments.length ? "\n" + attachments.map(a => ` - ${a}`).join('\n') : "");
|
(attachments.length ? "\n" + attachments.map(a => ` - ${a}`).join('\n') : "");
|
||||||
let combined = `${headers}\n${attachInfo}\n\n${bodyParts.join('\n')}`.trim();
|
let combined = `${headers}\n${attachInfo}\n\n${bodyParts.join('\n')}`.trim();
|
||||||
if (applyTransforms && tokenReduction) {
|
if (tokenReduction) {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
combined = combined.split('\n').filter(l => {
|
combined = combined.split('\n').filter(l => {
|
||||||
if (seen.has(l)) return false;
|
if (seen.has(l)) return false;
|
||||||
|
@ -249,7 +228,7 @@ function buildEmailText(full, applyTransforms = true) {
|
||||||
return true;
|
return true;
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
}
|
}
|
||||||
return applyTransforms ? sanitizeString(combined) : combined;
|
return sanitizeString(combined);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTimingStats(elapsed) {
|
function updateTimingStats(elapsed) {
|
||||||
|
@ -283,8 +262,8 @@ async function processMessage(id) {
|
||||||
updateActionIcon();
|
updateActionIcon();
|
||||||
try {
|
try {
|
||||||
const full = await messenger.messages.getFull(id);
|
const full = await messenger.messages.getFull(id);
|
||||||
const originalText = buildEmailText(full, false);
|
|
||||||
let text = buildEmailText(full);
|
let text = buildEmailText(full);
|
||||||
|
const originalText = text;
|
||||||
if (tokenReduction && maxTokens > 0) {
|
if (tokenReduction && maxTokens > 0) {
|
||||||
const limit = Math.floor(maxTokens * 0.9);
|
const limit = Math.floor(maxTokens * 0.9);
|
||||||
if (text.length > limit) {
|
if (text.length > limit) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Sortana",
|
"name": "Sortana",
|
||||||
"version": "2.2.0",
|
"version": "2.1.2",
|
||||||
"default_locale": "en-US",
|
"default_locale": "en-US",
|
||||||
"applications": {
|
"applications": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "ai-filter@jordanwages",
|
"id": "ai-filter@jordanwages",
|
||||||
"strict_min_version": "128.0",
|
"strict_min_version": "128.0",
|
||||||
"strict_max_version": "140.*"
|
"strict_max_version": "139.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"icons": {
|
"icons": {
|
||||||
|
|
|
@ -154,11 +154,6 @@
|
||||||
<input type="checkbox" id="token-reduction"> Aggressive token reduction
|
<input type="checkbox" id="token-reduction"> Aggressive token reduction
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<label class="checkbox">
|
|
||||||
<input type="checkbox" id="show-debug-tab"> Show debug information
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" for="max_tokens">Max tokens</label>
|
<label class="label" for="max_tokens">Max tokens</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
@ -225,6 +220,11 @@
|
||||||
<input class="input" type="number" step="0.01" id="tfs">
|
<input class="input" type="number" step="0.01" id="tfs">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" id="show-debug-tab"> Advanced Options
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -290,10 +290,7 @@
|
||||||
<span>Debug</span>
|
<span>Debug</span>
|
||||||
</h2>
|
</h2>
|
||||||
<pre id="payload-display"></pre>
|
<pre id="payload-display"></pre>
|
||||||
<div id="diff-container" class="mt-4 is-hidden">
|
<div id="diff-display" class="mt-4"></div>
|
||||||
<label class="label">Prompt diff</label>
|
|
||||||
<div id="diff-display" class="box content is-family-monospace"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -70,7 +70,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
await applyTheme(themeSelect.value);
|
await applyTheme(themeSelect.value);
|
||||||
const payloadDisplay = document.getElementById('payload-display');
|
const payloadDisplay = document.getElementById('payload-display');
|
||||||
const diffDisplay = document.getElementById('diff-display');
|
const diffDisplay = document.getElementById('diff-display');
|
||||||
const diffContainer = document.getElementById('diff-container');
|
|
||||||
|
|
||||||
let lastFullText = defaults.lastFullText || '';
|
let lastFullText = defaults.lastFullText || '';
|
||||||
let lastPromptText = defaults.lastPromptText || '';
|
let lastPromptText = defaults.lastPromptText || '';
|
||||||
|
@ -84,16 +83,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
dmp.Diff_EditCost = 4;
|
dmp.Diff_EditCost = 4;
|
||||||
const diffs = dmp.diff_main(lastFullText, lastPromptText);
|
const diffs = dmp.diff_main(lastFullText, lastPromptText);
|
||||||
dmp.diff_cleanupEfficiency(diffs);
|
dmp.diff_cleanupEfficiency(diffs);
|
||||||
const hasDiff = diffs.some(d => d[0] !== 0);
|
diffDisplay.innerHTML = dmp.diff_prettyHtml(diffs);
|
||||||
if (hasDiff) {
|
|
||||||
diffDisplay.innerHTML = dmp.diff_prettyHtml(diffs);
|
|
||||||
diffContainer.classList.remove('is-hidden');
|
|
||||||
} else {
|
|
||||||
diffDisplay.innerHTML = '';
|
|
||||||
diffContainer.classList.add('is-hidden');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
diffContainer.classList.add('is-hidden');
|
|
||||||
}
|
}
|
||||||
themeSelect.addEventListener('change', async () => {
|
themeSelect.addEventListener('change', async () => {
|
||||||
markDirty();
|
markDirty();
|
||||||
|
@ -761,17 +751,9 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
dmp.Diff_EditCost = 4;
|
dmp.Diff_EditCost = 4;
|
||||||
const diffs = dmp.diff_main(lastFullText, lastPromptText);
|
const diffs = dmp.diff_main(lastFullText, lastPromptText);
|
||||||
dmp.diff_cleanupEfficiency(diffs);
|
dmp.diff_cleanupEfficiency(diffs);
|
||||||
const hasDiff = diffs.some(d => d[0] !== 0);
|
diffDisplay.innerHTML = dmp.diff_prettyHtml(diffs);
|
||||||
if (hasDiff) {
|
|
||||||
diffDisplay.innerHTML = dmp.diff_prettyHtml(diffs);
|
|
||||||
diffContainer.classList.remove('is-hidden');
|
|
||||||
} else {
|
|
||||||
diffDisplay.innerHTML = '';
|
|
||||||
diffContainer.classList.add('is-hidden');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
diffDisplay.innerHTML = '';
|
diffDisplay.innerHTML = '';
|
||||||
diffContainer.classList.add('is-hidden');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue