const fs = require('fs'); const content = fs.readFileSync('temp/rich-outline-fail_57_1779015509994.txt', 'utf-8'); const marker = '========== AI εŽŸε§‹ε“εΊ” '; const markerIdx = content.indexOf(marker); const headerEndIdx = content.indexOf(' ==========', markerIdx); const aiStart = content.indexOf('\n', headerEndIdx) + 1; const aiEnd = content.indexOf('\n\n', aiStart); const aiResponse = content.substring(aiStart, aiEnd); console.log('AI response length:', aiResponse.length); // Check position 1624 const pos = 1624; console.log('\n=== Context around pos', pos, '==='); console.log(JSON.stringify(aiResponse.substring(pos-80, pos+80))); // Count bad patterns const badPattern = /,{number":/g; const matches = aiResponse.match(badPattern); console.log('\nBad pattern count:', matches ? matches.length : 0); // What is at position 1624? console.log('\nChars at', pos, 'to', pos+10, ':'); for (let i = pos; i < pos+10; i++) { console.log(' pos', i, ':', JSON.stringify(aiResponse[i]), 'code:', aiResponse.charCodeAt(i)); } // Try with different fix patterns function fixMissingQuotes(jsonStr) { return jsonStr .replace(/,(\{[^"]+":)/g, function(m) { return ',{"' + m.slice(2); }) .replace(/\{number":/g, '{"number":') .replace(/\{title":/g, '{"title":') .replace(/\{summary":/g, '{"summary":') .replace(/\{opening":/g, '{"opening":') .replace(/\{structure":/g, '{"structure":') .replace(/\{mustCover":/g, '{"mustCover":') .replace(/\{mustNotRepeat":/g, '{"mustNotRepeat":') .replace(/\{toneAdjustment":/g, '{"toneAdjustment":') .replace(/\{keyTakeaway":/g, '{"keyTakeaway":') .replace(/\{keyPoints":/g, '{"keyPoints":') .replace(/\{estimatedWords":/g, '{"estimatedWords":') .replace(/\{writingInstructions":/g, '{"writingInstructions":'); } const match = aiResponse.match(/\{[\s\S]*\}/); if (match) { const fixed = fixMissingQuotes(match[0]); try { const data = JSON.parse(fixed); console.log('\nFixed+parsed SUCCESS, chapters:', data.chapters?.length); } catch(e) { console.log('\nFixed+parsed failed:', e.message.substring(0, 100)); const p = parseInt(e.message.match(/position (\d+)/)?.[1] || '0'); console.log('Error at position', p); console.log('Context:', JSON.stringify(fixed.substring(Math.max(0,p-50), p+50))); } }