From ef5d7cee22f2e6028cb23dbdf4fefab7b6127e2a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 19 Feb 2026 00:10:08 +0000 Subject: [PATCH] refactor(agents): share fallback failure summary builder --- src/agents/model-fallback.ts | 62 ++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index c04e1d6fd6..5356fb3cdc 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -96,6 +96,26 @@ type ModelFallbackRunResult = { attempts: FallbackAttempt[]; }; +function throwFallbackFailureSummary(params: { + attempts: FallbackAttempt[]; + candidates: ModelCandidate[]; + lastError: unknown; + label: string; + formatAttempt: (attempt: FallbackAttempt) => string; +}): never { + if (params.attempts.length <= 1 && params.lastError) { + throw params.lastError; + } + const summary = + params.attempts.length > 0 ? params.attempts.map(params.formatAttempt).join(" | ") : "unknown"; + throw new Error( + `All ${params.label} failed (${params.attempts.length || params.candidates.length}): ${summary}`, + { + cause: params.lastError instanceof Error ? params.lastError : undefined, + }, + ); +} + function resolveImageFallbackCandidates(params: { cfg: OpenClawConfig | undefined; defaultProvider: string; @@ -376,22 +396,15 @@ export async function runWithModelFallback(params: { } } - if (attempts.length <= 1 && lastError) { - throw lastError; - } - const summary = - attempts.length > 0 - ? attempts - .map( - (attempt) => - `${attempt.provider}/${attempt.model}: ${attempt.error}${ - attempt.reason ? ` (${attempt.reason})` : "" - }`, - ) - .join(" | ") - : "unknown"; - throw new Error(`All models failed (${attempts.length || candidates.length}): ${summary}`, { - cause: lastError instanceof Error ? lastError : undefined, + throwFallbackFailureSummary({ + attempts, + candidates, + lastError, + label: "models", + formatAttempt: (attempt) => + `${attempt.provider}/${attempt.model}: ${attempt.error}${ + attempt.reason ? ` (${attempt.reason})` : "" + }`, }); } @@ -445,16 +458,11 @@ export async function runWithImageModelFallback(params: { } } - if (attempts.length <= 1 && lastError) { - throw lastError; - } - const summary = - attempts.length > 0 - ? attempts - .map((attempt) => `${attempt.provider}/${attempt.model}: ${attempt.error}`) - .join(" | ") - : "unknown"; - throw new Error(`All image models failed (${attempts.length || candidates.length}): ${summary}`, { - cause: lastError instanceof Error ? lastError : undefined, + throwFallbackFailureSummary({ + attempts, + candidates, + lastError, + label: "image models", + formatAttempt: (attempt) => `${attempt.provider}/${attempt.model}: ${attempt.error}`, }); }