Skip to content

fix: make AI summary JSON parsing more robust#69

Merged
AmintaCCCP merged 1 commit intomainfrom
fix/issue-67-ai-summary-json-parse
Apr 2, 2026
Merged

fix: make AI summary JSON parsing more robust#69
AmintaCCCP merged 1 commit intomainfrom
fix/issue-67-ai-summary-json-parse

Conversation

@AmintaCCCP
Copy link
Copy Markdown
Owner

@AmintaCCCP AmintaCCCP commented Apr 2, 2026

Summary

  • increase AI analysis token budget from 400 to 700 to reduce truncated JSON responses
  • strip fenced ```json code blocks before parsing AI output
  • replace fragile greedy regex extraction with balanced-brace JSON extraction
  • keep fallback behavior when the AI response still does not contain a complete JSON object

Why

Issue #67 reports garbled AI summaries. The core problem is not display encoding, but brittle parsing when the model returns:

  • fenced JSON blocks
  • extra explanatory text around JSON
  • truncated JSON caused by token limits

The previous implementation used a greedy regex to extract { ... }, which fails easily when the response is incomplete or wrapped in markdown.

Validation

  • built successfully with npm run build
  • verified the fix only touches src/services/aiService.ts

Closes #67

Summary by CodeRabbit

Release Notes

  • Improvements
    • Enhanced AI-powered repository analysis with increased processing capacity to handle larger and more complex codebases.
    • Strengthened response parsing and validation mechanisms for improved reliability and accuracy of generated analyses.
    • Improved error handling and preprocessing of AI outputs for more consistent results.
    • Refined fallback summary generation for better handling of edge cases.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

This change improves the AI response parsing robustness in aiService.ts by increasing the token limit for repository analysis from 400 to 700, restructuring JSON extraction to handle Markdown code fences, implementing balanced brace tracking for JSON parsing, and adding stricter field validation with conditional fallback generation.

Changes

Cohort / File(s) Summary
AI Response Parsing Improvements
src/services/aiService.ts
Increased maxTokens from 400 to 700 for repository analysis. Refactored parseAIResponse to trim and strip Markdown \``jsoncode fences, implement two-step JSON parsing (direct parse, then balanced brace scanning with string/escape state tracking), validatesummaryas non-empty string, filtertagsandplatformsto string values before slicing, and conditionally append...` to fallback summary based on length.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

A rabbit hops through JSON dreams, 🐰
Where braces balance, nothing seems
Quite scrambled now with cleaner code,
The AI's words down clearer road,
More tokens fuel the thoughtful flame ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: making AI summary JSON parsing more robust, which matches the core fixes implemented in the code (token increase, markdown stripping, and balanced-brace extraction).
Linked Issues check ✅ Passed The code changes directly address issue #67's garbled JSON problem by stripping markdown fences, implementing balanced-brace JSON extraction, and increasing token budget to prevent truncation.
Out of Scope Changes check ✅ Passed All changes are scoped to src/services/aiService.ts and focus on JSON parsing robustness, directly supporting the linked issue #67 without introducing unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-67-ai-summary-json-parse

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/services/aiService.ts (1)

354-358: Code fence stripping only matches at exact boundaries.

The regex anchors (^ and $) only strip code fences when they're at the very start/end of the trimmed content. If the AI returns something like Here's the JSON:\n\``json\n{...}\n````, the fences won't be stripped.

This is acceptable since extractAndParseAIJson will still locate the JSON via brace-matching, but a more permissive pattern could handle additional edge cases:

🔧 Optional: More permissive code fence stripping
      const cleaned = content
        .trim()
