import type { SpawnError } from "@uncaged/nerve-workflow-utils"; export async function runWithRetries( run: () => Promise< | { ok: true; stdout: string; stderr: string } | { ok: false; error: SpawnError; lastStdout: string; lastStderr: string } >, maxAttempts: number, ): Promise< | { ok: true; stdout: string; stderr: string; attemptsUsed: number } | { ok: false; error: SpawnError; attemptsUsed: number; lastStdout: string; lastStderr: string } > { let attemptsUsed = 0; let lastError: SpawnError | null = null; let lastStdout = ""; let lastStderr = ""; while (attemptsUsed < maxAttempts) { attemptsUsed += 1; const current = await run(); if (current.ok) { return { ok: true, stdout: current.stdout, stderr: current.stderr, attemptsUsed }; } lastError = current.error; lastStdout = current.lastStdout; lastStderr = current.lastStderr; if (attemptsUsed < maxAttempts) { const backoffMs = Math.min(1000 * 2 ** (attemptsUsed - 1), 4000); await new Promise((resolve) => setTimeout(resolve, backoffMs)); } } if (lastError === null) { return { ok: false, error: { kind: "spawn_failed", message: "unknown retry failure" }, attemptsUsed, lastStdout, lastStderr, }; } return { ok: false, error: lastError, attemptsUsed, lastStdout, lastStderr }; }