debug-parse16.js 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. const fs = require('fs');
  2. const content = fs.readFileSync('temp/rich-outline-fail_57_1779015509994.txt', 'utf-8');
  3. const marker = '========== AI 原始响应 ';
  4. const markerIdx = content.indexOf(marker);
  5. const headerEndIdx = content.indexOf(' ==========', markerIdx);
  6. const aiStart = content.indexOf('\n', headerEndIdx) + 1;
  7. const aiEnd = content.indexOf('\n\n', aiStart);
  8. const aiResponse = content.substring(aiStart, aiEnd);
  9. console.log('AI response length:', aiResponse.length);
  10. // Extract the substring around the error and try to parse it
  11. const pos = 1624;
  12. const start = Math.max(0, pos - 500);
  13. const end = Math.min(aiResponse.length, pos + 200);
  14. const snippet = aiResponse.substring(start, end);
  15. console.log('\n=== Snippet around error (500 before, 200 after pos 1624) ===');
  16. console.log('Start offset:', start, 'End offset:', end);
  17. console.log('JSON snippet:', JSON.stringify('...' + snippet + '...'));
  18. // Now let's try to create a mini JSON with just the part around the error
  19. // and see if we can identify the issue
  20. const beforeSnippet = aiResponse.substring(0, pos);
  21. const afterSnippet = aiResponse.substring(pos);
  22. // Try parsing a truncated version that ends at the error position
  23. console.log('\n=== Try parsing up to error position ===');
  24. try {
  25. JSON.parse(beforeSnippet);
  26. console.log('Parsed OK (unexpected)');
  27. } catch(e) {
  28. console.log('Parse error at:', e.message);
  29. }
  30. // Try parsing from error position onwards
  31. console.log('\n=== Try parsing from error position ===');
  32. try {
  33. const data = JSON.parse('{' + afterSnippet);
  34. console.log('Parsed OK, chapters:', data.chapters?.length);
  35. } catch(e) {
  36. console.log('Parse error at:', e.message.substring(0, 80));
  37. }
  38. // Let me check if maybe there's a weird character right before position 1624
  39. // that I'm missing
  40. console.log('\n=== Detailed byte analysis ===');
  41. for (let i = 1618; i < 1635; i++) {
  42. const code = aiResponse.charCodeAt(i);
  43. console.log(' pos', i, ':', 'U+' + code.toString(16).toUpperCase().padStart(4, '0'), JSON.stringify(aiResponse[i]));
  44. }
  45. // Let's also check if maybe there's a BOM or something
  46. console.log('\nFirst char:', aiResponse.charCodeAt(0), JSON.stringify(aiResponse[0]));
  47. console.log('First 3 chars:', aiResponse.substring(0, 3).split('').map(c => c.charCodeAt(0)));
  48. // Try using TextEncoder to get actual bytes
  49. const encoder = new TextEncoder();
  50. const bytes = encoder.encode(aiResponse);
  51. console.log('\n=== UTF-8 bytes around position 1624 (converted to code units) ===');
  52. // Since the string is 18719 chars but UTF-8 bytes is 38333,
  53. // that means most chars are 3-byte Chinese chars
  54. // Let's find the byte offset for UTF-16 position 1624
  55. let utf8Offset = 0;
  56. for (let utf16Idx = 0; utf16Idx < 1624; utf16Idx++) {
  57. const code = aiResponse.charCodeAt(utf16Idx);
  58. if (code <= 0x7F) utf8Offset += 1;
  59. else if (code <= 0x7FF) utf8Offset += 2;
  60. else if (code <= 0xFFFF) utf8Offset += 3;
  61. else utf8Offset += 4;
  62. }
  63. console.log('UTF-8 offset for UTF-16 pos 1624:', utf8Offset);
  64. console.log('UTF-8 bytes around that position:');
  65. for (let i = utf8Offset - 5; i < utf8Offset + 10; i++) {
  66. if (i >= 0 && i < bytes.length) {
  67. console.log(' byte', i, ':', bytes[i], String.fromCharCode(bytes[i]));
  68. }
  69. }
  70. // Now check if those UTF-8 bytes form valid UTF-8 characters
  71. console.log('\n=== Checking UTF-8 validity around position ===');
  72. // 3-byte UTF-8 for CJK: 1110xxxx 10xxxxxx 10xxxxxx
  73. // Let's see what the bytes around utf8Offset actually represent
  74. for (let i = utf8Offset - 3; i < utf8Offset + 6; i++) {
  75. if (i >= 0 && i < bytes.length) {
  76. const b = bytes[i];
  77. console.log(' byte', i, ':', b, 'binary:', b.toString(2).padStart(8, '0'));
  78. }
  79. }