diff --git a/manifest-chrome.json b/manifest-chrome.json index c1b9fd3..fb850ad 100644 --- a/manifest-chrome.json +++ b/manifest-chrome.json @@ -22,6 +22,7 @@ }, "host_permissions": [ "http://localhost/*", + "http://127.0.0.1/*", "http://*/*", "https://*/*" ], diff --git a/manifest-firefox.json b/manifest-firefox.json index 82b9227..5ef1b5a 100644 --- a/manifest-firefox.json +++ b/manifest-firefox.json @@ -15,6 +15,7 @@ "storage", "scripting", "declarativeNetRequest", + "declarativeNetRequestWithHostAccess", "contextMenus" ], "commands": { @@ -28,6 +29,7 @@ }, "host_permissions": [ "http://localhost/*", + "http://127.0.0.1/*", "http://*/*", "https://*/*" ], @@ -40,6 +42,9 @@ } ] }, + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" + }, "action": { "default_popup": "popup/popup.html", "default_icon": { @@ -50,7 +55,7 @@ } }, "background": { - "scripts": ["scripts/background.js"] + "scripts": ["scripts/config.js", "scripts/background.js"] }, "options_page": "options/options.html", "icons": { diff --git a/manifest.json b/manifest.json index c1b9fd3..fb850ad 100644 --- a/manifest.json +++ b/manifest.json @@ -22,6 +22,7 @@ }, "host_permissions": [ "http://localhost/*", + "http://127.0.0.1/*", "http://*/*", "https://*/*" ], diff --git a/options/options.js b/options/options.js index b9836a1..cbc6b32 100644 --- a/options/options.js +++ b/options/options.js @@ -159,15 +159,20 @@ testBtn.addEventListener("click", async () => { // Provide helpful troubleshooting if ( errorMsg.includes("Cannot connect") || - errorMsg.includes("Failed to fetch") + errorMsg.includes("Failed to fetch") || + errorMsg.includes("NetworkError") ) { + errorMsg += + "\n\nThis error often means nothing is listening at your API URL. If you use Ollama, it may not be running."; errorMsg += "\n\nšŸ’” Troubleshooting:\n"; errorMsg += "1. Check if Ollama is running: run `ollama serve`\n"; errorMsg += "2. Check if the model is pulled: run `ollama pull " + settings.model + "`\n"; - errorMsg += "3. Try switching API Mode (Native vs OpenAI-Compatible)"; + errorMsg += "3. Try switching API Mode (Native vs OpenAI-Compatible)\n"; + errorMsg += + "4. If using Ollama in Firefox: restart with OLLAMA_ORIGINS=* (e.g. OLLAMA_ORIGINS=* ollama serve)"; } showStatus("āŒ " + errorMsg, "error"); diff --git a/popup/popup.css b/popup/popup.css index 0bdf930..a383ce3 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -553,6 +553,7 @@ body { border-radius: 6px; font-size: 12px; line-height: 1.5; + white-space: pre-wrap; } /* ── PDF Error ── */ @@ -755,6 +756,7 @@ body { color: var(--error-text); padding: 10px 14px; border-radius: 6px; + white-space: pre-wrap; } .chat-spinner { diff --git a/popup/popup.js b/popup/popup.js index 314c064..3022987 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -189,9 +189,9 @@ function handleStreamDone(error) { if (!streamTarget) return; // Nothing was streaming if (error) { - showToast("Error: " + error); + showToast("Error: " + withOllamaFetchHint(error)); if (streamElement) { - streamElement.innerHTML = `
${escapeHtml(error)}
`; + streamElement.innerHTML = `
${escapeHtml(withOllamaFetchHint(error))}
`; } // Still finalize to reset states if (streamTarget === "chat") { @@ -801,7 +801,7 @@ async function sendChatMessage() { // Show error in chat const errorEl = document.createElement("div"); errorEl.className = "chat-message assistant error"; - errorEl.textContent = "Error: " + error.message; + errorEl.textContent = "Error: " + withOllamaFetchHint(error.message); chatSection.appendChild(errorEl); // Scroll to show error @@ -823,7 +823,7 @@ function finalizeChatStream(error) { chatInput.focus(); if (error) { - showToast("Error: " + error); + showToast("Error: " + withOllamaFetchHint(error)); return; } @@ -923,7 +923,7 @@ async function generateQuickSummary() { // The response will come via postMessage listener } catch (error) { console.error("API Error:", error); - resultContainer.innerHTML = `
${escapeHtml(error.message)}
`; + resultContainer.innerHTML = `
${escapeHtml(withOllamaFetchHint(error.message))}
`; setLoading(false); } } @@ -932,7 +932,7 @@ function finalizeSummaryStream(error) { if (error) { setLoading(false); if (currentStreamElement) { - currentStreamElement.innerHTML = `
${escapeHtml(error)}
`; + currentStreamElement.innerHTML = `
${escapeHtml(withOllamaFetchHint(error))}
`; } return; } @@ -1285,6 +1285,22 @@ function setLoading(loading) { } } +function looksLikeNetworkFetchFailure(message) { + const m = String(message ?? "").toLowerCase(); + return ( + m.includes("networkerror") || + m.includes("failed to fetch") || + m.includes("network error when attempting to fetch") + ); +} + +/** Explains that Ollama may be stopped when the error looks like a failed fetch. */ +function withOllamaFetchHint(message) { + const base = String(message ?? ""); + if (!looksLikeNetworkFetchFailure(base)) return base; + return `${base}\n\nIf you're using Ollama, it may not be running. Try \`ollama serve\`.`; +} + function escapeHtml(text) { const div = document.createElement("div"); div.textContent = text; diff --git a/rules.json b/rules.json index 75b803d..699a0dc 100644 --- a/rules.json +++ b/rules.json @@ -13,8 +13,24 @@ ] }, "condition": { - "urlFilter": "http://localhost:11434/*", - "resourceTypes": ["xmlhttprequest"] + "urlFilter": "http://localhost:11434/*" + } + }, + { + "id": 2, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [ + { + "header": "Origin", + "operation": "set", + "value": "http://127.0.0.1" + } + ] + }, + "condition": { + "urlFilter": "http://127.0.0.1:11434/*" } } ] diff --git a/scripts/background.js b/scripts/background.js index 0b970fe..cb2ddbb 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -1,8 +1,11 @@ // Background script - handles API communication // Uses centralized CONFIG from config.js -// Import shared configuration (service worker context) -importScripts("config.js"); +// Chrome MV3: service worker — load config via importScripts. +// Firefox MV3: event-page scripts — config.js is listed first in manifest "scripts". +if (typeof importScripts === "function") { + importScripts("config.js"); +} // Cache key prefixes from CONFIG const QUICK_SUMMARY_CACHE_PREFIX = CONFIG.CACHE.QUICK_SUMMARY; diff --git a/scripts/config.js b/scripts/config.js index 46461a2..b659534 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -19,7 +19,7 @@ const CONFIG = { BASE_URL: "http://localhost:11434", MODEL: "gpt-oss:20b-cloud", KEY: "", - DISABLE_THINKING: false, + DISABLE_THINKING: true, AUTO_SUMMARIZE: false, MAX_TOKENS: 2048, TEMPERATURE: 0.7,