9b7ec36828
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.
65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
import { Editor, Notice } from "obsidian";
|
|
import { AIService } from "../AIService";
|
|
import { resolveChatProvider } from "../ProviderResolver";
|
|
import NibbleAI from "main";
|
|
|
|
export class Proofreader {
|
|
private plugin: NibbleAI;
|
|
|
|
constructor(plugin: NibbleAI) {
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
async fixSelection(editor: Editor): Promise<void> {
|
|
const selection = editor.getSelection();
|
|
if (!selection || selection.trim().length === 0) {
|
|
new Notice("No text selected.");
|
|
return;
|
|
}
|
|
|
|
const config = resolveChatProvider(
|
|
this.plugin.settings,
|
|
this.plugin.settings.proofreadingProvider || "openrouter"
|
|
);
|
|
if (!config) {
|
|
new Notice(
|
|
"⚠️ No API key for selected provider. Check Settings \u2192 NibbleAI \u2192 API Keys."
|
|
);
|
|
return;
|
|
}
|
|
|
|
new Notice("🤖 Fixing punctuation and grammar...");
|
|
|
|
try {
|
|
const systemPrompt =
|
|
this.plugin.settings.proofreadingSystemPrompt ||
|
|
"You are a text proofreading tool. Fix punctuation and grammar in the text below. Return only the corrected text, nothing else.";
|
|
|
|
const corrected = await AIService.callChatCompletion(
|
|
selection,
|
|
systemPrompt,
|
|
{
|
|
apiKey: config.apiKey,
|
|
model: this.plugin.settings.proofreadingModel,
|
|
endpoint: config.endpoint,
|
|
provider: config.provider,
|
|
temperature: this.plugin.settings.proofreadingTemperature,
|
|
maxTokens: this.plugin.settings.proofreadingMaxTokens,
|
|
}
|
|
);
|
|
|
|
if (!corrected || corrected.trim().length === 0) {
|
|
new Notice("⚠️ AI returned empty result. No changes made.");
|
|
return;
|
|
}
|
|
|
|
editor.replaceSelection(corrected);
|
|
new Notice("✅ Punctuation and grammar fixed.");
|
|
} catch (error) {
|
|
console.error("Proofreading error:", error);
|
|
new Notice(
|
|
`❌ Fix failed: ${error instanceof Error ? error.message : String(error)}`
|
|
);
|
|
}
|
|
}
|
|
} |