Skip to content

Commit cb74276

Browse files
committed
fix: infinite loop
1 parent df07b5b commit cb74276

3 files changed

Lines changed: 27 additions & 3 deletions

File tree

src/sandbox/run-agent.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
import type { Sandbox as SandboxType } from "@vercel/sandbox";
2-
import { getWritable } from "workflow";
2+
import { getWritable, FatalError } from "workflow";
33
import { buildAgentCommand, parseAgentOutput, formatStreamEvent } from "./agent-runner.js";
44
import type { AgentOutput } from "./agent-runner.js";
55
import { SandboxManager } from "./manager.js";
66

7+
const NON_RETRYABLE_PATTERNS = [
8+
/credit balance is too low/i,
9+
/insufficient.?quota/i,
10+
/billing/i,
11+
/invalid.?api.?key/i,
12+
/authentication/i,
13+
/unauthorized/i,
14+
/permission.?denied/i,
15+
];
16+
717
type SandboxInstance = Awaited<ReturnType<typeof SandboxType.create>>;
818

919
interface RunAgentOptions {
@@ -69,10 +79,22 @@ export async function runAgent(
6979

7080
const raw = stdout.trim() || stderr.trim();
7181
const output = parseAgentOutput(raw);
82+
83+
const combinedText = `${output.error ?? ""} ${stderr}`;
84+
if (NON_RETRYABLE_PATTERNS.some((p) => p.test(combinedText))) {
85+
throw new FatalError(`Non-retryable agent error: ${output.error ?? stderr.slice(0, 500)}`);
86+
}
87+
7288
return { output, files };
7389
} catch (err) {
7490
await manager.runEndHook(sandbox).catch(() => {});
7591
const files = await manager.extractChanges(sandbox).catch(() => []);
92+
93+
const msg = (err as Error).message ?? "";
94+
if (NON_RETRYABLE_PATTERNS.some((p) => p.test(msg))) {
95+
throw new FatalError(`Non-retryable agent error: ${msg}`);
96+
}
97+
7698
throw Object.assign(err as Error, { files });
7799
} finally {
78100
await manager.teardown(sandbox);

src/workflows/implementation.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ async function runAgentInSandbox(
6666
const sandbox = await manager.provision(branchName, requirementsMd);
6767
return runAgent({ sandbox, manager, model: env.CLAUDE_MODEL, debug: env.DEBUG_AGENT });
6868
}
69+
runAgentInSandbox.maxRetries = 0;
6970

7071
async function pushChanges(
7172
branchName: string,
@@ -165,7 +166,7 @@ export async function implementationWorkflow(ticketId: string) {
165166
return;
166167
}
167168

169+
await moveTicket(ticketId, env.COLUMN_BACKLOG);
168170
await notifySlack(`Task ${ticket.identifier} failed: ${output.error ?? "unknown error"}`);
169171
await unregisterRun(ticket.identifier);
170-
throw new Error(`Agent failed for ${ticketId}: ${output.error}`);
171172
}

src/workflows/review-fix.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ async function runFixingAgentInSandbox(
7979
const sandbox = await manager.provision(branchName, requirementsMd);
8080
return runAgent({ sandbox, manager, model: env.CLAUDE_MODEL, debug: env.DEBUG_AGENT });
8181
}
82+
runFixingAgentInSandbox.maxRetries = 0;
8283

8384
async function pushChanges(
8485
branchName: string,
@@ -146,7 +147,7 @@ export async function reviewFixWorkflow(
146147
return;
147148
}
148149

150+
await moveTicket(ticketId, env.COLUMN_BACKLOG);
149151
await notifySlack(`Task ${ticket.identifier} review-fix failed: ${output.error ?? "unknown error"}`);
150152
await unregisterRun(ticket.identifier);
151-
throw new Error(`Agent failed for ${ticketId}: ${output.error}`);
152153
}

0 commit comments

Comments
 (0)