fix(pearl): display responses as text instead of raw JSON blocks#251
fix(pearl): display responses as text instead of raw JSON blocks#251srivtx wants to merge 1 commit intobubblelabai:mainfrom
Conversation
Use parseJsonWithFallbacks instead of raw JSON.parse to handle AI responses wrapped in markdown code blocks (```json ... ```). Also updated error messages to be user-friendly instead of including raw response text with markdown formatting. Fixes bubblelabai#238
📝 WalkthroughWalkthroughUpdates JSON parsing in two AI service files from direct Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Suggested PR title from PearlTitle: Body: ChangesImproves JSON response parsing and error handling in MilkTea and Pearl AI agents. What Changed
Error Message ImprovementsBefore:
After:
WhyAI models sometimes wrap JSON responses in markdown code blocks, which causes standard JSON parsing to fail. The new Files Modified
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/bubblelab-api/src/services/ai/milktea.ts (1)
517-522: LGTM! Proper use of parseJsonWithFallbacks to handle markdown-wrapped JSON.The implementation correctly replaces direct
JSON.parsewithparseJsonWithFallbacks, which handles AI responses wrapped in markdown code blocks (e.g., ````json ... ```). The validation of bothparseResult.successand `parseResult.parsed` before proceeding, followed by Zod schema validation, ensures robust error handling.Optional: Consider explicit undefined check
The condition
!parseResult.parseduses falsy evaluation, which could theoretically be problematic ifparsedis a valid but falsy value like0,false, or"". While this is unlikely given the expected object type, you could make it more explicit:-if (!parseResult.success || !parseResult.parsed) { +if (!parseResult.success || parseResult.parsed === undefined) {However, this is a minor pedantic concern and not necessary for this use case.
apps/bubblelab-api/src/services/ai/pearl.ts (1)
598-600: Add a brief comment explaining the array handling logic.The
parseJsonWithFallbacksfunction can return either an object or an array at the top level. This code handles the case where it returns an array by extracting the first element. While this pattern appears elsewhere in the codebase (e.g., slack-formatter-agent.ts, coffee.ts), similar implementations in other files document why arrays are handled. A comment here would improve clarity:// Handle case where AI returns an array of responses instead of a single object if (Array.isArray(parsedResponse) && parsedResponse.length > 0) { parsedResponse = parsedResponse[0]; }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/bubblelab-api/src/services/ai/milktea.tsapps/bubblelab-api/src/services/ai/pearl.ts
🧰 Additional context used
🧬 Code graph analysis (1)
apps/bubblelab-api/src/services/ai/milktea.ts (2)
packages/bubble-core/src/index.ts (1)
parseJsonWithFallbacks(139-139)packages/bubble-shared-schemas/src/milk-tea.ts (1)
MilkTeaAgentOutputSchema(93-97)
🔇 Additional comments (3)
apps/bubblelab-api/src/services/ai/milktea.ts (1)
527-528: LGTM! User-friendly error message improves UX.The updated error message provides a clear, actionable message to users without exposing potentially confusing raw AI responses or markdown formatting. The detailed error information is still preserved in the
errorfield (line 530) for debugging purposes, which maintains a good balance between user experience and developer observability.apps/bubblelab-api/src/services/ai/pearl.ts (2)
591-597: LGTM! Well-documented parsing logic handles markdown-wrapped JSON.The implementation correctly uses
parseJsonWithFallbacksto handle AI responses wrapped in markdown code blocks. The explanatory comments (lines 591-592) add valuable context about why this utility is used instead of directJSON.parse, making the code more maintainable. The validation checks and error handling are robust.
615-615: LGTM! User-friendly error messages with clear documentation.The error messages are now generic and actionable, avoiding exposure of potentially confusing raw AI responses with markdown formatting. The explanatory comments (lines 675-676) clearly document why raw
responseTextis excluded from user-facing messages, which aids future maintainers. The detailed error information is still preserved in theerrorfield for debugging, maintaining good observability.Also applies to: 675-680
Fixes #238
Summary
When the AI model wraps its JSON response in markdown code blocks, JSON.parse() fails and the raw response (including markdown) was displayed to users as a "JSON Response" block.
This fix uses the existing parseJsonWithFallbacks() utility which properly strips markdown formatting before parsing, allowing the clean message text to be displayed.
Related Issues
Fixes #238
Type of Change
Checklist
Screenshots (if applicable)
N/A - Backend fix, no UI changes.
Additional Context
The parseJsonWithFallbacks() function is already used elsewhere in the codebase and has 60 passing tests covering markdown-wrapped JSON scenarios.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.