debug-parse17.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. // The error is at position 1624, char "{" code 123
  11. // Error: Expected double-quoted property name
  12. // This means when the parser hits {, it expected "propertyName": first
  13. // This can happen if:
  14. // 1. We're at the start of a new object but the previous object wasn't properly closed
  15. // 2. There's a structural error that makes the parser think we're in the wrong place
  16. // Let me trace the brace/bracket depth and check where it goes negative
  17. let inString = false;
  18. let escapeNext = false;
  19. let braceLevel = 0; // { }
  20. let bracketLevel = 0; // [ ]
  21. let pos = 0;
  22. let errorPos = 1624;
  23. for (let i = 0; i <= errorPos; i++) {
  24. const ch = aiResponse[i];
  25. if (escapeNext) { escapeNext = false; continue; }
  26. if (ch === '\\') { escapeNext = true; continue; }
  27. if (ch === '"') { inString = !inString; continue; }
  28. if (inString) continue;
  29. if (ch === '{') {
  30. braceLevel++;
  31. if (i === errorPos) {
  32. console.log('At error pos, opening brace, levels: brace=', braceLevel, 'bracket=', bracketLevel);
  33. }
  34. } else if (ch === '}') {
  35. braceLevel--;
  36. if (i === errorPos) {
  37. console.log('At error pos, closing brace, levels: brace=', braceLevel, 'bracket=', bracketLevel);
  38. }
  39. } else if (ch === '[') {
  40. bracketLevel++;
  41. if (i === errorPos) {
  42. console.log('At error pos, opening bracket, levels: brace=', braceLevel, 'bracket=', bracketLevel);
  43. }
  44. } else if (ch === ']') {
  45. bracketLevel--;
  46. if (i === errorPos) {
  47. console.log('At error pos, closing bracket, levels: brace=', braceLevel, 'bracket=', bracketLevel);
  48. }
  49. }
  50. // Check what levels are at errorPos-1 (the char before the error)
  51. if (i === errorPos - 1) {
  52. console.log('Before error pos (at ' + i + '):', JSON.stringify(ch), 'levels: brace=', braceLevel, 'bracket=', bracketLevel);
  53. }
  54. }
  55. console.log('\nAt error position 1624 itself, before processing it:');
  56. // Calculate levels BEFORE processing char at 1624
  57. let braceBefore = 0, bracketBefore = 0;
  58. inString = false;
  59. escapeNext = false;
  60. for (let i = 0; i < 1624; i++) {
  61. const ch = aiResponse[i];
  62. if (escapeNext) { escapeNext = false; continue; }
  63. if (ch === '\\') { escapeNext = true; continue; }
  64. if (ch === '"') { inString = !inString; continue; }
  65. if (inString) continue;
  66. if (ch === '{') braceBefore++;
  67. else if (ch === '}') braceBefore--;
  68. else if (ch === '[') bracketBefore++;
  69. else if (ch === ']') bracketBefore--;
  70. }
  71. console.log('Before processing char at 1624: braceLevel=' + braceBefore + ' bracketLevel=' + bracketBefore);
  72. console.log('Char at 1624 is:', JSON.stringify(aiResponse[1624]));
  73. // The char at 1624 is "{" - so after processing it, braceLevel would be braceBefore+1
  74. console.log('If we process {, braceLevel would become:', braceBefore + 1);
  75. // But the ERROR says at position 1624 we saw { and expected a property name
  76. // This means braceLevel must have been 0 BEFORE processing the {, meaning
  77. // we're trying to open a new object at the top level, which is fine IF we
  78. // just had a comma
  79. // Wait - let me check what's BEFORE the { at 1624
  80. console.log('\n=== Context before the { at 1624 ===');
  81. console.log(JSON.stringify(aiResponse.substring(1580, 1640)));
  82. // The substring shows: ...],\"mustNotRepeat\":[...],{\"number\":3,...
  83. // So it's: ]},{"number":3
  84. // That ] closes an array, } closes an object, , separates, { starts new object
  85. // This is valid if we're adding to a chapters array!
  86. // Let me try a different approach - parse the JSON and see where it fails
  87. // by trying to parse chunks
  88. console.log('\n=== Trying incremental parse ===');
  89. let lastGoodPos = 0;
  90. inString = false;
  91. escapeNext = false;
  92. braceLevel = 0;
  93. bracketLevel = 0;
  94. for (let i = 0; i < aiResponse.length; i++) {
  95. const ch = aiResponse[i];
  96. if (escapeNext) { escapeNext = false; continue; }
  97. if (ch === '\\') { escapeNext = true; continue; }
  98. if (ch === '"') { inString = !inString; continue; }
  99. if (inString) continue;
  100. if (ch === '{') braceLevel++;
  101. else if (ch === '}') braceLevel--;
  102. else if (ch === '[') bracketLevel++;
  103. else if (ch === ']') bracketLevel--;
  104. // Try parsing up to this point
  105. if ((ch === '}' || ch === ',') && braceLevel === 0 && bracketLevel === 0) {
  106. try {
  107. JSON.parse(aiResponse.substring(0, i + 1));
  108. lastGoodPos = i + 1;
  109. } catch(e) {
  110. if (i > 1600 && i < 1700) {
  111. console.log('Parse failed at', i, 'char', JSON.stringify(ch), 'error:', e.message.substring(0, 60));
  112. }
  113. }
  114. }
  115. }
  116. console.log('Last good parse position:', lastGoodPos);
  117. console.log('Context around last good:', JSON.stringify(aiResponse.substring(lastGoodPos - 20, lastGoodPos + 40)));