mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 06:42:03 +00:00
fix(suggestions): Improve JSON extraction for Cursor responses
Cursor responses may include text after the JSON object, causing
JSON.parse to fail. Added multi-strategy extraction similar to
validate-issue.ts:
1. Try extracting from ```json code block
2. Try extracting from ``` code block
3. Try finding {"suggestions" and matching braces
4. Try finding any JSON object with suggestions array
Uses bracket counting to find the correct closing brace.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -289,11 +289,10 @@ ${JSON.stringify(suggestionsSchema, null, 2)}`;
|
||||
})),
|
||||
});
|
||||
} else {
|
||||
// Fallback: try to parse from text (for backwards compatibility)
|
||||
// Fallback: try to parse from text using multiple strategies
|
||||
logger.warn('No structured output received, attempting to parse from text');
|
||||
const jsonMatch = responseText.match(/\{[\s\S]*"suggestions"[\s\S]*\}/);
|
||||
if (jsonMatch) {
|
||||
const parsed = JSON.parse(jsonMatch[0]);
|
||||
const parsed = extractSuggestionsJson(responseText);
|
||||
if (parsed && parsed.suggestions) {
|
||||
events.emit('suggestions:event', {
|
||||
type: 'suggestions_complete',
|
||||
suggestions: parsed.suggestions.map((s: Record<string, unknown>, i: number) => ({
|
||||
@@ -323,3 +322,99 @@ ${JSON.stringify(suggestionsSchema, null, 2)}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract suggestions JSON from response text using multiple strategies.
|
||||
* Handles various formats: markdown code blocks, raw JSON, etc.
|
||||
*/
|
||||
function extractSuggestionsJson(
|
||||
responseText: string
|
||||
): { suggestions: Array<Record<string, unknown>> } | null {
|
||||
const strategies = [
|
||||
// Strategy 1: JSON in ```json code block
|
||||
() => {
|
||||
const match = responseText.match(/```json\s*([\s\S]*?)```/);
|
||||
if (match) {
|
||||
return JSON.parse(match[1].trim());
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Strategy 2: JSON in ``` code block (no language specified)
|
||||
() => {
|
||||
const match = responseText.match(/```\s*([\s\S]*?)```/);
|
||||
if (match) {
|
||||
const content = match[1].trim();
|
||||
if (content.startsWith('{') && content.includes('"suggestions"')) {
|
||||
return JSON.parse(content);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Strategy 3: Find JSON object containing "suggestions" array
|
||||
() => {
|
||||
// Find the start of the JSON object
|
||||
const startIdx = responseText.indexOf('{"suggestions"');
|
||||
if (startIdx === -1) return null;
|
||||
|
||||
// Find matching closing brace by counting brackets
|
||||
let depth = 0;
|
||||
let endIdx = -1;
|
||||
for (let i = startIdx; i < responseText.length; i++) {
|
||||
if (responseText[i] === '{') depth++;
|
||||
if (responseText[i] === '}') {
|
||||
depth--;
|
||||
if (depth === 0) {
|
||||
endIdx = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (endIdx > startIdx) {
|
||||
return JSON.parse(responseText.slice(startIdx, endIdx));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Strategy 4: Find any JSON object with suggestions
|
||||
() => {
|
||||
const startIdx = responseText.indexOf('{');
|
||||
if (startIdx === -1) return null;
|
||||
|
||||
// Find matching closing brace
|
||||
let depth = 0;
|
||||
let endIdx = -1;
|
||||
for (let i = startIdx; i < responseText.length; i++) {
|
||||
if (responseText[i] === '{') depth++;
|
||||
if (responseText[i] === '}') {
|
||||
depth--;
|
||||
if (depth === 0) {
|
||||
endIdx = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (endIdx > startIdx) {
|
||||
const parsed = JSON.parse(responseText.slice(startIdx, endIdx));
|
||||
if (parsed.suggestions && Array.isArray(parsed.suggestions)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
];
|
||||
|
||||
for (const strategy of strategies) {
|
||||
try {
|
||||
const result = strategy();
|
||||
if (result && result.suggestions && Array.isArray(result.suggestions)) {
|
||||
logger.debug('Successfully extracted suggestions JSON');
|
||||
return result;
|
||||
}
|
||||
} catch {
|
||||
// Strategy failed, try next
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user