special prompts validation for config errors. see #766
This commit is contained in:
parent
fc803700fa
commit
c7234d035e
3 changed files with 62 additions and 4 deletions
|
|
@ -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`
|
- Worker: `js/workers/model-worker-anthropic.js`
|
||||||
- Settings keys: `anthropic_api_key`, `anthropic_model`, `anthropic_version`, `anthropic_max_tokens`, `anthropic_system_prompt`, `anthropic_temperature`
|
- 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
|
## Web Worker Pattern
|
||||||
|
|
||||||
For all API-based providers (everything except ChatGPT Web), the call goes through a Web Worker:
|
For all API-based providers (everything except ChatGPT Web), the call goes through a Web Worker:
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,33 @@
|
||||||
integration_options_config
|
integration_options_config
|
||||||
} from "../options/mzta-options-default.js";
|
} from "../options/mzta-options-default.js";
|
||||||
import { taLogger } from './mzta-logger.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 {
|
export class mzta_specialCommand {
|
||||||
|
|
||||||
|
|
@ -92,6 +119,15 @@
|
||||||
|
|
||||||
const prefs_api = await browser.storage.sync.get(prefsToGet);
|
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 = {
|
let workerInitMessage = {
|
||||||
type: 'init',
|
type: 'init',
|
||||||
do_debug: this.do_debug,
|
do_debug: this.do_debug,
|
||||||
|
|
|
||||||
|
|
@ -705,7 +705,7 @@ async function _generateSummaryForMessage(headerMessageId, tabId = null, options
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ThunderAI] Error generating summary:", 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" } });
|
if (tabId) browser.tabs.sendMessage(tabId, { command: "showSummary", data: { error: true, message: error.message || "Failed to generate summary" } });
|
||||||
taWorkingStatus.stopWorking();
|
taWorkingStatus.stopWorking();
|
||||||
}
|
}
|
||||||
|
|
@ -805,7 +805,7 @@ async function _generateTranslationForMessage(headerMessageId, tabId = null, opt
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ThunderAI] Error generating translation:", 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" } });
|
if (tabId) browser.tabs.sendMessage(tabId, { command: "showTranslation", data: { error: true, message: error.message || "Failed to generate translation" } });
|
||||||
taWorkingStatus.stopWorking();
|
taWorkingStatus.stopWorking();
|
||||||
}
|
}
|
||||||
|
|
@ -984,8 +984,12 @@ async function _generateSpamReportForMessage(headerMessageId, options = {}) {
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ThunderAI] Error generating spam report:", error);
|
console.error("[ThunderAI] Error generating spam report:", error);
|
||||||
let err_data = await spamReport.saveError(headerMessageId, error.message || String(error));
|
if (error.isConfigError) {
|
||||||
await updateSpamPanel(headerMessageId, "showSpamReport", err_data);
|
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 };
|
return { success: false };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue