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('Length:', aiResponse.length); // Test the raw response without any fixes console.log('\n=== TEST 1: Raw response ==='); try { const data = JSON.parse(aiResponse); console.log('SUCCESS, chapters:', data.chapters?.length); } catch(e) { console.log('FAILED:', e.message.substring(0, 80)); } // Test with the regex match const match = aiResponse.match(/\{[\s\S]*\}/); console.log('\n=== TEST 2: Regex match ==='); if (match) { console.log('Match length:', match[0].length); console.log('Match starts with:', JSON.stringify(match[0].substring(0, 50))); console.log('Match ends with:', JSON.stringify(match[0].substring(match[0].length - 50))); try { const data = JSON.parse(match[0]); console.log('SUCCESS, chapters:', data.chapters?.length); } catch(e) { console.log('FAILED:', e.message.substring(0, 80)); } } else { console.log('No match found'); } // Let's test the actual structure around position 1624 console.log('\n=== TEST 3: Structural analysis ==='); const pos = 1624; console.log('At pos', pos, ':'); console.log(' Char:', JSON.stringify(aiResponse[pos]), 'code:', aiResponse.charCodeAt(pos)); // Find the last complete property before pos 1624 // Look for patterns like "propertyName":value or "propertyName":[" or "propertyName":{ const beforeError = aiResponse.substring(0, pos); const lastPropMatch = beforeError.match(/"([^"]+)":\s*[^\[{,"]+$/); console.log('Last property value before error:', lastPropMatch ? lastPropMatch[0] : 'none'); // Let's also check if there's a 0x00 embedded null byte that didn't show up in our check console.log('\n=== TEST 4: Byte-level analysis ==='); const bytes = Buffer.from(aiResponse, 'utf8'); console.log('Buffer length:', bytes.length); for (let i = 1620; i < 1630; i++) { console.log(' byte', i, ':', bytes[i], '(char:', String.fromCharCode(bytes[i]), ')'); } // Check the original file for any 0x00 bytes that might be stripped console.log('\n=== TEST 5: Original file check ==='); const fileBytes = fs.readFileSync('temp/rich-outline-fail_57_1779015509994.txt'); console.log('File size:', fileBytes.length); const aiStartMarker = '========== AI 原始响应 '; const aiStartIdx = fileBytes.indexOf(aiStartMarker); const headerEndIdxBytes = fileBytes.indexOf(Buffer.from(' =========='), aiStartIdx); const aiContentStart = fileBytes.indexOf(Buffer.from('\n'), headerEndIdxBytes) + 1; const aiContentEnd = fileBytes.indexOf(Buffer.from('\n\n========== 响应结尾'), aiContentStart); console.log('AI content start offset:', aiContentStart, 'end offset:', aiContentEnd); console.log('AI content length from file:', aiContentEnd - aiContentStart); // Check for null bytes in the file let nullCount = 0; for (let i = aiContentStart; i < aiContentEnd; i++) { if (fileBytes[i] === 0) nullCount++; } console.log('Null bytes in AI content:', nullCount);