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); // The error is at position 1624, char "{" code 123 // Error: Expected double-quoted property name // This means when the parser hits {, it expected "propertyName": first // This can happen if: // 1. We're at the start of a new object but the previous object wasn't properly closed // 2. There's a structural error that makes the parser think we're in the wrong place // Let me trace the brace/bracket depth and check where it goes negative let inString = false; let escapeNext = false; let braceLevel = 0; // { } let bracketLevel = 0; // [ ] let pos = 0; let errorPos = 1624; for (let i = 0; i <= errorPos; i++) { const ch = aiResponse[i]; if (escapeNext) { escapeNext = false; continue; } if (ch === '\\') { escapeNext = true; continue; } if (ch === '"') { inString = !inString; continue; } if (inString) continue; if (ch === '{') { braceLevel++; if (i === errorPos) { console.log('At error pos, opening brace, levels: brace=', braceLevel, 'bracket=', bracketLevel); } } else if (ch === '}') { braceLevel--; if (i === errorPos) { console.log('At error pos, closing brace, levels: brace=', braceLevel, 'bracket=', bracketLevel); } } else if (ch === '[') { bracketLevel++; if (i === errorPos) { console.log('At error pos, opening bracket, levels: brace=', braceLevel, 'bracket=', bracketLevel); } } else if (ch === ']') { bracketLevel--; if (i === errorPos) { console.log('At error pos, closing bracket, levels: brace=', braceLevel, 'bracket=', bracketLevel); } } // Check what levels are at errorPos-1 (the char before the error) if (i === errorPos - 1) { console.log('Before error pos (at ' + i + '):', JSON.stringify(ch), 'levels: brace=', braceLevel, 'bracket=', bracketLevel); } } console.log('\nAt error position 1624 itself, before processing it:'); // Calculate levels BEFORE processing char at 1624 let braceBefore = 0, bracketBefore = 0; inString = false; escapeNext = false; for (let i = 0; i < 1624; i++) { const ch = aiResponse[i]; if (escapeNext) { escapeNext = false; continue; } if (ch === '\\') { escapeNext = true; continue; } if (ch === '"') { inString = !inString; continue; } if (inString) continue; if (ch === '{') braceBefore++; else if (ch === '}') braceBefore--; else if (ch === '[') bracketBefore++; else if (ch === ']') bracketBefore--; } console.log('Before processing char at 1624: braceLevel=' + braceBefore + ' bracketLevel=' + bracketBefore); console.log('Char at 1624 is:', JSON.stringify(aiResponse[1624])); // The char at 1624 is "{" - so after processing it, braceLevel would be braceBefore+1 console.log('If we process {, braceLevel would become:', braceBefore + 1); // But the ERROR says at position 1624 we saw { and expected a property name // This means braceLevel must have been 0 BEFORE processing the {, meaning // we're trying to open a new object at the top level, which is fine IF we // just had a comma // Wait - let me check what's BEFORE the { at 1624 console.log('\n=== Context before the { at 1624 ==='); console.log(JSON.stringify(aiResponse.substring(1580, 1640))); // The substring shows: ...],\"mustNotRepeat\":[...],{\"number\":3,... // So it's: ]},{"number":3 // That ] closes an array, } closes an object, , separates, { starts new object // This is valid if we're adding to a chapters array! // Let me try a different approach - parse the JSON and see where it fails // by trying to parse chunks console.log('\n=== Trying incremental parse ==='); let lastGoodPos = 0; inString = false; escapeNext = false; braceLevel = 0; bracketLevel = 0; for (let i = 0; i < aiResponse.length; i++) { const ch = aiResponse[i]; if (escapeNext) { escapeNext = false; continue; } if (ch === '\\') { escapeNext = true; continue; } if (ch === '"') { inString = !inString; continue; } if (inString) continue; if (ch === '{') braceLevel++; else if (ch === '}') braceLevel--; else if (ch === '[') bracketLevel++; else if (ch === ']') bracketLevel--; // Try parsing up to this point if ((ch === '}' || ch === ',') && braceLevel === 0 && bracketLevel === 0) { try { JSON.parse(aiResponse.substring(0, i + 1)); lastGoodPos = i + 1; } catch(e) { if (i > 1600 && i < 1700) { console.log('Parse failed at', i, 'char', JSON.stringify(ch), 'error:', e.message.substring(0, 60)); } } } } console.log('Last good parse position:', lastGoodPos); console.log('Context around last good:', JSON.stringify(aiResponse.substring(lastGoodPos - 20, lastGoodPos + 40)));