feat: implement self-correcting compile loop (Ralph Loop) inside cloud agent runner

This commit is contained in:
2026-06-02 14:41:42 -07:00
parent 1a138b6d90
commit 49d7da6291

View File

@@ -15,6 +15,50 @@ import { resolvePrompt } from "./prompts/loader";
const MAX_TURNS = 45;
function runBuildVerification(
repoRoot: string,
appPath: string,
): { success: boolean; error?: string } {
const fs = require("fs") as typeof import("fs");
const path = require("path") as typeof import("path");
const { execSync } = require("child_process");
const absoluteAppPath = path.join(repoRoot, appPath);
const pkgJsonPath = path.join(absoluteAppPath, "package.json");
if (!fs.existsSync(pkgJsonPath)) {
return { success: true }; // No package.json, skip build check
}
try {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
// Only verify if there is an explicit build script
if (!pkg.scripts || !pkg.scripts.build) {
return { success: true };
}
console.log(
`[Ralph Loop] Running automatic build verification: npm run build inside ${absoluteAppPath}...`,
);
// Run npm run build with a 45s timeout to prevent hanging
execSync("npm run build", {
cwd: absoluteAppPath,
stdio: "pipe",
timeout: 45000,
});
return { success: true };
} catch (err: any) {
const stderr = err.stderr
? err.stderr.toString()
: err.message || String(err);
console.warn(`[Ralph Loop] Build verification failed:`, stderr);
return {
success: false,
error: stderr.slice(-3000), // Cap the log length to avoid flooding the prompt context
};
}
}
export interface OutputLine {
ts: string;
type: "step" | "stdout" | "stderr" | "info" | "error" | "done";
@@ -354,6 +398,37 @@ Do NOT run git commit or git push — the platform handles committing after you
continue;
}
// ── Cloud Build Verification (Ralph Loop integration) ──
if (opts.repoRoot && ralphIteration < 3) {
await emit({
ts: now(),
type: "info",
text: "🔍 [Ralph Loop] Initiating automatic build verification...",
});
const verification = runBuildVerification(opts.repoRoot, opts.appPath);
if (!verification.success) {
ralphIteration++;
await emit({
ts: now(),
type: "error",
text: `❌ [Ralph Loop] Build verification failed (iteration ${ralphIteration}/3). Feeding compilation errors back to the model...`,
});
history.push({
role: "user",
content: `Your previous edits completed, but the project's build check failed with compilation errors. Please fix these errors immediately so the build compiles clean:\n\n\`\`\`text\n${verification.error}\n\`\`\``,
});
continue;
} else {
await emit({
ts: now(),
type: "info",
text: "🟢 [Ralph Loop] Build verification passed successfully! 0 errors.",
});
}
}
// If fully complete, trigger auto-commit and finish
if (opts.autoApprove) {
await autoCommitAndDeploy(opts, task, emit);