special prompts validation for config errors. see #766

This commit is contained in:
Mic 2026-04-20 18:39:12 +02:00
parent fc803700fa
commit c7234d035e
3 changed files with 62 additions and 4 deletions

View file

@ -51,6 +51,24 @@ Content script `js/lib/diff.js` is injected into ChatGPT pages for diff-view sup
- Worker: `js/workers/model-worker-anthropic.js`
- Settings keys: `anthropic_api_key`, `anthropic_model`, `anthropic_version`, `anthropic_max_tokens`, `anthropic_system_prompt`, `anthropic_temperature`
## Configuration Validation
For special prompts (`mzta_specialCommand`), required fields are validated in `initWorker()` (`js/mzta-special-commands.js`) **before** the worker is created. If a required field is empty, an `Error` with `isConfigError = true` is thrown. Validation covers:
| Provider | Required fields |
|----------|----------------|
| `chatgpt_api` | `chatgpt_api_key`, `chatgpt_model` |
| `google_gemini_api` | `google_gemini_api_key`, `google_gemini_model` |
| `ollama_api` | `ollama_host`, `ollama_model` |
| `openai_comp_api` | `openai_comp_host`, `openai_comp_model` |
| `anthropic_api` | `anthropic_api_key`, `anthropic_model`, `anthropic_version` |
Validation is skipped when `use_specific_api = true` (i.e., the prompt's own `api_type` overrides the global setting — credentials come from the prompt config, not global prefs).
The `isConfigError` flag on the thrown error tells callers in `mzta-background.js` to display the error in the panel **without saving it to storage** — so the user can fix settings and retry cleanly.
For regular prompts (`openChatGPT()`), validation still happens inside the listener callback after the API webchat window is created (unchanged behavior).
## Web Worker Pattern
For all API-based providers (everything except ChatGPT Web), the call goes through a Web Worker:

View file

@ -22,6 +22,33 @@
integration_options_config
} from "../options/mzta-options-default.js";
import { taLogger } from './mzta-logger.js';
function validateAPIConfig(llm, prefs) {
switch (llm) {
case 'chatgpt_api':
if (!prefs.chatgpt_api_key) return browser.i18n.getMessage('chatgpt_empty_apikey');
if (!prefs.chatgpt_model) return browser.i18n.getMessage('chatgpt_empty_model');
break;
case 'google_gemini_api':
if (!prefs.google_gemini_api_key) return browser.i18n.getMessage('google_gemini_empty_apikey');
if (!prefs.google_gemini_model) return browser.i18n.getMessage('google_gemini_empty_model');
break;
case 'ollama_api':
if (!prefs.ollama_host) return browser.i18n.getMessage('ollama_empty_host');
if (!prefs.ollama_model) return browser.i18n.getMessage('ollama_empty_model');
break;
case 'openai_comp_api':
if (!prefs.openai_comp_host) return browser.i18n.getMessage('OpenAIComp_empty_host');
if (!prefs.openai_comp_model) return browser.i18n.getMessage('OpenAIComp_empty_model');
break;
case 'anthropic_api':
if (!prefs.anthropic_api_key) return browser.i18n.getMessage('anthropic_empty_apikey');
if (!prefs.anthropic_model) return browser.i18n.getMessage('anthropic_empty_model');
if (!prefs.anthropic_version) return browser.i18n.getMessage('anthropic_empty_version');
break;
}
return null;
}
export class mzta_specialCommand {
@ -92,6 +119,15 @@
const prefs_api = await browser.storage.sync.get(prefsToGet);
if (!use_specific_api) {
const configError = validateAPIConfig(this.llm, prefs_api);
if (configError) {
const err = new Error(configError);
err.isConfigError = true;
throw err;
}
}
let workerInitMessage = {
type: 'init',
do_debug: this.do_debug,

View file

@ -705,7 +705,7 @@ async function _generateSummaryForMessage(headerMessageId, tabId = null, options
} catch (error) {
console.error("[ThunderAI] Error generating summary:", error);
await summaryStore.saveError(headerMessageId, error.message || String(error));
if (!error.isConfigError) await summaryStore.saveError(headerMessageId, error.message || String(error));
if (tabId) browser.tabs.sendMessage(tabId, { command: "showSummary", data: { error: true, message: error.message || "Failed to generate summary" } });
taWorkingStatus.stopWorking();
}
@ -805,7 +805,7 @@ async function _generateTranslationForMessage(headerMessageId, tabId = null, opt
} catch (error) {
console.error("[ThunderAI] Error generating translation:", error);
await translationStore.saveError(headerMessageId, error.message || String(error));
if (!error.isConfigError) await translationStore.saveError(headerMessageId, error.message || String(error));
if (tabId) browser.tabs.sendMessage(tabId, { command: "showTranslation", data: { error: true, message: error.message || "Failed to generate translation" } });
taWorkingStatus.stopWorking();
}
@ -984,8 +984,12 @@ async function _generateSpamReportForMessage(headerMessageId, options = {}) {
} catch (error) {
console.error("[ThunderAI] Error generating spam report:", error);
let err_data = await spamReport.saveError(headerMessageId, error.message || String(error));
await updateSpamPanel(headerMessageId, "showSpamReport", err_data);
if (error.isConfigError) {
await updateSpamPanel(headerMessageId, "showSpamReport", { spamValue: -999, explanation: error.message || String(error) });
} else {
let err_data = await spamReport.saveError(headerMessageId, error.message || String(error));
await updateSpamPanel(headerMessageId, "showSpamReport", err_data);
}
return { success: false };
}
}