Skip to content

Commit a249efa

Browse files
committed
Add auto-fix for incomplete diffs and API response monitoring
- Add stop_reason logging to detect if API response was truncated - Auto-fix missing +++ b/ lines (inserts correct path from --- a/ line) - Auto-fix incomplete +++ b/ lines (fixes truncated paths) - Re-validates diff after auto-fix - Should handle cases where model stops mid-generation - Logs API response completion status for debugging
1 parent 53584c5 commit a249efa

1 file changed

Lines changed: 64 additions & 11 deletions

File tree

.github/agent/agent.mjs

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,17 @@ async function callAI(promptText) {
981981
temperature: 0.2,
982982
messages: [{ role: "user", content: promptText }],
983983
});
984+
985+
// Check if response was truncated
986+
if (response.stop_reason === "max_tokens") {
987+
console.warn(`[AGENT] WARNING: Response was truncated due to max_tokens limit`);
988+
console.warn(`[AGENT] Response length: ${response.content[0].text.length} characters`);
989+
} else if (response.stop_reason === "stop_sequence") {
990+
console.log(`[AGENT] Response stopped at stop sequence`);
991+
} else {
992+
console.log(`[AGENT] Response completed normally (stop_reason: ${response.stop_reason})`);
993+
}
994+
984995
return response.content[0].text;
985996
} else if (provider === "openai") {
986997
const response = await aiClient.chat.completions.create({
@@ -1054,17 +1065,59 @@ if (validationResult.errors.length > 0 || diff.match(/\+\+\+ b\/[^\n]*$/m)) {
10541065
console.warn(`[AGENT] Diff length: ${diffLength} characters`);
10551066
console.warn(`[AGENT] Last 5 lines:\n${lastLines}`);
10561067

1057-
// Try to detect if this is a token limit or truncation issue
1058-
// Check for incomplete +++ b/ lines (truncated file paths)
1059-
const incompletePathMatch = diff.match(/\+\+\+ b\/[^\n]{1,10}$/m);
1060-
if (incompletePathMatch || (diffLength > 7000 && diff.match(/\+\+\+ b\/[^\n]*$/m))) {
1061-
const truncationReason = incompletePathMatch
1062-
? "Diff appears to be truncated mid-file-path (model stopped generating)"
1063-
: "Diff appears to be truncated (likely hit token limit)";
1064-
const errorMsg = `${truncationReason}. The AI model may have generated an incomplete diff.\n\nErrors:\n${validationResult.errors.join('\n')}\n\nDiff preview (last 500 chars):\n\`\`\`\n${diff.substring(Math.max(0, diffLength - 500))}\n\`\`\`\n\nPossible causes:\n- Model hit output token limit (check max_tokens setting)\n- Low API credits causing early termination\n- Input context too large, leaving insufficient room for output\n- Model stopped generating for other reasons\n\nSuggestions:\n- Check Anthropic account credits\n- Reduce input context size (fewer files)\n- Break task into smaller parts\n- Verify max_tokens is sufficient (currently 180K)`;
1065-
const errorDetails = formatErrorDetails(new Error(errorMsg), { diff: diff.substring(Math.max(0, diffLength - 1000)), files: validationResult.stats.filesChanged });
1066-
await handleError(new Error(errorMsg), "Incomplete Diff (Truncated)", { diff: diff.substring(Math.max(0, diffLength - 1000)), errorDetails });
1067-
// handleError calls process.exit(1), so we never reach here
1068+
// Try to auto-fix incomplete or missing +++ b/ lines
1069+
const lines = diff.split('\n');
1070+
let needsFix = false;
1071+
1072+
// Check for incomplete +++ b/ lines or missing +++ b/ lines after --- a/ lines
1073+
for (let i = 0; i < lines.length; i++) {
1074+
if (lines[i].startsWith('--- a/')) {
1075+
const oldPath = lines[i].substring(6).trim();
1076+
const nextLine = i + 1 < lines.length ? lines[i + 1] : '';
1077+
1078+
// Check if +++ b/ line is missing or incomplete
1079+
if (!nextLine.startsWith('+++ b/')) {
1080+
// Missing +++ b/ line - insert it
1081+
lines.splice(i + 1, 0, `+++ b/${oldPath}`);
1082+
needsFix = true;
1083+
console.log(`[AGENT] Auto-fixed missing +++ b/ line for: ${oldPath}`);
1084+
i++; // Skip the line we just added
1085+
} else if (nextLine.startsWith('+++ b/') && nextLine.length < 20) {
1086+
// Incomplete +++ b/ line - fix it
1087+
lines[i + 1] = `+++ b/${oldPath}`;
1088+
needsFix = true;
1089+
console.log(`[AGENT] Auto-fixed incomplete +++ b/ line: ${lines[i + 1]}`);
1090+
}
1091+
}
1092+
}
1093+
1094+
// If we made fixes, update diff and re-validate
1095+
if (needsFix) {
1096+
diff = lines.join('\n');
1097+
const fixedValidation = validateDiff(diff);
1098+
if (fixedValidation.isValid) {
1099+
console.log(`[AGENT] Diff validation passed after auto-fix`);
1100+
// Update validation result
1101+
Object.assign(validationResult, fixedValidation);
1102+
} else {
1103+
console.warn(`[AGENT] Auto-fix did not resolve all validation errors`);
1104+
// Update validation result with new errors
1105+
validationResult.errors = fixedValidation.errors;
1106+
}
1107+
}
1108+
1109+
// If still invalid after auto-fix attempt, report error
1110+
if (!validationResult.isValid) {
1111+
const incompletePathMatchAfterFix = diff.match(/\+\+\+ b\/[^\n]{1,10}$/m);
1112+
if (incompletePathMatchAfterFix || (diffLength > 7000 && diff.match(/\+\+\+ b\/[^\n]*$/m))) {
1113+
const truncationReason = incompletePathMatchAfterFix
1114+
? "Diff appears to be truncated mid-file-path (model stopped generating)"
1115+
: "Diff appears to be truncated (likely hit token limit)";
1116+
const errorMsg = `${truncationReason}. The AI model may have generated an incomplete diff.\n\nErrors:\n${validationResult.errors.join('\n')}\n\nDiff preview (last 500 chars):\n\`\`\`\n${diff.substring(Math.max(0, diffLength - 500))}\n\`\`\`\n\nPossible causes:\n- Model hit output token limit (check max_tokens setting)\n- Input context too large, leaving insufficient room for output\n- Model stopped generating for other reasons\n\nSuggestions:\n- Reduce input context size (fewer files) - already reduced to 400KB\n- Break task into smaller parts\n- Verify max_tokens is sufficient (currently 180K)`;
1117+
const errorDetails = formatErrorDetails(new Error(errorMsg), { diff: diff.substring(Math.max(0, diffLength - 1000)), files: validationResult.stats.filesChanged });
1118+
await handleError(new Error(errorMsg), "Incomplete Diff (Truncated)", { diff: diff.substring(Math.max(0, diffLength - 1000)), errorDetails });
1119+
// handleError calls process.exit(1), so we never reach here
1120+
}
10681121
}
10691122
}
10701123

0 commit comments

Comments
 (0)