const FALLBACK = { identity_title: 'A Better Version of Me', identity_summary: 'You are starting a journey to transform yourself, step by step. Every small action counts.', suggested_habits: [ 'Do one small positive action today', 'Avoid one bad habit', 'Reflect for 2 minutes before sleep', ], }; /** * Safely parse AI JSON response. * Handles markdown wrapping, broken JSON, and missing fields. * Always returns a valid result — never throws. * * @param {string} raw - Raw text from AI response * @returns {{ identity_title: string, identity_summary: string, suggested_habits: string[] }} */ export default function safeParseAI(raw) { if (!raw || typeof raw !== 'string') return { ...FALLBACK }; try { // Strip markdown code fences let cleaned = raw.trim(); cleaned = cleaned.replace(/```json\s*/gi, '').replace(/```\s*/gi, ''); cleaned = cleaned.trim(); // Find first { and last } to extract JSON object const start = cleaned.indexOf('{'); const end = cleaned.lastIndexOf('}'); if (start === -1 || end === -1) return { ...FALLBACK }; cleaned = cleaned.slice(start, end + 1); const parsed = JSON.parse(cleaned); // Validate required fields const title = typeof parsed.identity_title === 'string' && parsed.identity_title.trim() ? parsed.identity_title.trim() : FALLBACK.identity_title; const summary = typeof parsed.identity_summary === 'string' && parsed.identity_summary.trim() ? parsed.identity_summary.trim() : FALLBACK.identity_summary; let habits = FALLBACK.suggested_habits; if (Array.isArray(parsed.suggested_habits) && parsed.suggested_habits.length > 0) { habits = parsed.suggested_habits .filter((h) => typeof h === 'string' && h.trim()) .map((h) => h.trim()); } if (habits.length === 0) habits = FALLBACK.suggested_habits; return { identity_title: title, identity_summary: summary, suggested_habits: habits, }; } catch (_) { return { ...FALLBACK }; } } export { FALLBACK };