fix: report errors to progress comment when agent fails without throwing (#376)

* fix: report errors to progress comment when agent fails without throwing

when an agent returns success: false without throwing (e.g., opencode exits
with code 0 despite provider errors), the catch block in main.ts is never
reached, leaving the progress comment stuck on "leaping into action."

two fixes:
- opencode: return success: false when 0 events processed and a provider
  error was detected (converts silent failures to explicit failures)
- main.ts: after handleAgentResult, check if the progress comment was ever
  updated — if not, report the error to the comment as a safety net

Co-authored-by: Cursor <cursoragent@cursor.com>

* address review: use result directly and force failure on unreported progress

* refactor: move safety-net logic into handleAgentResult

---------

Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Anna Bocharova <robin_tail@me.com>
This commit is contained in:
pullfrog[bot]
2026-02-26 08:36:36 +00:00
committed by pullfrog[bot]
parent 1ed3da8273
commit 6311138132
4 changed files with 80 additions and 12 deletions
+9
View File
@@ -437,6 +437,15 @@ export const opencode = agent({
};
}
if (eventCount === 0 && lastProviderError) {
return {
success: false,
output: finalOutput || output,
error: `provider error: ${lastProviderError}`,
usage,
};
}
return {
success: true,
output: finalOutput || output,
+35 -6
View File
@@ -146353,6 +146353,14 @@ ${stderrContext}`);
usage
};
}
if (eventCount === 0 && lastProviderError) {
return {
success: false,
output: finalOutput || output,
error: `provider error: ${lastProviderError}`,
usage
};
}
return {
success: true,
output: finalOutput || output,
@@ -147335,18 +147343,34 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
}
// utils/run.ts
function handleAgentResult(result) {
if (!result.success) {
async function handleAgentResult(ctx) {
if (!ctx.result.success) {
return {
success: false,
error: result.error || "Agent execution failed",
output: result.output
error: ctx.result.error || "Agent execution failed",
output: ctx.result.output
};
}
if (!ctx.toolState.wasUpdated && ctx.toolState.progressCommentId && !ctx.silent) {
const error49 = ctx.result.error || "agent completed without reporting progress";
try {
await reportErrorToComment({
toolState: ctx.toolState,
error: error49,
title: "Error"
});
} catch {
}
return {
success: false,
error: error49,
output: ctx.result.output || ""
};
}
log.success("Task complete.");
return {
success: true,
output: result.output || ""
output: ctx.result.output || ""
};
}
@@ -147696,8 +147720,13 @@ ${instructions.user}` : null,
if (toolState.output) {
log.info(`::pullfrog-output::${Buffer.from(toolState.output).toString("base64")}`);
}
const mainResult = await handleAgentResult({
result,
toolState,
silent: payload.event.silent ?? false
});
return {
...handleAgentResult(result),
...mainResult,
result: toolState.output
};
} catch (_) {
+7 -1
View File
@@ -235,8 +235,14 @@ export async function main(): Promise<MainResult> {
log.info(`::pullfrog-output::${Buffer.from(toolState.output).toString("base64")}`);
}
const mainResult = await handleAgentResult({
result,
toolState,
silent: payload.event.silent ?? false,
});
return {
...handleAgentResult(result),
...mainResult,
result: toolState.output,
};
} catch (error) {
+29 -5
View File
@@ -1,13 +1,37 @@
import type { AgentResult } from "../agents/shared.ts";
import type { MainResult } from "../main.ts";
import type { ToolState } from "../mcp/server.ts";
import { log } from "./cli.ts";
import { reportErrorToComment } from "./errorReport.ts";
export function handleAgentResult(result: AgentResult): MainResult {
if (!result.success) {
export interface HandleAgentResultParams {
result: AgentResult;
toolState: ToolState;
silent: boolean | undefined;
}
export async function handleAgentResult(ctx: HandleAgentResultParams): Promise<MainResult> {
if (!ctx.result.success) {
return {
success: false,
error: result.error || "Agent execution failed",
output: result.output!,
error: ctx.result.error || "Agent execution failed",
output: ctx.result.output!,
};
}
if (!ctx.toolState.wasUpdated && ctx.toolState.progressCommentId && !ctx.silent) {
const error = ctx.result.error || "agent completed without reporting progress";
try {
await reportErrorToComment({
toolState: ctx.toolState,
error,
title: "Error",
});
} catch {}
return {
success: false,
error,
output: ctx.result.output || "",
};
}
@@ -15,6 +39,6 @@ export function handleAgentResult(result: AgentResult): MainResult {
return {
success: true,
output: result.output || "",
output: ctx.result.output || "",
};
}