-       .replace(/^```(?:json)?\s*/i, '')
-       .replace(/\s*```$/i, '')
+       .replace(/```(?:json)?\s*/gi, '')
        .trim();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/aiService.ts` around lines 354 - 358, The current code that
constructs the cleaned string only strips triple-backtick fences when they are
at the absolute start/end (the const cleaned block); change the regexes to
remove any triple-backtick fences (optionally followed/preceded by "json")
anywhere in content rather than using ^/$ anchors (e.g., replace occurrences of
/```(?:json)?\s*/gi and /```/gi or a single global pattern) so cleaned will have
fences removed even when they are not the exact boundaries; update the
replacement logic inside the const cleaned definition in aiService.ts
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/services/aiService.ts`:
- Around line 370-375: The current return uses cleaned.substring(0, 50) which
yields an empty string when cleaned is empty; update the summary fallback so
that if cleaned is falsy or trimmed length is 0 it returns a clear message like
"Unable to generate summary" (or "Analysis failed" depending on context) instead
of an empty string—modify the return logic where cleaned is used (the block that
builds { summary: ..., tags: [], platforms: [] }) to check cleaned.trim().length
and choose the explicit fallback message, otherwise keep the existing
substring(0, 50) + ellipsis behavior.

---

Nitpick comments:
In `@src/services/aiService.ts`:
- Around line 354-358: The current code that constructs the cleaned string only
strips triple-backtick fences when they are at the absolute start/end (the const
cleaned block); change the regexes to remove any triple-backtick fences
(optionally followed/preceded by "json") anywhere in content rather than using
^/$ anchors (e.g., replace occurrences of /```(?:json)?\s*/gi and /```/gi or a
single global pattern) so cleaned will have fences removed even when they are
not the exact boundaries; update the replacement logic inside the const cleaned
definition in aiService.ts accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 00b09e19-74b0-4afd-b419-912a0a097877

📥 Commits

Reviewing files that changed from the base of the PR and between 60c5787 and 583841f.

📒 Files selected for processing (1)
  • src/services/aiService.ts

Comment on lines +370 to 375

return {
summary: content.substring(0, 50) + '...',
summary: cleaned.substring(0, 50) + (cleaned.length > 50 ? '...' : ''),
tags: [],
platforms: [],
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Empty content fallback yields an empty summary string.

If cleaned is empty (e.g., the AI returned only code fences with no content), cleaned.substring(0, 50) returns "". This is inconsistent with the other fallback paths that return explicit messages like "Unable to generate summary" (line 365) or "Analysis failed" (line 379).

🔧 Proposed fix for consistency
      return {
-       summary: cleaned.substring(0, 50) + (cleaned.length > 50 ? '...' : ''),
+       summary: cleaned.trim()
+         ? cleaned.substring(0, 50) + (cleaned.length > 50 ? '...' : '')
+         : (this.language === 'zh' ? '无法生成概述' : 'Unable to generate summary'),
        tags: [],
        platforms: [],
      };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return {
summary: content.substring(0, 50) + '...',
summary: cleaned.substring(0, 50) + (cleaned.length > 50 ? '...' : ''),
tags: [],
platforms: [],
};
return {
summary: cleaned.trim()
? cleaned.substring(0, 50) + (cleaned.length > 50 ? '...' : '')
: (this.language === 'zh' ? '无法生成概述' : 'Unable to generate summary'),
tags: [],
platforms: [],
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/aiService.ts` around lines 370 - 375, The current return uses
cleaned.substring(0, 50) which yields an empty string when cleaned is empty;
update the summary fallback so that if cleaned is falsy or trimmed length is 0
it returns a clear message like "Unable to generate summary" (or "Analysis
failed" depending on context) instead of an empty string—modify the return logic
where cleaned is used (the block that builds { summary: ..., tags: [],
platforms: [] }) to check cleaned.trim().length and choose the explicit fallback
message, otherwise keep the existing substring(0, 50) + ellipsis behavior.

@AmintaCCCP AmintaCCCP merged commit 825ab55 into main Apr 2, 2026
5 checks passed
@AmintaCCCP AmintaCCCP deleted the fix/issue-67-ai-summary-json-parse branch April 2, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI 总结中有 json 乱码

1 participant