| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- 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);
- // Extract the substring around the error and try to parse it
- const pos = 1624;
- const start = Math.max(0, pos - 500);
- const end = Math.min(aiResponse.length, pos + 200);
- const snippet = aiResponse.substring(start, end);
- console.log('\n=== Snippet around error (500 before, 200 after pos 1624) ===');
- console.log('Start offset:', start, 'End offset:', end);
- console.log('JSON snippet:', JSON.stringify('...' + snippet + '...'));
- // Now let's try to create a mini JSON with just the part around the error
- // and see if we can identify the issue
- const beforeSnippet = aiResponse.substring(0, pos);
- const afterSnippet = aiResponse.substring(pos);
- // Try parsing a truncated version that ends at the error position
- console.log('\n=== Try parsing up to error position ===');
- try {
- JSON.parse(beforeSnippet);
- console.log('Parsed OK (unexpected)');
- } catch(e) {
- console.log('Parse error at:', e.message);
- }
- // Try parsing from error position onwards
- console.log('\n=== Try parsing from error position ===');
- try {
- const data = JSON.parse('{' + afterSnippet);
- console.log('Parsed OK, chapters:', data.chapters?.length);
- } catch(e) {
- console.log('Parse error at:', e.message.substring(0, 80));
- }
- // Let me check if maybe there's a weird character right before position 1624
- // that I'm missing
- console.log('\n=== Detailed byte analysis ===');
- for (let i = 1618; i < 1635; i++) {
- const code = aiResponse.charCodeAt(i);
- console.log(' pos', i, ':', 'U+' + code.toString(16).toUpperCase().padStart(4, '0'), JSON.stringify(aiResponse[i]));
- }
- // Let's also check if maybe there's a BOM or something
- console.log('\nFirst char:', aiResponse.charCodeAt(0), JSON.stringify(aiResponse[0]));
- console.log('First 3 chars:', aiResponse.substring(0, 3).split('').map(c => c.charCodeAt(0)));
- // Try using TextEncoder to get actual bytes
- const encoder = new TextEncoder();
- const bytes = encoder.encode(aiResponse);
- console.log('\n=== UTF-8 bytes around position 1624 (converted to code units) ===');
- // Since the string is 18719 chars but UTF-8 bytes is 38333,
- // that means most chars are 3-byte Chinese chars
- // Let's find the byte offset for UTF-16 position 1624
- let utf8Offset = 0;
- for (let utf16Idx = 0; utf16Idx < 1624; utf16Idx++) {
- const code = aiResponse.charCodeAt(utf16Idx);
- if (code <= 0x7F) utf8Offset += 1;
- else if (code <= 0x7FF) utf8Offset += 2;
- else if (code <= 0xFFFF) utf8Offset += 3;
- else utf8Offset += 4;
- }
- console.log('UTF-8 offset for UTF-16 pos 1624:', utf8Offset);
- console.log('UTF-8 bytes around that position:');
- for (let i = utf8Offset - 5; i < utf8Offset + 10; i++) {
- if (i >= 0 && i < bytes.length) {
- console.log(' byte', i, ':', bytes[i], String.fromCharCode(bytes[i]));
- }
- }
- // Now check if those UTF-8 bytes form valid UTF-8 characters
- console.log('\n=== Checking UTF-8 validity around position ===');
- // 3-byte UTF-8 for CJK: 1110xxxx 10xxxxxx 10xxxxxx
- // Let's see what the bytes around utf8Offset actually represent
- for (let i = utf8Offset - 3; i < utf8Offset + 6; i++) {
- if (i >= 0 && i < bytes.length) {
- const b = bytes[i];
- console.log(' byte', i, ':', b, 'binary:', b.toString(2).padStart(8, '0'));
- }
- }
|