diff --git a/packages/cli/src/shared/agent-setup.ts b/packages/cli/src/shared/agent-setup.ts index 0b3677a6..d84d7912 100644 --- a/packages/cli/src/shared/agent-setup.ts +++ b/packages/cli/src/shared/agent-setup.ts @@ -51,7 +51,7 @@ async function installAgent( ): Promise { logStep(`Installing ${agentName}...`); const r = await asyncTryCatch(() => - withRetry(`${agentName} install`, () => wrapSshCall(runner.runServer(installCmd, timeoutSecs)), 2, 10), + withRetry(`${agentName} install`, () => wrapSshCall(runner.runServer(installCmd, timeoutSecs)), 4, 10, true), ); if (!r.ok) { logError(`${agentName} installation failed`); @@ -82,8 +82,9 @@ async function uploadConfigFile(runner: CloudRunner, content: string, remotePath ); })(), ), - 2, + 4, 5, + true, ), ); tryCatchIf(isOperationalError, () => unlinkSync(tmpFile)); diff --git a/packages/cli/src/shared/ui.ts b/packages/cli/src/shared/ui.ts index 2de35f68..cbcfa47f 100644 --- a/packages/cli/src/shared/ui.ts +++ b/packages/cli/src/shared/ui.ts @@ -213,6 +213,7 @@ export async function withRetry( fn: () => Promise>, maxAttempts = 3, delaySec = 5, + exponential = false, ): Promise { for (let attempt = 1; attempt <= maxAttempts; attempt++) { const result = await fn(); // throws → not retried (non-retryable) @@ -222,8 +223,9 @@ export async function withRetry( if (attempt >= maxAttempts) { throw result.error; } - logWarn(`${label} failed (attempt ${attempt}/${maxAttempts}), retrying in ${delaySec}s...`); - await new Promise((r) => setTimeout(r, delaySec * 1000)); + const delay = exponential ? delaySec * 2 ** (attempt - 1) : delaySec; + logWarn(`${label} failed (attempt ${attempt}/${maxAttempts}), retrying in ${delay}s...`); + await new Promise((r) => setTimeout(r, delay * 1000)); } throw new Error("unreachable"); }