import { getSystemConfig } from '@/lib/config' import { getChatProvider } from '@/lib/ai/factory' export interface ClipAnalysis { title: string summary: string tags: string[] readingTimeMinutes: number } function parseAnalysisJson(raw: string): ClipAnalysis | null { const trimmed = raw.trim() const jsonMatch = trimmed.match(/\{[\s\S]*\}/) if (!jsonMatch) return null try { const parsed = JSON.parse(jsonMatch[0]) as Partial const tags = Array.isArray(parsed.tags) ? parsed.tags.filter((t): t is string => typeof t === 'string').slice(0, 5) : [] const readingTime = typeof parsed.readingTimeMinutes === 'number' ? Math.max(1, Math.min(120, Math.round(parsed.readingTimeMinutes))) : 5 return { title: typeof parsed.title === 'string' && parsed.title.trim() ? parsed.title.trim().slice(0, 200) : 'Web clip', summary: typeof parsed.summary === 'string' ? parsed.summary.trim().slice(0, 800) : '', tags, readingTimeMinutes: readingTime, } } catch { return null } } function estimateReadingMinutes(text: string): number { const words = text.split(/\s+/).filter(Boolean).length return Math.max(1, Math.round(words / 200)) } export async function analyzeClipContent(params: { url: string title: string textContent: string }): Promise { const excerpt = params.textContent.slice(0, 6000) const fallbackReading = estimateReadingMinutes(params.textContent) try { const config = await getSystemConfig() const provider = getChatProvider(config) const prompt = `You analyze web articles for a personal knowledge base. URL: ${params.url} Page title: ${params.title} Content excerpt: ${excerpt} Respond with ONLY valid JSON (no markdown): { "title": "concise improved title", "summary": "max 3 sentences in the same language as the content", "tags": ["tag1", "tag2"], "readingTimeMinutes": ${fallbackReading} } Rules: tags max 5, short lowercase labels, summary factual.` const raw = await provider.generateText(prompt) const parsed = parseAnalysisJson(raw) if (parsed) { if (!parsed.title) parsed.title = params.title || 'Web clip' if (!parsed.summary && params.textContent) { parsed.summary = params.textContent.slice(0, 400) } if (parsed.tags.length === 0) parsed.tags = [] return parsed } } catch (error) { console.error('[ClipAnalyze] AI failed:', error) } return { title: params.title || 'Web clip', summary: params.textContent.slice(0, 400), tags: [], readingTimeMinutes: fallbackReading, } }