| null>(null);
const fetchRun = useCallback(async () => {
@@ -124,6 +134,24 @@ export function RunDetail({ runId }: { runId: string }) {
}
}, [runId]);
+ const retrigger = useCallback(async () => {
+ setRetriggering(true);
+ setRetriggerError(null);
+ try {
+ const res = await fetch(`/api/runs/${runId}/retrigger`, {
+ method: "POST",
+ });
+ const body = await res.json();
+ if (!res.ok)
+ throw new Error(body?.error ?? `Request failed (${res.status})`);
+ // Left disabled through the navigation; the remount clears it.
+ router.push(`/runs/${(body as RunRef).run_id}`);
+ } catch (err) {
+ setRetriggerError((err as Error).message);
+ setRetriggering(false);
+ }
+ }, [runId, router]);
+
if (!run && error) {
return {error}
;
}
@@ -159,12 +187,27 @@ export function RunDetail({ runId }: { runId: string }) {
)}
-
- ← all runs
-
+
+ {isFailed(run.status) && (
+
+ )}
+
+ ← all runs
+
+
{error && Refresh error: {error}
}
+ {retriggerError && (
+ Re-run failed: {retriggerError}
+ )}
Run
diff --git a/services/hackbot-ui/lib/types.ts b/services/hackbot-ui/lib/types.ts
index 1fc07ab664..1f586f116e 100644
--- a/services/hackbot-ui/lib/types.ts
+++ b/services/hackbot-ui/lib/types.ts
@@ -17,6 +17,10 @@ export function isTerminal(status: RunStatus): boolean {
return TERMINAL_STATUSES.includes(status);
}
+export function isFailed(status: RunStatus): boolean {
+ return status === "failed" || status === "timed_out";
+}
+
export interface AgentDescriptor {
name: string;
description: string;