Unify AI provider selection across all features

Every LLM-backed feature (Post-Processing, Proofreading, Title
Generation, Property Filler) now reads from one CHAT_PROVIDERS
registry instead of 5 hand-duplicated provider lists, so they always
offer the exact same providers in the exact same order.

- Add Groq as a 5th chat-completion provider (was transcription-only
  despite its OpenAI-compatible API and an already-collected key).
- Provider dropdowns disable options with no API key configured
  (shown as e.g. "Anthropic (no API key)") instead of silently
  failing at runtime when picked.
- Collapse 3 byte-for-byte duplicated resolveProvider() methods
  (Proofreader, TitleGenerator, PropertyFiller) plus AudioHandler's
  getPostProcessingApiKey() into one resolveChatProvider() helper
  (src/ProviderResolver.ts).
- Fix Custom provider: previously Proofreading/Title/Property silently
  reused Post-Processing's postProcessingUrl with no visible field to
  set it. Renamed to a shared customApiUrl field with its own UI
  (createCustomProviderFields), now exposed on every tab that offers
  Custom, plus rows on the API Keys tab. Migrates old data.json values
  automatically.
- Update README settings reference and getting-started sections to
  match.

No behavior change for existing single-provider setups; migration
handles the postProcessingUrl -> customApiUrl rename transparently.
This commit is contained in:
2026-09-07 17:14:33 -04:00
parent 3abd9d9b3b
commit 9b7ec36828
9 changed files with 270 additions and 207 deletions
+27
View File
@@ -0,0 +1,27 @@
import { CHAT_PROVIDERS, PROVIDER_URLS, PluginSettings, PostProcessingProvider } from "./SettingsManager";
export interface ResolvedChatProvider {
apiKey: string;
endpoint: string;
provider: PostProcessingProvider;
}
/**
* Resolves the API key + endpoint for a chat-completion provider selection.
* Shared by every AI feature that talks to an LLM (Post-Processing,
* Proofreading, Title Generation, Property Filler) so they all treat
* providers — including "no key configured" — identically.
*/
export function resolveChatProvider(
settings: PluginSettings,
provider: PostProcessingProvider
): ResolvedChatProvider | null {
const info = CHAT_PROVIDERS.find((p) => p.id === provider);
if (!info) return null;
const apiKey = settings[info.apiKeyField];
const endpoint = provider === "custom" ? settings.customApiUrl : PROVIDER_URLS[provider];
if (!apiKey || !endpoint) return null;
return { apiKey, endpoint, provider };
}