debug-parse21.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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('Length:', aiResponse.length);
  10. // Goal: Find the chapters that are COMPLETE (both opening and closing braces)
  11. // by finding the last position where we have a valid chapter object
  12. // Strategy: Find all "chapters": [ patterns, then find where each chapter ends
  13. // A chapter ends when we see "}," or "]," patterns that close the chapter object
  14. // Actually, let's try a different approach: find the last complete "number":X in a chapters array
  15. // and work backwards to find the full chapter
  16. // First, find where chapters array starts
  17. const chaptersStart = aiResponse.indexOf('"chapters":[');
  18. console.log('Chapters array starts at:', chaptersStart);
  19. if (chaptersStart === -1) {
  20. console.log('No chapters array found');
  21. process.exit(1);
  22. }
  23. // Try to find where the JSON becomes invalid - that's our truncation point
  24. // Then extract all chapters before that
  25. let lastGoodPos = chaptersStart;
  26. let braceLevel = 0;
  27. let inString = false;
  28. let escapeNext = false;
  29. for (let i = chaptersStart; i < aiResponse.length; i++) {
  30. const ch = aiResponse[i];
  31. if (escapeNext) { escapeNext = false; continue; }
  32. if (ch === '\\') { escapeNext = true; continue; }
  33. if (ch === '"') { inString = !inString; continue; }
  34. if (inString) continue;
  35. if (ch === '{') braceLevel++;
  36. else if (ch === '}') braceLevel--;
  37. else if (ch === '[') braceLevel++;
  38. else if (ch === ']') braceLevel--;
  39. if (braceLevel < 0) {
  40. console.log('JSON goes negative at position', i, '- char', JSON.stringify(ch));
  41. break;
  42. }
  43. // Try to parse up to this point
  44. const sub = '{"outline":' + aiResponse.substring(chaptersStart, i + 1) + '}';
  45. try {
  46. JSON.parse(sub);
  47. lastGoodPos = i + 1;
  48. } catch(e) {
  49. // If it fails because braces are unbalanced, that's ok - we might be mid-chapter
  50. if (!e.message.includes('Unexpected end')) {
  51. // Some other error
  52. }
  53. }
  54. }
  55. console.log('Last position where prefix might be valid:', lastGoodPos);
  56. console.log('Prefix length:', lastGoodPos - chaptersStart);
  57. // Try to extract the complete chapters from the prefix
  58. const prefix = '{"outline":{"chapters":' + aiResponse.substring(chaptersStart + 13, lastGoodPos) + '}}';
  59. console.log('\nTrying to parse prefix as complete outline...');
  60. try {
  61. const data = JSON.parse(prefix);
  62. console.log('SUCCESS! Chapters:', data.outline?.chapters?.length);
  63. if (data.outline?.chapters?.length > 0) {
  64. console.log('First chapter:', data.outline.chapters[0].title);
  65. console.log('Last chapter:', data.outline.chapters[data.outline.chapters.length - 1].title);
  66. }
  67. } catch(e) {
  68. console.log('FAILED:', e.message.substring(0, 100));
  69. // Try a more aggressive approach - just extract complete chapter objects
  70. console.log('\n=== Trying chapter-by-chapter extraction ===');
  71. // Find all occurrences of "number":N where N is a number
  72. const chapterNumRegex = /"number":(\d+)/g;
  73. let match;
  74. let chapters = [];
  75. let lastEnd = chaptersStart + 13; // After "chapters":[
  76. while ((match = chapterNumRegex.exec(aiResponse)) !== null) {
  77. const num = parseInt(match[1]);
  78. const startPos = match.index;
  79. // Find the end of this chapter - look for }], or }},{ patterns
  80. let endSearchStart = startPos + match[0].length;
  81. // Find the next "number": pattern or end of chapters array
  82. const nextNumMatch = chapterNumRegex.exec(aiResponse.substring(endSearchStart));
  83. const endPos = nextNumMatch ? endSearchStart + nextNumMatch.index : aiResponse.lastIndexOf(']}', aiResponse.length);
  84. const chapterJson = '{"number":' + num + aiResponse.substring(startPos + 9, endPos);
  85. try {
  86. const chapter = JSON.parse(chapterJson);
  87. if (chapter.title && chapter.summary) {
  88. chapters.push(chapter);
  89. console.log('Found chapter', num + ':', chapter.title, 'length:', chapterJson.length);
  90. }
  91. } catch(e) {
  92. console.log('Chapter', num, 'parse failed:', e.message.substring(0, 50));
  93. }
  94. }
  95. console.log('\nTotal complete chapters found:', chapters.length);
  96. }