/** * Paragraph Refactor Service * Provides AI-powered text reformulation with 3 options: * 1. Clarify - Make ambiguous text clearer * 2. Shorten - Condense while keeping meaning * 3. Improve Style - Enhance readability and flow */ import { LanguageDetectionService } from './language-detection.service' import { getTagsProvider } from '../factory' import { getSystemConfig } from '@/lib/config' export type RefactorMode = 'clarify' | 'shorten' | 'improveStyle' | 'fix_grammar' | 'translate' | 'explain' | 'write' export interface RefactorOption { mode: RefactorMode label: string description: string icon: string } export interface RefactorResult { original: string refactored: string mode: RefactorMode language: string wordCountChange: { original: number refactored: number difference: number percentage: number } } export const REFACTOR_OPTIONS: RefactorOption[] = [ { mode: 'clarify', label: 'Clarify', description: 'Make the text clearer and easier to understand', icon: '💡' }, { mode: 'shorten', label: 'Shorten', description: 'Condense the text while keeping key information', icon: '✂️' }, { mode: 'improveStyle', label: 'Improve Style', description: 'Enhance readability, flow, and expression', icon: '✨' } ] export class ParagraphRefactorService { private languageDetection: LanguageDetectionService private readonly MIN_WORDS = 10 private readonly MAX_WORDS = 5000 constructor() { this.languageDetection = new LanguageDetectionService() } /** * Refactor a paragraph with the specified mode */ async refactor( content: string, mode: RefactorMode, format: 'html' | 'markdown' = 'markdown', targetLanguage?: string, writePrompt?: string ): Promise { // 'write' mode skips word count validation (generates from prompt, no selection needed) if (mode !== 'write') { const wordCount = content.split(/\s+/).length if (wordCount < this.MIN_WORDS || wordCount > this.MAX_WORDS) { throw new Error( `Please select ${this.MIN_WORDS}-${this.MAX_WORDS} words to reformulate` ) } } // Detect language or use provided target language const { language: detectedLanguage } = mode === 'write' ? { language: targetLanguage || 'fr' } : await this.languageDetection.detectLanguage(content) const language = targetLanguage || detectedLanguage try { // Build prompts const systemPrompt = this.getSystemPrompt(mode, format) const userPrompt = this.getUserPrompt(mode, content, language, format, writePrompt) // Get AI provider from factory const config = await getSystemConfig() const provider = getTagsProvider(config) // Use provider's generateText method const fullPrompt = `${systemPrompt}\n\n${userPrompt}` const refactored = await provider.generateText(fullPrompt) // Calculate word count change const refactoredWordCount = refactored.split(/\s+/).length const wordCountChange = { original: mode === 'write' ? 0 : content.split(/\s+/).length, refactored: refactoredWordCount, difference: refactoredWordCount - (mode === 'write' ? 0 : content.split(/\s+/).length), percentage: 0 } return { original: content, refactored, mode, language, wordCountChange } } catch (error) { throw new Error('Failed to refactor paragraph. Please try again.') } } /** * Get all 3 refactor options for a paragraph at once * More efficient than calling refactor() 3 times */ async refactorAllModes(content: string): Promise { // Validate word count const wordCount = content.split(/\s+/).length if (wordCount < this.MIN_WORDS || wordCount > this.MAX_WORDS) { throw new Error( `Please select ${this.MIN_WORDS}-${this.MAX_WORDS} words to reformulate` ) } // Detect language const { language } = await this.languageDetection.detectLanguage(content) try { // System prompt for all modes const systemPrompt = `You are an expert text editor who can improve text in multiple ways. Your task is to provide 3 different reformulations of the user's text. For each reformulation: 1. Clarify: Make the text clearer, more explicit, easier to understand 2. Shorten: Condense the text while preserving all key information and meaning 3. Improve Style: Enhance readability, flow, vocabulary, and expression CRITICAL LANGUAGE RULE: You MUST respond in the EXACT SAME LANGUAGE as the input text. - If input is French, ALL 3 outputs MUST be in French - If input is German, ALL 3 outputs MUST be in German - If input is Spanish, ALL 3 outputs MUST be in Spanish - NEVER translate to English unless the input is in English Maintain the original meaning and intent: - For "shorten", aim to reduce by 30-50% while keeping all key points - For "clarify", expand where necessary but keep it natural - For "improve style", keep similar length but enhance quality Output Format (JSON): { "clarify": "clarified text here...", "shorten": "shortened text here...", "improveStyle": "improved text here..." }` const userPrompt = `CRITICAL LANGUAGE INSTRUCTION: The text below is in ${language}. Your response MUST be in ${language}. Do NOT translate to English. Please provide 3 reformulations of this ${language} text: ${content} Original language: ${language} IMPORTANT: Provide all 3 versions in ${language}. No English, no explanations.` // Get AI provider from factory const config = await getSystemConfig() const provider = getTagsProvider(config) // Use provider's generateText method const fullPrompt = `${systemPrompt}\n\n${userPrompt}` const response = await provider.generateText(fullPrompt) // Parse JSON response const jsonResponse = JSON.parse(response) const modes: RefactorMode[] = ['clarify', 'shorten', 'improveStyle'] const results: RefactorResult[] = [] for (const mode of modes) { if (!jsonResponse[mode]) continue const refactored = this.extractRefactoredText(jsonResponse[mode]) const refactoredWordCount = refactored.split(/\s+/).length results.push({ original: content, refactored, mode, language, wordCountChange: { original: wordCount, refactored: refactoredWordCount, difference: refactoredWordCount - wordCount, percentage: ((refactoredWordCount - wordCount) / wordCount) * 100 } }) } return results } catch (error) { throw new Error('Failed to generate refactor options. Please try again.') } } /** * Get mode-specific system prompt */ private getSystemPrompt(mode: RefactorMode, format: 'html' | 'markdown' = 'markdown'): string { const formatInstruction = format === 'html' ? "\nCRITICAL FORMAT RULE: You MUST return your response as valid HTML fragments (e.g., using

, , ,